aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-01-02 19:18:08 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-01-02 19:18:08 +0000
commitbab175ec4b075c8076ba14c762900392533f6ee4 (patch)
tree01f4f29419a2cb10abe13c1e63cd2a66068b0137 /lib
parent8b7a8012d223fac5d17d16a66bb39168a9a1dfc0 (diff)
downloadsrc-bab175ec4b075c8076ba14c762900392533f6ee4.tar.gz
src-bab175ec4b075c8076ba14c762900392533f6ee4.zip
Vendor import of clang trunk r290819:vendor/clang/clang-trunk-r290819
Notes
Notes: svn path=/vendor/clang/dist/; revision=311118 svn path=/vendor/clang/clang-trunk-r290819/; revision=311119; tag=vendor/clang/clang-trunk-r290819
Diffstat (limited to 'lib')
-rw-r--r--lib/ARCMigrate/ARCMT.cpp1
-rw-r--r--lib/ARCMigrate/FileRemapper.cpp2
-rw-r--r--lib/ARCMigrate/Transforms.cpp5
-rw-r--r--lib/AST/APValue.cpp21
-rw-r--r--lib/AST/ASTContext.cpp619
-rw-r--r--lib/AST/ASTDiagnostic.cpp18
-rw-r--r--lib/AST/ASTDumper.cpp58
-rw-r--r--lib/AST/ASTImporter.cpp726
-rw-r--r--lib/AST/ASTTypeTraits.cpp5
-rw-r--r--lib/AST/AttrImpl.cpp3
-rw-r--r--lib/AST/CXXABI.h9
-rw-r--r--lib/AST/CXXInheritance.cpp1
-rw-r--r--lib/AST/Comment.cpp157
-rw-r--r--lib/AST/CommentBriefParser.cpp1
-rw-r--r--lib/AST/CommentLexer.cpp10
-rw-r--r--lib/AST/CommentParser.cpp2
-rw-r--r--lib/AST/CommentSema.cpp11
-rw-r--r--lib/AST/Decl.cpp164
-rw-r--r--lib/AST/DeclBase.cpp96
-rw-r--r--lib/AST/DeclCXX.cpp198
-rw-r--r--lib/AST/DeclGroup.cpp3
-rw-r--r--lib/AST/DeclObjC.cpp29
-rw-r--r--lib/AST/DeclOpenMP.cpp13
-rw-r--r--lib/AST/DeclPrinter.cpp237
-rw-r--r--lib/AST/DeclTemplate.cpp109
-rw-r--r--lib/AST/DeclarationName.cpp13
-rw-r--r--lib/AST/Expr.cpp185
-rw-r--r--lib/AST/ExprCXX.cpp101
-rw-r--r--lib/AST/ExprClassification.cpp21
-rw-r--r--lib/AST/ExprConstant.cpp1053
-rw-r--r--lib/AST/ExprObjC.cpp2
-rw-r--r--lib/AST/ItaniumCXXABI.cpp18
-rw-r--r--lib/AST/ItaniumMangle.cpp163
-rw-r--r--lib/AST/Mangle.cpp3
-rw-r--r--lib/AST/MicrosoftCXXABI.cpp17
-rw-r--r--lib/AST/MicrosoftMangle.cpp114
-rw-r--r--lib/AST/NestedNameSpecifier.cpp13
-rw-r--r--lib/AST/OpenMPClause.cpp127
-rw-r--r--lib/AST/RawCommentList.cpp9
-rw-r--r--lib/AST/Stmt.cpp30
-rw-r--r--lib/AST/StmtCXX.cpp4
-rw-r--r--lib/AST/StmtObjC.cpp4
-rw-r--r--lib/AST/StmtOpenMP.cpp609
-rw-r--r--lib/AST/StmtPrinter.cpp58
-rw-r--r--lib/AST/StmtProfile.cpp58
-rw-r--r--lib/AST/TemplateBase.cpp27
-rw-r--r--lib/AST/Type.cpp136
-rw-r--r--lib/AST/TypeLoc.cpp16
-rw-r--r--lib/AST/TypePrinter.cpp31
-rw-r--r--lib/AST/VTableBuilder.cpp230
-rw-r--r--lib/ASTMatchers/ASTMatchFinder.cpp38
-rw-r--r--lib/ASTMatchers/ASTMatchersInternal.cpp13
-rw-r--r--lib/ASTMatchers/Dynamic/Marshallers.h69
-rw-r--r--lib/ASTMatchers/Dynamic/Parser.cpp1
-rw-r--r--lib/ASTMatchers/Dynamic/Registry.cpp61
-rw-r--r--lib/Analysis/AnalysisDeclContext.cpp14
-rw-r--r--lib/Analysis/CFG.cpp50
-rw-r--r--lib/Analysis/CMakeLists.txt2
-rw-r--r--lib/Analysis/CallGraph.cpp18
-rw-r--r--lib/Analysis/CloneDetection.cpp894
-rw-r--r--lib/Analysis/Consumed.cpp5
-rw-r--r--lib/Analysis/FormatString.cpp27
-rw-r--r--lib/Analysis/FormatStringParsing.h1
-rw-r--r--lib/Analysis/LiveVariables.cpp27
-rw-r--r--lib/Analysis/OSLog.cpp202
-rw-r--r--lib/Analysis/PrintfFormatString.cpp43
-rw-r--r--lib/Analysis/ReachableCode.cpp2
-rw-r--r--lib/Analysis/ScanfFormatString.cpp6
-rw-r--r--lib/Analysis/ThreadSafety.cpp8
-rw-r--r--lib/Analysis/ThreadSafetyCommon.cpp9
-rw-r--r--lib/Analysis/UninitializedValues.cpp3
-rw-r--r--lib/Basic/CMakeLists.txt2
-rw-r--r--lib/Basic/Diagnostic.cpp21
-rw-r--r--lib/Basic/DiagnosticOptions.cpp2
-rw-r--r--lib/Basic/FileManager.cpp24
-rw-r--r--lib/Basic/FileSystemStatCache.cpp6
-rw-r--r--lib/Basic/IdentifierTable.cpp18
-rw-r--r--lib/Basic/LangOptions.cpp7
-rw-r--r--lib/Basic/Module.cpp11
-rw-r--r--lib/Basic/OpenMPKinds.cpp137
-rw-r--r--lib/Basic/SourceLocation.cpp1
-rw-r--r--lib/Basic/SourceManager.cpp40
-rw-r--r--lib/Basic/TargetInfo.cpp48
-rw-r--r--lib/Basic/Targets.cpp590
-rw-r--r--lib/Basic/Version.cpp2
-rw-r--r--lib/Basic/VirtualFileSystem.cpp134
-rw-r--r--lib/CodeGen/ABIInfo.h2
-rw-r--r--lib/CodeGen/BackendUtil.cpp390
-rw-r--r--lib/CodeGen/CGAtomic.cpp6
-rw-r--r--lib/CodeGen/CGBlocks.cpp152
-rw-r--r--lib/CodeGen/CGBlocks.h17
-rw-r--r--lib/CodeGen/CGBuilder.h18
-rw-r--r--lib/CodeGen/CGBuiltin.cpp1093
-rw-r--r--lib/CodeGen/CGCUDABuiltin.cpp6
-rw-r--r--lib/CodeGen/CGCUDANV.cpp92
-rw-r--r--lib/CodeGen/CGCUDARuntime.cpp11
-rw-r--r--lib/CodeGen/CGCXX.cpp67
-rw-r--r--lib/CodeGen/CGCXXABI.cpp5
-rw-r--r--lib/CodeGen/CGCXXABI.h13
-rw-r--r--lib/CodeGen/CGCall.cpp352
-rw-r--r--lib/CodeGen/CGCall.h143
-rw-r--r--lib/CodeGen/CGClass.cpp246
-rw-r--r--lib/CodeGen/CGCleanup.cpp2
-rw-r--r--lib/CodeGen/CGCleanup.h3
-rw-r--r--lib/CodeGen/CGCoroutine.cpp116
-rw-r--r--lib/CodeGen/CGDebugInfo.cpp593
-rw-r--r--lib/CodeGen/CGDebugInfo.h54
-rw-r--r--lib/CodeGen/CGDecl.cpp122
-rw-r--r--lib/CodeGen/CGDeclCXX.cpp9
-rw-r--r--lib/CodeGen/CGException.cpp14
-rw-r--r--lib/CodeGen/CGExpr.cpp383
-rw-r--r--lib/CodeGen/CGExprAgg.cpp115
-rw-r--r--lib/CodeGen/CGExprCXX.cpp684
-rw-r--r--lib/CodeGen/CGExprComplex.cpp11
-rw-r--r--lib/CodeGen/CGExprConstant.cpp99
-rw-r--r--lib/CodeGen/CGExprScalar.cpp149
-rw-r--r--lib/CodeGen/CGLoopInfo.cpp31
-rw-r--r--lib/CodeGen/CGLoopInfo.h11
-rw-r--r--lib/CodeGen/CGObjC.cpp49
-rw-r--r--lib/CodeGen/CGObjCGNU.cpp1059
-rw-r--r--lib/CodeGen/CGObjCMac.cpp2207
-rw-r--r--lib/CodeGen/CGObjCRuntime.cpp27
-rw-r--r--lib/CodeGen/CGObjCRuntime.h3
-rw-r--r--lib/CodeGen/CGOpenCLRuntime.cpp38
-rw-r--r--lib/CodeGen/CGOpenCLRuntime.h14
-rw-r--r--lib/CodeGen/CGOpenMPRuntime.cpp613
-rw-r--r--lib/CodeGen/CGOpenMPRuntime.h50
-rw-r--r--lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp5
-rw-r--r--lib/CodeGen/CGOpenMPRuntimeNVPTX.h7
-rw-r--r--lib/CodeGen/CGStmt.cpp64
-rw-r--r--lib/CodeGen/CGStmtOpenMP.cpp256
-rw-r--r--lib/CodeGen/CGVTT.cpp16
-rw-r--r--lib/CodeGen/CGVTables.cpp328
-rw-r--r--lib/CodeGen/CGVTables.h33
-rw-r--r--lib/CodeGen/CMakeLists.txt7
-rw-r--r--lib/CodeGen/CodeGenAction.cpp133
-rw-r--r--lib/CodeGen/CodeGenFunction.cpp143
-rw-r--r--lib/CodeGen/CodeGenFunction.h177
-rw-r--r--lib/CodeGen/CodeGenModule.cpp607
-rw-r--r--lib/CodeGen/CodeGenModule.h97
-rw-r--r--lib/CodeGen/CodeGenPGO.cpp4
-rw-r--r--lib/CodeGen/CodeGenPGO.h2
-rw-r--r--lib/CodeGen/CodeGenTypeCache.h5
-rw-r--r--lib/CodeGen/CodeGenTypes.cpp24
-rw-r--r--lib/CodeGen/CodeGenTypes.h10
-rw-r--r--lib/CodeGen/ConstantBuilder.h444
-rw-r--r--lib/CodeGen/CoverageMappingGen.cpp73
-rw-r--r--lib/CodeGen/CoverageMappingGen.h1
-rw-r--r--lib/CodeGen/EHScopeStack.h6
-rw-r--r--lib/CodeGen/ItaniumCXXABI.cpp293
-rw-r--r--lib/CodeGen/MicrosoftCXXABI.cpp314
-rw-r--r--lib/CodeGen/ModuleBuilder.cpp2
-rw-r--r--lib/CodeGen/ObjectFilePCHContainerOperations.cpp37
-rw-r--r--lib/CodeGen/SanitizerMetadata.cpp8
-rw-r--r--lib/CodeGen/SwiftCallingConv.cpp9
-rw-r--r--lib/CodeGen/TargetInfo.cpp488
-rw-r--r--lib/CodeGen/TargetInfo.h16
-rw-r--r--lib/CodeGen/VarBypassDetector.cpp168
-rw-r--r--lib/CodeGen/VarBypassDetector.h70
-rw-r--r--lib/Driver/Action.cpp57
-rw-r--r--lib/Driver/CMakeLists.txt1
-rw-r--r--lib/Driver/Compilation.cpp17
-rw-r--r--lib/Driver/CrossWindowsToolChain.cpp1
-rw-r--r--lib/Driver/Distro.cpp134
-rw-r--r--lib/Driver/Driver.cpp1921
-rw-r--r--lib/Driver/Job.cpp141
-rw-r--r--lib/Driver/MSVCToolChain.cpp105
-rw-r--r--lib/Driver/Multilib.cpp2
-rw-r--r--lib/Driver/SanitizerArgs.cpp67
-rw-r--r--lib/Driver/Tool.cpp10
-rw-r--r--lib/Driver/ToolChain.cpp194
-rw-r--r--lib/Driver/ToolChains.cpp1133
-rw-r--r--lib/Driver/ToolChains.h318
-rw-r--r--lib/Driver/Tools.cpp1755
-rw-r--r--lib/Driver/Tools.h46
-rw-r--r--lib/Driver/Types.cpp116
-rw-r--r--lib/Edit/RewriteObjCFoundationAPI.cpp2
-rw-r--r--lib/Format/BreakableToken.cpp16
-rw-r--r--lib/Format/CMakeLists.txt1
-rw-r--r--lib/Format/Comments.cpp36
-rw-r--r--lib/Format/Comments.h33
-rw-r--r--lib/Format/ContinuationIndenter.cpp14
-rw-r--r--lib/Format/Encoding.h29
-rw-r--r--lib/Format/Format.cpp498
-rw-r--r--lib/Format/FormatToken.cpp15
-rw-r--r--lib/Format/FormatToken.h19
-rw-r--r--lib/Format/FormatTokenLexer.cpp70
-rw-r--r--lib/Format/FormatTokenLexer.h21
-rw-r--r--lib/Format/SortJavaScriptImports.cpp62
-rw-r--r--lib/Format/TokenAnalyzer.cpp16
-rw-r--r--lib/Format/TokenAnalyzer.h7
-rw-r--r--lib/Format/TokenAnnotator.cpp197
-rw-r--r--lib/Format/TokenAnnotator.h1
-rw-r--r--lib/Format/UnwrappedLineFormatter.cpp3
-rw-r--r--lib/Format/UnwrappedLineFormatter.h2
-rw-r--r--lib/Format/UnwrappedLineParser.cpp46
-rw-r--r--lib/Format/WhitespaceManager.cpp15
-rw-r--r--lib/Format/WhitespaceManager.h3
-rw-r--r--lib/Frontend/ASTConsumers.cpp1
-rw-r--r--lib/Frontend/ASTUnit.cpp13
-rw-r--r--lib/Frontend/CacheTokens.cpp30
-rw-r--r--lib/Frontend/ChainedIncludesSource.cpp3
-rw-r--r--lib/Frontend/CompilerInstance.cpp228
-rw-r--r--lib/Frontend/CompilerInvocation.cpp211
-rw-r--r--lib/Frontend/DependencyFile.cpp19
-rw-r--r--lib/Frontend/DiagnosticRenderer.cpp2
-rw-r--r--lib/Frontend/FrontendAction.cpp12
-rw-r--r--lib/Frontend/FrontendActions.cpp116
-rw-r--r--lib/Frontend/FrontendOptions.cpp2
-rw-r--r--lib/Frontend/InitHeaderSearch.cpp7
-rw-r--r--lib/Frontend/InitPreprocessor.cpp82
-rw-r--r--lib/Frontend/ModuleDependencyCollector.cpp66
-rw-r--r--lib/Frontend/MultiplexConsumer.cpp6
-rw-r--r--lib/Frontend/PCHContainerOperations.cpp7
-rw-r--r--lib/Frontend/PrintPreprocessedOutput.cpp34
-rw-r--r--lib/Frontend/Rewrite/FrontendActions.cpp3
-rw-r--r--lib/Frontend/Rewrite/HTMLPrint.cpp5
-rw-r--r--lib/Frontend/Rewrite/InclusionRewriter.cpp6
-rw-r--r--lib/Frontend/Rewrite/RewriteModernObjC.cpp33
-rw-r--r--lib/Frontend/Rewrite/RewriteObjC.cpp36
-rw-r--r--lib/Frontend/Rewrite/RewriteTest.cpp4
-rw-r--r--lib/Frontend/SerializedDiagnosticPrinter.cpp5
-rw-r--r--lib/Frontend/SerializedDiagnosticReader.cpp17
-rw-r--r--lib/Frontend/TextDiagnostic.cpp37
-rw-r--r--lib/Frontend/TextDiagnosticPrinter.cpp2
-rw-r--r--lib/Frontend/VerifyDiagnosticConsumer.cpp3
-rw-r--r--lib/FrontendTool/ExecuteCompilerInvocation.cpp10
-rw-r--r--lib/Headers/CMakeLists.txt18
-rw-r--r--lib/Headers/__clang_cuda_builtin_vars.h (renamed from lib/Headers/cuda_builtin_vars.h)0
-rw-r--r--lib/Headers/__clang_cuda_cmath.h341
-rw-r--r--lib/Headers/__clang_cuda_complex_builtins.h203
-rw-r--r--lib/Headers/__clang_cuda_math_forward_declares.h25
-rw-r--r--lib/Headers/__clang_cuda_runtime_wrapper.h46
-rw-r--r--lib/Headers/__wmmintrin_aes.h12
-rw-r--r--lib/Headers/__wmmintrin_pclmul.h15
-rw-r--r--lib/Headers/altivec.h2274
-rw-r--r--lib/Headers/ammintrin.h77
-rw-r--r--lib/Headers/armintr.h45
-rw-r--r--lib/Headers/avx512bwintrin.h428
-rw-r--r--lib/Headers/avx512dqintrin.h437
-rw-r--r--lib/Headers/avx512fintrin.h2346
-rw-r--r--lib/Headers/avx512vlbwintrin.h1822
-rw-r--r--lib/Headers/avx512vldqintrin.h439
-rw-r--r--lib/Headers/avx512vlintrin.h2470
-rw-r--r--lib/Headers/avxintrin.h3096
-rw-r--r--lib/Headers/bmiintrin.h64
-rw-r--r--lib/Headers/cuda_wrappers/algorithm96
-rw-r--r--lib/Headers/cuda_wrappers/complex82
-rw-r--r--lib/Headers/cuda_wrappers/new47
-rw-r--r--lib/Headers/emmintrin.h2546
-rw-r--r--lib/Headers/f16cintrin.h28
-rw-r--r--lib/Headers/float.h7
-rw-r--r--lib/Headers/fxsrintrin.h62
-rw-r--r--lib/Headers/ia32intrin.h6
-rw-r--r--lib/Headers/immintrin.h35
-rw-r--r--lib/Headers/intrin.h682
-rw-r--r--lib/Headers/lzcntintrin.h50
-rw-r--r--lib/Headers/mmintrin.h174
-rw-r--r--lib/Headers/module.modulemap2
-rw-r--r--lib/Headers/opencl-c.h655
-rw-r--r--lib/Headers/pmmintrin.h53
-rw-r--r--lib/Headers/popcntintrin.h8
-rw-r--r--lib/Headers/stdatomic.h10
-rw-r--r--lib/Headers/tmmintrin.h42
-rw-r--r--lib/Headers/xmmintrin.h579
-rw-r--r--lib/Index/CommentToXML.cpp45
-rw-r--r--lib/Index/IndexBody.cpp45
-rw-r--r--lib/Index/IndexDecl.cpp46
-rw-r--r--lib/Index/IndexSymbol.cpp130
-rw-r--r--lib/Index/IndexingContext.cpp20
-rw-r--r--lib/Index/USRGeneration.cpp32
-rw-r--r--lib/Lex/HeaderMap.cpp2
-rw-r--r--lib/Lex/HeaderSearch.cpp128
-rw-r--r--lib/Lex/Lexer.cpp82
-rw-r--r--lib/Lex/LiteralSupport.cpp52
-rw-r--r--lib/Lex/MacroInfo.cpp2
-rw-r--r--lib/Lex/ModuleMap.cpp119
-rw-r--r--lib/Lex/PPCaching.cpp4
-rw-r--r--lib/Lex/PPDirectives.cpp87
-rw-r--r--lib/Lex/PPExpressions.cpp17
-rw-r--r--lib/Lex/PPLexerChange.cpp16
-rw-r--r--lib/Lex/PPMacroExpansion.cpp95
-rw-r--r--lib/Lex/PTHLexer.cpp17
-rw-r--r--lib/Lex/Pragma.cpp66
-rw-r--r--lib/Lex/PreprocessingRecord.cpp15
-rw-r--r--lib/Lex/Preprocessor.cpp73
-rw-r--r--lib/Lex/TokenConcatenation.cpp2
-rw-r--r--lib/Lex/TokenLexer.cpp11
-rw-r--r--lib/Parse/ParseAST.cpp22
-rw-r--r--lib/Parse/ParseCXXInlineMethods.cpp52
-rw-r--r--lib/Parse/ParseDecl.cpp211
-rw-r--r--lib/Parse/ParseDeclCXX.cpp539
-rw-r--r--lib/Parse/ParseExpr.cpp19
-rw-r--r--lib/Parse/ParseExprCXX.cpp168
-rw-r--r--lib/Parse/ParseInit.cpp3
-rw-r--r--lib/Parse/ParseObjc.cpp47
-rw-r--r--lib/Parse/ParseOpenMP.cpp58
-rw-r--r--lib/Parse/ParsePragma.cpp201
-rw-r--r--lib/Parse/ParseStmt.cpp10
-rw-r--r--lib/Parse/ParseStmtAsm.cpp6
-rw-r--r--lib/Parse/ParseTemplate.cpp12
-rw-r--r--lib/Parse/ParseTentative.cpp13
-rw-r--r--lib/Parse/Parser.cpp219
-rw-r--r--lib/Rewrite/HTMLRewrite.cpp19
-rw-r--r--lib/Sema/AnalysisBasedWarnings.cpp60
-rw-r--r--lib/Sema/AttributeList.cpp3
-rw-r--r--lib/Sema/CodeCompleteConsumer.cpp31
-rw-r--r--lib/Sema/DeclSpec.cpp95
-rw-r--r--lib/Sema/DelayedDiagnostic.cpp33
-rw-r--r--lib/Sema/JumpDiagnostics.cpp23
-rw-r--r--lib/Sema/MultiplexExternalSemaSource.cpp3
-rw-r--r--lib/Sema/ScopeInfo.cpp2
-rw-r--r--lib/Sema/Sema.cpp192
-rw-r--r--lib/Sema/SemaAttr.cpp2
-rw-r--r--lib/Sema/SemaCUDA.cpp520
-rw-r--r--lib/Sema/SemaCXXScopeSpec.cpp133
-rw-r--r--lib/Sema/SemaCast.cpp50
-rw-r--r--lib/Sema/SemaChecking.cpp1250
-rw-r--r--lib/Sema/SemaCodeComplete.cpp397
-rw-r--r--lib/Sema/SemaCoroutine.cpp373
-rw-r--r--lib/Sema/SemaDecl.cpp1311
-rw-r--r--lib/Sema/SemaDeclAttr.cpp626
-rw-r--r--lib/Sema/SemaDeclCXX.cpp1223
-rw-r--r--lib/Sema/SemaDeclObjC.cpp49
-rw-r--r--lib/Sema/SemaExceptionSpec.cpp240
-rw-r--r--lib/Sema/SemaExpr.cpp885
-rw-r--r--lib/Sema/SemaExprCXX.cpp1908
-rw-r--r--lib/Sema/SemaExprMember.cpp111
-rw-r--r--lib/Sema/SemaExprObjC.cpp22
-rw-r--r--lib/Sema/SemaInit.cpp1192
-rw-r--r--lib/Sema/SemaLambda.cpp125
-rw-r--r--lib/Sema/SemaLookup.cpp38
-rw-r--r--lib/Sema/SemaObjCProperty.cpp48
-rw-r--r--lib/Sema/SemaOpenMP.cpp2179
-rw-r--r--lib/Sema/SemaOverload.cpp548
-rw-r--r--lib/Sema/SemaPseudoObject.cpp14
-rw-r--r--lib/Sema/SemaStmt.cpp26
-rw-r--r--lib/Sema/SemaStmtAsm.cpp81
-rw-r--r--lib/Sema/SemaStmtAttr.cpp10
-rw-r--r--lib/Sema/SemaTemplate.cpp957
-rw-r--r--lib/Sema/SemaTemplateDeduction.cpp1669
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp144
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp457
-rw-r--r--lib/Sema/SemaTemplateVariadic.cpp84
-rw-r--r--lib/Sema/SemaType.cpp693
-rw-r--r--lib/Sema/TreeTransform.h423
-rw-r--r--lib/Sema/TypeLocBuilder.h2
-rw-r--r--lib/Serialization/ASTCommon.cpp5
-rw-r--r--lib/Serialization/ASTCommon.h1
-rw-r--r--lib/Serialization/ASTReader.cpp1067
-rw-r--r--lib/Serialization/ASTReaderDecl.cpp1427
-rw-r--r--lib/Serialization/ASTReaderInternals.h17
-rw-r--r--lib/Serialization/ASTReaderStmt.cpp2196
-rw-r--r--lib/Serialization/ASTWriter.cpp297
-rw-r--r--lib/Serialization/ASTWriterDecl.cpp75
-rw-r--r--lib/Serialization/ASTWriterStmt.cpp109
-rw-r--r--lib/Serialization/GeneratePCH.cpp27
-rw-r--r--lib/Serialization/GlobalModuleIndex.cpp12
-rw-r--r--lib/Serialization/Module.cpp1
-rw-r--r--lib/Serialization/ModuleFileExtension.cpp1
-rw-r--r--lib/Serialization/ModuleManager.cpp101
-rw-r--r--lib/Serialization/MultiOnDiskHashTable.h4
-rw-r--r--lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp68
-rw-r--r--lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp92
-rw-r--r--lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp77
-rw-r--r--lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp109
-rw-r--r--lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp1
-rw-r--r--lib/StaticAnalyzer/Checkers/CMakeLists.txt11
-rw-r--r--lib/StaticAnalyzer/Checkers/CStringChecker.cpp8
-rw-r--r--lib/StaticAnalyzer/Checkers/CXXSelfAssignmentChecker.cpp62
-rw-r--r--lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp21
-rw-r--r--lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp7
-rw-r--r--lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp87
-rw-r--r--lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp33
-rw-r--r--lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp1
-rw-r--r--lib/StaticAnalyzer/Checkers/ChrootChecker.cpp1
-rw-r--r--lib/StaticAnalyzer/Checkers/CloneChecker.cpp161
-rw-r--r--lib/StaticAnalyzer/Checkers/ConversionChecker.cpp192
-rw-r--r--lib/StaticAnalyzer/Checkers/DynamicTypeChecker.cpp7
-rw-r--r--lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp40
-rw-r--r--lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp105
-rw-r--r--lib/StaticAnalyzer/Checkers/GTestChecker.cpp299
-rw-r--r--lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp44
-rw-r--r--lib/StaticAnalyzer/Checkers/MPI-Checker/MPIBugReporter.h4
-rw-r--r--lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.cpp9
-rw-r--r--lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.h12
-rw-r--r--lib/StaticAnalyzer/Checkers/MPI-Checker/MPIFunctionClassifier.cpp2
-rw-r--r--lib/StaticAnalyzer/Checkers/MPI-Checker/MPIFunctionClassifier.h97
-rw-r--r--lib/StaticAnalyzer/Checkers/MPI-Checker/MPITypes.h3
-rw-r--r--lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp7
-rw-r--r--lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp73
-rw-r--r--lib/StaticAnalyzer/Checkers/MallocChecker.cpp87
-rw-r--r--lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp29
-rw-r--r--lib/StaticAnalyzer/Checkers/NumberObjectConversionChecker.cpp348
-rw-r--r--lib/StaticAnalyzer/Checkers/ObjCPropertyChecker.cpp82
-rw-r--r--lib/StaticAnalyzer/Checkers/ObjCSuperDeallocChecker.cpp2
-rw-r--r--lib/StaticAnalyzer/Checkers/PaddingChecker.cpp58
-rw-r--r--lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp1
-rw-r--r--lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp1
-rw-r--r--lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp82
-rw-r--r--lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp1055
-rw-r--r--lib/StaticAnalyzer/Checkers/StreamChecker.cpp1
-rw-r--r--lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp105
-rw-r--r--lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp14
-rw-r--r--lib/StaticAnalyzer/Checkers/ValistChecker.cpp373
-rw-r--r--lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp121
-rw-r--r--lib/StaticAnalyzer/Core/AnalyzerOptions.cpp26
-rw-r--r--lib/StaticAnalyzer/Core/BasicValueFactory.cpp50
-rw-r--r--lib/StaticAnalyzer/Core/BugReporter.cpp107
-rw-r--r--lib/StaticAnalyzer/Core/BugReporterVisitors.cpp197
-rw-r--r--lib/StaticAnalyzer/Core/CallEvent.cpp7
-rw-r--r--lib/StaticAnalyzer/Core/CheckerManager.cpp19
-rw-r--r--lib/StaticAnalyzer/Core/CheckerRegistry.cpp19
-rw-r--r--lib/StaticAnalyzer/Core/CoreEngine.cpp23
-rw-r--r--lib/StaticAnalyzer/Core/ExplodedGraph.cpp2
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngine.cpp227
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngineC.cpp222
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngineCXX.cpp30
-rw-r--r--lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp88
-rw-r--r--lib/StaticAnalyzer/Core/IssueHash.cpp1
-rw-r--r--lib/StaticAnalyzer/Core/MemRegion.cpp42
-rw-r--r--lib/StaticAnalyzer/Core/PathDiagnostic.cpp39
-rw-r--r--lib/StaticAnalyzer/Core/PlistDiagnostics.cpp56
-rw-r--r--lib/StaticAnalyzer/Core/ProgramState.cpp33
-rw-r--r--lib/StaticAnalyzer/Core/RangeConstraintManager.cpp202
-rw-r--r--lib/StaticAnalyzer/Core/RegionStore.cpp9
-rw-r--r--lib/StaticAnalyzer/Core/SValBuilder.cpp12
-rw-r--r--lib/StaticAnalyzer/Core/SVals.cpp53
-rw-r--r--lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp153
-rw-r--r--lib/StaticAnalyzer/Core/SimpleConstraintManager.h80
-rw-r--r--lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp41
-rw-r--r--lib/StaticAnalyzer/Core/Store.cpp2
-rw-r--r--lib/StaticAnalyzer/Core/SymbolManager.cpp10
-rw-r--r--lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp138
-rw-r--r--lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp25
-rw-r--r--lib/StaticAnalyzer/Frontend/ModelInjector.cpp1
-rw-r--r--lib/StaticAnalyzer/Frontend/ModelInjector.h4
-rw-r--r--lib/Tooling/ArgumentsAdjusters.cpp2
-rw-r--r--lib/Tooling/CMakeLists.txt8
-rw-r--r--lib/Tooling/CompilationDatabase.cpp8
-rw-r--r--lib/Tooling/Core/Lookup.cpp94
-rw-r--r--lib/Tooling/Core/QualTypeNames.cpp2
-rw-r--r--lib/Tooling/Core/Replacement.cpp501
-rw-r--r--lib/Tooling/JSONCompilationDatabase.cpp60
-rw-r--r--lib/Tooling/Refactoring.cpp23
-rw-r--r--lib/Tooling/RefactoringCallbacks.cpp50
-rw-r--r--lib/Tooling/Tooling.cpp10
447 files changed, 56519 insertions, 24864 deletions
diff --git a/lib/ARCMigrate/ARCMT.cpp b/lib/ARCMigrate/ARCMT.cpp
index da93d8418e78..680aa3e48da4 100644
--- a/lib/ARCMigrate/ARCMT.cpp
+++ b/lib/ARCMigrate/ARCMT.cpp
@@ -16,6 +16,7 @@
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "clang/Frontend/Utils.h"
#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/PreprocessorOptions.h"
#include "clang/Rewrite/Core/Rewriter.h"
#include "clang/Sema/SemaDiagnostic.h"
#include "clang/Serialization/ASTReader.h"
diff --git a/lib/ARCMigrate/FileRemapper.cpp b/lib/ARCMigrate/FileRemapper.cpp
index 2cf20699aeef..4dedac88f982 100644
--- a/lib/ARCMigrate/FileRemapper.cpp
+++ b/lib/ARCMigrate/FileRemapper.cpp
@@ -64,7 +64,7 @@ bool FileRemapper::initFromFile(StringRef filePath, DiagnosticsEngine &Diag,
std::vector<std::pair<const FileEntry *, const FileEntry *> > pairs;
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> fileBuf =
- llvm::MemoryBuffer::getFile(infoFile.c_str());
+ llvm::MemoryBuffer::getFile(infoFile);
if (!fileBuf)
return report("Error opening file: " + infoFile, Diag);
diff --git a/lib/ARCMigrate/Transforms.cpp b/lib/ARCMigrate/Transforms.cpp
index 3fd36ff310f3..cb96a547fbac 100644
--- a/lib/ARCMigrate/Transforms.cpp
+++ b/lib/ARCMigrate/Transforms.cpp
@@ -11,17 +11,12 @@
#include "Internals.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/RecursiveASTVisitor.h"
-#include "clang/AST/StmtVisitor.h"
#include "clang/Analysis/DomainSpecific/CocoaConventions.h"
#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"
-#include "llvm/ADT/StringSwitch.h"
-#include <map>
using namespace clang;
using namespace arcmt;
diff --git a/lib/AST/APValue.cpp b/lib/AST/APValue.cpp
index 3c587331ed07..488ad3373ca3 100644
--- a/lib/AST/APValue.cpp
+++ b/lib/AST/APValue.cpp
@@ -17,8 +17,6 @@
#include "clang/AST/DeclCXX.h"
#include "clang/AST/Expr.h"
#include "clang/AST/Type.h"
-#include "clang/Basic/Diagnostic.h"
-#include "llvm/ADT/SmallString.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
@@ -29,6 +27,7 @@ namespace {
CharUnits Offset;
unsigned PathLength;
unsigned CallIndex;
+ bool IsNullPtr;
};
}
@@ -151,10 +150,11 @@ APValue::APValue(const APValue &RHS) : Kind(Uninitialized) {
MakeLValue();
if (RHS.hasLValuePath())
setLValue(RHS.getLValueBase(), RHS.getLValueOffset(), RHS.getLValuePath(),
- RHS.isLValueOnePastTheEnd(), RHS.getLValueCallIndex());
+ RHS.isLValueOnePastTheEnd(), RHS.getLValueCallIndex(),
+ RHS.isNullPointer());
else
setLValue(RHS.getLValueBase(), RHS.getLValueOffset(), NoLValuePath(),
- RHS.getLValueCallIndex());
+ RHS.getLValueCallIndex(), RHS.isNullPointer());
break;
case Array:
MakeArray(RHS.getArrayInitializedElts(), RHS.getArraySize());
@@ -263,7 +263,7 @@ LLVM_DUMP_METHOD void APValue::dump() const {
static double GetApproxValue(const llvm::APFloat &F) {
llvm::APFloat V = F;
bool ignored;
- V.convert(llvm::APFloat::IEEEdouble, llvm::APFloat::rmNearestTiesToEven,
+ V.convert(llvm::APFloat::IEEEdouble(), llvm::APFloat::rmNearestTiesToEven,
&ignored);
return V.convertToDouble();
}
@@ -581,8 +581,13 @@ unsigned APValue::getLValueCallIndex() const {
return ((const LV*)(const char*)Data.buffer)->CallIndex;
}
+bool APValue::isNullPointer() const {
+ assert(isLValue() && "Invalid usage");
+ return ((const LV*)(const char*)Data.buffer)->IsNullPtr;
+}
+
void APValue::setLValue(LValueBase B, const CharUnits &O, NoLValuePath,
- unsigned CallIndex) {
+ unsigned CallIndex, bool IsNullPtr) {
assert(isLValue() && "Invalid accessor");
LV &LVal = *((LV*)(char*)Data.buffer);
LVal.BaseAndIsOnePastTheEnd.setPointer(B);
@@ -590,11 +595,12 @@ void APValue::setLValue(LValueBase B, const CharUnits &O, NoLValuePath,
LVal.Offset = O;
LVal.CallIndex = CallIndex;
LVal.resizePath((unsigned)-1);
+ LVal.IsNullPtr = IsNullPtr;
}
void APValue::setLValue(LValueBase B, const CharUnits &O,
ArrayRef<LValuePathEntry> Path, bool IsOnePastTheEnd,
- unsigned CallIndex) {
+ unsigned CallIndex, bool IsNullPtr) {
assert(isLValue() && "Invalid accessor");
LV &LVal = *((LV*)(char*)Data.buffer);
LVal.BaseAndIsOnePastTheEnd.setPointer(B);
@@ -603,6 +609,7 @@ void APValue::setLValue(LValueBase B, const CharUnits &O,
LVal.CallIndex = CallIndex;
LVal.resizePath(Path.size());
memcpy(LVal.getPath(), Path.data(), Path.size() * sizeof(LValuePathEntry));
+ LVal.IsNullPtr = IsNullPtr;
}
const ValueDecl *APValue::getMemberPointerDecl() const {
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 6aad4d1d570b..1b5988d01988 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -34,7 +34,6 @@
#include "clang/Basic/Builtins.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
-#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Support/Capacity.h"
@@ -652,6 +651,10 @@ ASTContext::getCanonicalTemplateTemplateParmDecl(
cast<TemplateTemplateParmDecl>(*P)));
}
+ assert(!TTP->getRequiresClause() &&
+ "Unexpected requires-clause on template template-parameter");
+ Expr *const CanonRequiresClause = nullptr;
+
TemplateTemplateParmDecl *CanonTTP
= TemplateTemplateParmDecl::Create(*this, getTranslationUnitDecl(),
SourceLocation(), TTP->getDepth(),
@@ -661,7 +664,8 @@ ASTContext::getCanonicalTemplateTemplateParmDecl(
TemplateParameterList::Create(*this, SourceLocation(),
SourceLocation(),
CanonParams,
- SourceLocation()));
+ SourceLocation(),
+ CanonRequiresClause));
// Get the new insert position for the node we care about.
Canonical = CanonTemplateTemplateParms.FindNodeOrInsertPos(ID, InsertPos);
@@ -700,8 +704,8 @@ static const LangAS::Map *getAddressSpaceMap(const TargetInfo &T,
// language-specific address space.
static const unsigned FakeAddrSpaceMap[] = {
1, // opencl_global
- 2, // opencl_local
- 3, // opencl_constant
+ 3, // opencl_local
+ 2, // opencl_constant
4, // opencl_generic
5, // cuda_device
6, // cuda_constant
@@ -788,7 +792,8 @@ ASTContext::~ASTContext() {
MaterializedTemporaryValues)
MTVPair.second->~APValue();
- llvm::DeleteContainerSeconds(MangleNumberingContexts);
+ for (const auto &Value : ModuleInitializers)
+ Value.second->~PerModuleInitializers();
}
void ASTContext::ReleaseParentMapEntries() {
@@ -902,6 +907,67 @@ void ASTContext::deduplicateMergedDefinitonsFor(NamedDecl *ND) {
Merged.erase(std::remove(Merged.begin(), Merged.end(), nullptr), Merged.end());
}
+void ASTContext::PerModuleInitializers::resolve(ASTContext &Ctx) {
+ if (LazyInitializers.empty())
+ return;
+
+ auto *Source = Ctx.getExternalSource();
+ assert(Source && "lazy initializers but no external source");
+
+ auto LazyInits = std::move(LazyInitializers);
+ LazyInitializers.clear();
+
+ for (auto ID : LazyInits)
+ Initializers.push_back(Source->GetExternalDecl(ID));
+
+ assert(LazyInitializers.empty() &&
+ "GetExternalDecl for lazy module initializer added more inits");
+}
+
+void ASTContext::addModuleInitializer(Module *M, Decl *D) {
+ // One special case: if we add a module initializer that imports another
+ // module, and that module's only initializer is an ImportDecl, simplify.
+ if (auto *ID = dyn_cast<ImportDecl>(D)) {
+ auto It = ModuleInitializers.find(ID->getImportedModule());
+
+ // Maybe the ImportDecl does nothing at all. (Common case.)
+ if (It == ModuleInitializers.end())
+ return;
+
+ // Maybe the ImportDecl only imports another ImportDecl.
+ auto &Imported = *It->second;
+ if (Imported.Initializers.size() + Imported.LazyInitializers.size() == 1) {
+ Imported.resolve(*this);
+ auto *OnlyDecl = Imported.Initializers.front();
+ if (isa<ImportDecl>(OnlyDecl))
+ D = OnlyDecl;
+ }
+ }
+
+ auto *&Inits = ModuleInitializers[M];
+ if (!Inits)
+ Inits = new (*this) PerModuleInitializers;
+ Inits->Initializers.push_back(D);
+}
+
+void ASTContext::addLazyModuleInitializers(Module *M, ArrayRef<uint32_t> IDs) {
+ auto *&Inits = ModuleInitializers[M];
+ if (!Inits)
+ Inits = new (*this) PerModuleInitializers;
+ Inits->LazyInitializers.insert(Inits->LazyInitializers.end(),
+ IDs.begin(), IDs.end());
+}
+
+ArrayRef<Decl*> ASTContext::getModuleInitializers(Module *M) {
+ auto It = ModuleInitializers.find(M);
+ if (It == ModuleInitializers.end())
+ return None;
+
+ auto *Inits = It->second;
+ Inits->resolve(*this);
+ return Inits->Initializers;
+}
+
ExternCContextDecl *ASTContext::getExternCContextDecl() const {
if (!ExternCContext)
ExternCContext = ExternCContextDecl::Create(*this, getTranslationUnitDecl());
@@ -1204,9 +1270,8 @@ void ASTContext::setClassScopeSpecializationPattern(FunctionDecl *FD,
}
NamedDecl *
-ASTContext::getInstantiatedFromUsingDecl(UsingDecl *UUD) {
- llvm::DenseMap<UsingDecl *, NamedDecl *>::const_iterator Pos
- = InstantiatedFromUsingDecl.find(UUD);
+ASTContext::getInstantiatedFromUsingDecl(NamedDecl *UUD) {
+ auto Pos = InstantiatedFromUsingDecl.find(UUD);
if (Pos == InstantiatedFromUsingDecl.end())
return nullptr;
@@ -1214,11 +1279,15 @@ ASTContext::getInstantiatedFromUsingDecl(UsingDecl *UUD) {
}
void
-ASTContext::setInstantiatedFromUsingDecl(UsingDecl *Inst, NamedDecl *Pattern) {
+ASTContext::setInstantiatedFromUsingDecl(NamedDecl *Inst, NamedDecl *Pattern) {
assert((isa<UsingDecl>(Pattern) ||
isa<UnresolvedUsingValueDecl>(Pattern) ||
isa<UnresolvedUsingTypenameDecl>(Pattern)) &&
"pattern decl is not a using decl");
+ assert((isa<UsingDecl>(Inst) ||
+ isa<UnresolvedUsingValueDecl>(Inst) ||
+ isa<UnresolvedUsingTypenameDecl>(Inst)) &&
+ "instantiation did not produce a using decl");
assert(!InstantiatedFromUsingDecl[Inst] && "pattern already exists");
InstantiatedFromUsingDecl[Inst] = Pattern;
}
@@ -1504,6 +1573,30 @@ bool ASTContext::isAlignmentRequired(QualType T) const {
return isAlignmentRequired(T.getTypePtr());
}
+unsigned ASTContext::getTypeAlignIfKnown(QualType T) const {
+ // An alignment on a typedef overrides anything else.
+ if (auto *TT = T->getAs<TypedefType>())
+ if (unsigned Align = TT->getDecl()->getMaxAlignment())
+ return Align;
+
+ // If we have an (array of) complete type, we're done.
+ T = getBaseElementType(T);
+ if (!T->isIncompleteType())
+ return getTypeAlign(T);
+
+ // If we had an array type, its element type might be a typedef
+ // type with an alignment attribute.
+ if (auto *TT = T->getAs<TypedefType>())
+ if (unsigned Align = TT->getDecl()->getMaxAlignment())
+ return Align;
+
+ // Otherwise, see if the declaration of the type had an attribute.
+ if (auto *TT = T->getAs<TagType>())
+ return TT->getDecl()->getMaxAlignment();
+
+ return 0;
+}
+
TypeInfo ASTContext::getTypeInfo(const Type *T) const {
TypeInfoMap::iterator I = MemoizedTypeInfo.find(T);
if (I != MemoizedTypeInfo.end())
@@ -1671,24 +1764,29 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
Width = Target->getPointerWidth(0);
Align = Target->getPointerAlign(0);
break;
- case BuiltinType::OCLSampler:
- // Samplers are modeled as integers.
- Width = Target->getIntWidth();
- Align = Target->getIntAlign();
+ case BuiltinType::OCLSampler: {
+ auto AS = getTargetAddressSpace(LangAS::opencl_constant);
+ Width = Target->getPointerWidth(AS);
+ Align = Target->getPointerAlign(AS);
break;
+ }
case BuiltinType::OCLEvent:
case BuiltinType::OCLClkEvent:
case BuiltinType::OCLQueue:
case BuiltinType::OCLNDRange:
case BuiltinType::OCLReserveID:
-#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
- case BuiltinType::Id:
-#include "clang/Basic/OpenCLImageTypes.def"
-
// Currently these types are pointers to opaque types.
Width = Target->getPointerWidth(0);
Align = Target->getPointerAlign(0);
break;
+#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
+ case BuiltinType::Id:
+#include "clang/Basic/OpenCLImageTypes.def"
+ {
+ auto AS = getTargetAddressSpace(Target->getOpenCLImageAddrSpace());
+ Width = Target->getPointerWidth(AS);
+ Align = Target->getPointerAlign(AS);
+ }
}
break;
case Type::ObjCObjectPointer:
@@ -1787,6 +1885,9 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
case Type::Paren:
return getTypeInfo(cast<ParenType>(T)->getInnerType().getTypePtr());
+ case Type::ObjCTypeParam:
+ return getTypeInfo(cast<ObjCTypeParamType>(T)->desugar().getTypePtr());
+
case Type::Typedef: {
const TypedefNameDecl *Typedef = cast<TypedefType>(T)->getDecl();
TypeInfo Info = getTypeInfo(Typedef->getUnderlyingType().getTypePtr());
@@ -2284,6 +2385,14 @@ static QualType getFunctionTypeWithExceptionSpec(
Proto->getExtProtoInfo().withExceptionSpec(ESI));
}
+bool ASTContext::hasSameFunctionTypeIgnoringExceptionSpec(QualType T,
+ QualType U) {
+ return hasSameType(T, U) ||
+ (getLangOpts().CPlusPlus1z &&
+ hasSameType(getFunctionTypeWithExceptionSpec(*this, T, EST_None),
+ getFunctionTypeWithExceptionSpec(*this, U, EST_None)));
+}
+
void ASTContext::adjustExceptionSpec(
FunctionDecl *FD, const FunctionProtoType::ExceptionSpecInfo &ESI,
bool AsWritten) {
@@ -3039,46 +3148,160 @@ ASTContext::getCanonicalFunctionResultType(QualType ResultType) const {
return CanResultType;
}
-QualType
-ASTContext::getFunctionType(QualType ResultTy, ArrayRef<QualType> ArgArray,
- const FunctionProtoType::ExtProtoInfo &EPI) const {
+static bool isCanonicalExceptionSpecification(
+ const FunctionProtoType::ExceptionSpecInfo &ESI, bool NoexceptInType) {
+ if (ESI.Type == EST_None)
+ return true;
+ if (!NoexceptInType)
+ return false;
+
+ // C++17 onwards: exception specification is part of the type, as a simple
+ // boolean "can this function type throw".
+ if (ESI.Type == EST_BasicNoexcept)
+ return true;
+
+ // A dynamic exception specification is canonical if it only contains pack
+ // expansions (so we can't tell whether it's non-throwing) and all its
+ // contained types are canonical.
+ if (ESI.Type == EST_Dynamic) {
+ bool AnyPackExpansions = false;
+ for (QualType ET : ESI.Exceptions) {
+ if (!ET.isCanonical())
+ return false;
+ if (ET->getAs<PackExpansionType>())
+ AnyPackExpansions = true;
+ }
+ return AnyPackExpansions;
+ }
+
+ // A noexcept(expr) specification is (possibly) canonical if expr is
+ // value-dependent.
+ if (ESI.Type == EST_ComputedNoexcept)
+ return ESI.NoexceptExpr && ESI.NoexceptExpr->isValueDependent();
+
+ return false;
+}
+
+QualType ASTContext::getFunctionTypeInternal(
+ QualType ResultTy, ArrayRef<QualType> ArgArray,
+ const FunctionProtoType::ExtProtoInfo &EPI, bool OnlyWantCanonical) const {
size_t NumArgs = ArgArray.size();
// Unique functions, to guarantee there is only one function of a particular
// structure.
llvm::FoldingSetNodeID ID;
FunctionProtoType::Profile(ID, ResultTy, ArgArray.begin(), NumArgs, EPI,
- *this);
+ *this, true);
+
+ QualType Canonical;
+ bool Unique = false;
void *InsertPos = nullptr;
- if (FunctionProtoType *FTP =
- FunctionProtoTypes.FindNodeOrInsertPos(ID, InsertPos))
- return QualType(FTP, 0);
+ if (FunctionProtoType *FPT =
+ FunctionProtoTypes.FindNodeOrInsertPos(ID, InsertPos)) {
+ QualType Existing = QualType(FPT, 0);
+
+ // If we find a pre-existing equivalent FunctionProtoType, we can just reuse
+ // it so long as our exception specification doesn't contain a dependent
+ // noexcept expression, or we're just looking for a canonical type.
+ // Otherwise, we're going to need to create a type
+ // sugar node to hold the concrete expression.
+ if (OnlyWantCanonical || EPI.ExceptionSpec.Type != EST_ComputedNoexcept ||
+ EPI.ExceptionSpec.NoexceptExpr == FPT->getNoexceptExpr())
+ return Existing;
+
+ // We need a new type sugar node for this one, to hold the new noexcept
+ // expression. We do no canonicalization here, but that's OK since we don't
+ // expect to see the same noexcept expression much more than once.
+ Canonical = getCanonicalType(Existing);
+ Unique = true;
+ }
+
+ bool NoexceptInType = getLangOpts().CPlusPlus1z;
+ bool IsCanonicalExceptionSpec =
+ isCanonicalExceptionSpecification(EPI.ExceptionSpec, NoexceptInType);
// Determine whether the type being created is already canonical or not.
- bool isCanonical =
- EPI.ExceptionSpec.Type == EST_None && isCanonicalResultType(ResultTy) &&
- !EPI.HasTrailingReturn;
+ bool isCanonical = !Unique && IsCanonicalExceptionSpec &&
+ isCanonicalResultType(ResultTy) && !EPI.HasTrailingReturn;
for (unsigned i = 0; i != NumArgs && isCanonical; ++i)
if (!ArgArray[i].isCanonicalAsParam())
isCanonical = false;
- // If this type isn't canonical, get the canonical version of it.
- // The exception spec is not part of the canonical type.
- QualType Canonical;
- if (!isCanonical) {
+ if (OnlyWantCanonical)
+ assert(isCanonical &&
+ "given non-canonical parameters constructing canonical type");
+
+ // If this type isn't canonical, get the canonical version of it if we don't
+ // already have it. The exception spec is only partially part of the
+ // canonical type, and only in C++17 onwards.
+ if (!isCanonical && Canonical.isNull()) {
SmallVector<QualType, 16> CanonicalArgs;
CanonicalArgs.reserve(NumArgs);
for (unsigned i = 0; i != NumArgs; ++i)
CanonicalArgs.push_back(getCanonicalParamType(ArgArray[i]));
+ llvm::SmallVector<QualType, 8> ExceptionTypeStorage;
FunctionProtoType::ExtProtoInfo CanonicalEPI = EPI;
CanonicalEPI.HasTrailingReturn = false;
- CanonicalEPI.ExceptionSpec = FunctionProtoType::ExceptionSpecInfo();
+
+ if (IsCanonicalExceptionSpec) {
+ // Exception spec is already OK.
+ } else if (NoexceptInType) {
+ switch (EPI.ExceptionSpec.Type) {
+ case EST_Unparsed: case EST_Unevaluated: case EST_Uninstantiated:
+ // We don't know yet. It shouldn't matter what we pick here; no-one
+ // should ever look at this.
+ LLVM_FALLTHROUGH;
+ case EST_None: case EST_MSAny:
+ CanonicalEPI.ExceptionSpec.Type = EST_None;
+ break;
+
+ // A dynamic exception specification is almost always "not noexcept",
+ // with the exception that a pack expansion might expand to no types.
+ case EST_Dynamic: {
+ bool AnyPacks = false;
+ for (QualType ET : EPI.ExceptionSpec.Exceptions) {
+ if (ET->getAs<PackExpansionType>())
+ AnyPacks = true;
+ ExceptionTypeStorage.push_back(getCanonicalType(ET));
+ }
+ if (!AnyPacks)
+ CanonicalEPI.ExceptionSpec.Type = EST_None;
+ else {
+ CanonicalEPI.ExceptionSpec.Type = EST_Dynamic;
+ CanonicalEPI.ExceptionSpec.Exceptions = ExceptionTypeStorage;
+ }
+ break;
+ }
+
+ case EST_DynamicNone: case EST_BasicNoexcept:
+ CanonicalEPI.ExceptionSpec.Type = EST_BasicNoexcept;
+ break;
+
+ case EST_ComputedNoexcept:
+ llvm::APSInt Value(1);
+ auto *E = CanonicalEPI.ExceptionSpec.NoexceptExpr;
+ if (!E || !E->isIntegerConstantExpr(Value, *this, nullptr,
+ /*IsEvaluated*/false)) {
+ // This noexcept specification is invalid.
+ // FIXME: Should this be able to happen?
+ CanonicalEPI.ExceptionSpec.Type = EST_None;
+ break;
+ }
+
+ CanonicalEPI.ExceptionSpec.Type =
+ Value.getBoolValue() ? EST_BasicNoexcept : EST_None;
+ break;
+ }
+ } else {
+ CanonicalEPI.ExceptionSpec = FunctionProtoType::ExceptionSpecInfo();
+ }
// Adjust the canonical function result type.
CanQualType CanResultTy = getCanonicalFunctionResultType(ResultTy);
- Canonical = getFunctionType(CanResultTy, CanonicalArgs, CanonicalEPI);
+ Canonical =
+ getFunctionTypeInternal(CanResultTy, CanonicalArgs, CanonicalEPI, true);
// Get the new insert position for the node we care about.
FunctionProtoType *NewIP =
@@ -3121,14 +3344,14 @@ ASTContext::getFunctionType(QualType ResultTy, ArrayRef<QualType> ArgArray,
FunctionProtoType::ExtProtoInfo newEPI = EPI;
new (FTP) FunctionProtoType(ResultTy, ArgArray, Canonical, newEPI);
Types.push_back(FTP);
- FunctionProtoTypes.InsertNode(FTP, InsertPos);
+ if (!Unique)
+ FunctionProtoTypes.InsertNode(FTP, InsertPos);
return QualType(FTP, 0);
}
-/// Return pipe type for the specified type.
-QualType ASTContext::getPipeType(QualType T) const {
+QualType ASTContext::getPipeType(QualType T, bool ReadOnly) const {
llvm::FoldingSetNodeID ID;
- PipeType::Profile(ID, T);
+ PipeType::Profile(ID, T, ReadOnly);
void *InsertPos = 0;
if (PipeType *PT = PipeTypes.FindNodeOrInsertPos(ID, InsertPos))
@@ -3138,19 +3361,27 @@ QualType ASTContext::getPipeType(QualType T) const {
// either, so fill in the canonical type field.
QualType Canonical;
if (!T.isCanonical()) {
- Canonical = getPipeType(getCanonicalType(T));
+ Canonical = getPipeType(getCanonicalType(T), ReadOnly);
// Get the new insert position for the node we care about.
PipeType *NewIP = PipeTypes.FindNodeOrInsertPos(ID, InsertPos);
assert(!NewIP && "Shouldn't be in the map!");
(void)NewIP;
}
- PipeType *New = new (*this, TypeAlignment) PipeType(T, Canonical);
+ PipeType *New = new (*this, TypeAlignment) PipeType(T, Canonical, ReadOnly);
Types.push_back(New);
PipeTypes.InsertNode(New, InsertPos);
return QualType(New, 0);
}
+QualType ASTContext::getReadPipeType(QualType T) const {
+ return getPipeType(T, true);
+}
+
+QualType ASTContext::getWritePipeType(QualType T) const {
+ return getPipeType(T, false);
+}
+
#ifndef NDEBUG
static bool NeedsInjectedClassNameType(const RecordDecl *D) {
if (!isa<CXXRecordDecl>(D)) return false;
@@ -3641,6 +3872,44 @@ ASTContext::getDependentTemplateSpecializationType(
return QualType(T, 0);
}
+void
+ASTContext::getInjectedTemplateArgs(const TemplateParameterList *Params,
+ SmallVectorImpl<TemplateArgument> &Args) {
+ Args.reserve(Args.size() + Params->size());
+
+ for (NamedDecl *Param : *Params) {
+ TemplateArgument Arg;
+ if (auto *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) {
+ QualType ArgType = getTypeDeclType(TTP);
+ if (TTP->isParameterPack())
+ ArgType = getPackExpansionType(ArgType, None);
+
+ Arg = TemplateArgument(ArgType);
+ } else if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
+ Expr *E = new (*this) DeclRefExpr(
+ NTTP, /*enclosing*/false,
+ NTTP->getType().getNonLValueExprType(*this),
+ Expr::getValueKindForType(NTTP->getType()), NTTP->getLocation());
+
+ if (NTTP->isParameterPack())
+ E = new (*this) PackExpansionExpr(DependentTy, E, NTTP->getLocation(),
+ None);
+ Arg = TemplateArgument(E);
+ } else {
+ auto *TTP = cast<TemplateTemplateParmDecl>(Param);
+ if (TTP->isParameterPack())
+ Arg = TemplateArgument(TemplateName(TTP), Optional<unsigned>());
+ else
+ Arg = TemplateArgument(TemplateName(TTP));
+ }
+
+ if (Param->isTemplateParameterPack())
+ Arg = TemplateArgument::CreatePackCopy(*this, Arg);
+
+ Args.push_back(Arg);
+ }
+}
+
QualType ASTContext::getPackExpansionType(QualType Pattern,
Optional<unsigned> NumExpansions) {
llvm::FoldingSetNodeID ID;
@@ -3798,6 +4067,116 @@ QualType ASTContext::getObjCObjectType(
return QualType(T, 0);
}
+/// Apply Objective-C protocol qualifiers to the given type.
+/// If this is for the canonical type of a type parameter, we can apply
+/// protocol qualifiers on the ObjCObjectPointerType.
+QualType
+ASTContext::applyObjCProtocolQualifiers(QualType type,
+ ArrayRef<ObjCProtocolDecl *> protocols, bool &hasError,
+ bool allowOnPointerType) const {
+ hasError = false;
+
+ if (const ObjCTypeParamType *objT =
+ dyn_cast<ObjCTypeParamType>(type.getTypePtr())) {
+ return getObjCTypeParamType(objT->getDecl(), protocols);
+ }
+
+ // Apply protocol qualifiers to ObjCObjectPointerType.
+ if (allowOnPointerType) {
+ if (const ObjCObjectPointerType *objPtr =
+ dyn_cast<ObjCObjectPointerType>(type.getTypePtr())) {
+ const ObjCObjectType *objT = objPtr->getObjectType();
+ // Merge protocol lists and construct ObjCObjectType.
+ SmallVector<ObjCProtocolDecl*, 8> protocolsVec;
+ protocolsVec.append(objT->qual_begin(),
+ objT->qual_end());
+ protocolsVec.append(protocols.begin(), protocols.end());
+ ArrayRef<ObjCProtocolDecl *> protocols = protocolsVec;
+ type = getObjCObjectType(
+ objT->getBaseType(),
+ objT->getTypeArgsAsWritten(),
+ protocols,
+ objT->isKindOfTypeAsWritten());
+ return getObjCObjectPointerType(type);
+ }
+ }
+
+ // Apply protocol qualifiers to ObjCObjectType.
+ if (const ObjCObjectType *objT = dyn_cast<ObjCObjectType>(type.getTypePtr())){
+ // FIXME: Check for protocols to which the class type is already
+ // known to conform.
+
+ return getObjCObjectType(objT->getBaseType(),
+ objT->getTypeArgsAsWritten(),
+ protocols,
+ objT->isKindOfTypeAsWritten());
+ }
+
+ // If the canonical type is ObjCObjectType, ...
+ 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 getObjCObjectType(type, { }, protocols, false);
+ }
+
+ // id<protocol-list>
+ if (type->isObjCIdType()) {
+ const ObjCObjectPointerType *objPtr = type->castAs<ObjCObjectPointerType>();
+ type = getObjCObjectType(ObjCBuiltinIdTy, { }, protocols,
+ objPtr->isKindOfType());
+ return getObjCObjectPointerType(type);
+ }
+
+ // Class<protocol-list>
+ if (type->isObjCClassType()) {
+ const ObjCObjectPointerType *objPtr = type->castAs<ObjCObjectPointerType>();
+ type = getObjCObjectType(ObjCBuiltinClassTy, { }, protocols,
+ objPtr->isKindOfType());
+ return getObjCObjectPointerType(type);
+ }
+
+ hasError = true;
+ return type;
+}
+
+QualType
+ASTContext::getObjCTypeParamType(const ObjCTypeParamDecl *Decl,
+ ArrayRef<ObjCProtocolDecl *> protocols,
+ QualType Canonical) const {
+ // Look in the folding set for an existing type.
+ llvm::FoldingSetNodeID ID;
+ ObjCTypeParamType::Profile(ID, Decl, protocols);
+ void *InsertPos = nullptr;
+ if (ObjCTypeParamType *TypeParam =
+ ObjCTypeParamTypes.FindNodeOrInsertPos(ID, InsertPos))
+ return QualType(TypeParam, 0);
+
+ if (Canonical.isNull()) {
+ // We canonicalize to the underlying type.
+ Canonical = getCanonicalType(Decl->getUnderlyingType());
+ if (!protocols.empty()) {
+ // Apply the protocol qualifers.
+ bool hasError;
+ Canonical = applyObjCProtocolQualifiers(Canonical, protocols, hasError,
+ true/*allowOnPointerType*/);
+ assert(!hasError && "Error when apply protocol qualifier to bound type");
+ }
+ }
+
+ unsigned size = sizeof(ObjCTypeParamType);
+ size += protocols.size() * sizeof(ObjCProtocolDecl *);
+ void *mem = Allocate(size, TypeAlignment);
+ ObjCTypeParamType *newType = new (mem)
+ ObjCTypeParamType(Decl, Canonical, protocols);
+
+ Types.push_back(newType);
+ ObjCTypeParamTypes.InsertNode(newType, InsertPos);
+ return QualType(newType, 0);
+}
+
/// ObjCObjectAdoptsQTypeProtocols - Checks that protocols in IC's
/// protocol list adopt all protocols in QT's qualified-id protocol
/// list.
@@ -3983,7 +4362,7 @@ QualType ASTContext::getDecltypeType(Expr *e, QualType UnderlyingType) const {
DependentDecltypeType *Canon
= DependentDecltypeTypes.FindNodeOrInsertPos(ID, InsertPos);
if (!Canon) {
- // Build a new, canonical typeof(expr) type.
+ // Build a new, canonical decltype(expr) type.
Canon = new (*this, TypeAlignment) DependentDecltypeType(*this, e);
DependentDecltypeTypes.InsertNode(Canon, InsertPos);
}
@@ -4590,7 +4969,15 @@ QualType ASTContext::getArrayDecayedType(QualType Ty) const {
QualType PtrTy = getPointerType(PrettyArrayType->getElementType());
// int x[restrict 4] -> int *restrict
- return getQualifiedType(PtrTy, PrettyArrayType->getIndexTypeQualifiers());
+ QualType Result = getQualifiedType(PtrTy,
+ PrettyArrayType->getIndexTypeQualifiers());
+
+ // int x[_Nullable] -> int * _Nullable
+ if (auto Nullability = Ty->getNullability(*this)) {
+ Result = const_cast<ASTContext *>(this)->getAttributedType(
+ AttributedType::getNullabilityAttrKind(*Nullability), Result, Result);
+ }
+ return Result;
}
QualType ASTContext::getBaseElementType(const ArrayType *array) const {
@@ -5223,8 +5610,9 @@ std::string ASTContext::getObjCEncodingForBlock(const BlockExpr *Expr) const {
return S;
}
-bool ASTContext::getObjCEncodingForFunctionDecl(const FunctionDecl *Decl,
- std::string& S) {
+std::string
+ASTContext::getObjCEncodingForFunctionDecl(const FunctionDecl *Decl) const {
+ std::string S;
// Encode result type.
getObjCEncodingForType(Decl->getReturnType(), S);
CharUnits ParmOffset;
@@ -5235,8 +5623,8 @@ bool ASTContext::getObjCEncodingForFunctionDecl(const FunctionDecl *Decl,
if (sz.isZero())
continue;
- assert (sz.isPositive() &&
- "getObjCEncodingForFunctionDecl - Incomplete param type");
+ assert(sz.isPositive() &&
+ "getObjCEncodingForFunctionDecl - Incomplete param type");
ParmOffset += sz;
}
S += charUnitsToString(ParmOffset);
@@ -5258,7 +5646,7 @@ bool ASTContext::getObjCEncodingForFunctionDecl(const FunctionDecl *Decl,
ParmOffset += getObjCEncodingTypeSize(PType);
}
- return false;
+ return S;
}
/// getObjCEncodingForMethodParameter - Return the encoded type for a single
@@ -5280,11 +5668,11 @@ void ASTContext::getObjCEncodingForMethodParameter(Decl::ObjCDeclQualifier QT,
/// getObjCEncodingForMethodDecl - Return the encoded type for this method
/// declaration.
-bool ASTContext::getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl,
- std::string& S,
- bool Extended) const {
+std::string ASTContext::getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl,
+ bool Extended) const {
// FIXME: This is not very efficient.
// Encode return type.
+ std::string S;
getObjCEncodingForMethodParameter(Decl->getObjCDeclQualifier(),
Decl->getReturnType(), S, Extended);
// Compute size of all parameters.
@@ -5330,7 +5718,7 @@ bool ASTContext::getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl,
ParmOffset += getObjCEncodingTypeSize(PType);
}
- return false;
+ return S;
}
ObjCPropertyImplDecl *
@@ -5378,9 +5766,9 @@ ASTContext::getObjCPropertyImplDeclForPropertyDecl(
/// kPropertyNonAtomic = 'N' // property non-atomic
/// };
/// @endcode
-void ASTContext::getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD,
- const Decl *Container,
- std::string& S) const {
+std::string
+ASTContext::getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD,
+ const Decl *Container) const {
// Collect information from the property implementation decl(s).
bool Dynamic = false;
ObjCPropertyImplDecl *SynthesizePID = nullptr;
@@ -5394,7 +5782,7 @@ void ASTContext::getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD,
}
// FIXME: This is not very efficient.
- S = "T";
+ std::string S = "T";
// Encode result type.
// GCC has some special rules regarding encoding of properties which
@@ -5443,6 +5831,7 @@ void ASTContext::getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD,
}
// FIXME: OBJCGC: weak & strong
+ return S;
}
/// getLegacyIntegralTypeEncoding -
@@ -5833,18 +6222,20 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
ObjCInterfaceDecl *OI = T->castAs<ObjCObjectType>()->getInterface();
S += '{';
S += OI->getObjCRuntimeNameAsString();
- S += '=';
- SmallVector<const ObjCIvarDecl*, 32> Ivars;
- DeepCollectObjCIvars(OI, true, Ivars);
- for (unsigned i = 0, e = Ivars.size(); i != e; ++i) {
- const FieldDecl *Field = cast<FieldDecl>(Ivars[i]);
- if (Field->isBitField())
- getObjCEncodingForTypeImpl(Field->getType(), S, false, true, Field);
- else
- getObjCEncodingForTypeImpl(Field->getType(), S, false, true, FD,
- false, false, false, false, false,
- EncodePointerToObjCTypedef,
- NotEncodedT);
+ if (ExpandStructures) {
+ S += '=';
+ SmallVector<const ObjCIvarDecl*, 32> Ivars;
+ DeepCollectObjCIvars(OI, true, Ivars);
+ for (unsigned i = 0, e = Ivars.size(); i != e; ++i) {
+ const FieldDecl *Field = cast<FieldDecl>(Ivars[i]);
+ if (Field->isBitField())
+ getObjCEncodingForTypeImpl(Field->getType(), S, false, true, Field);
+ else
+ getObjCEncodingForTypeImpl(Field->getType(), S, false, true, FD,
+ false, false, false, false, false,
+ EncodePointerToObjCTypedef,
+ NotEncodedT);
+ }
}
S += '}';
return;
@@ -6369,9 +6760,8 @@ CreateX86_64ABIBuiltinVaListDecl(const ASTContext *Context) {
static TypedefDecl *CreatePNaClABIBuiltinVaListDecl(const ASTContext *Context) {
// typedef int __builtin_va_list[4];
llvm::APInt Size(Context->getTypeSize(Context->getSizeType()), 4);
- QualType IntArrayType
- = Context->getConstantArrayType(Context->IntTy,
- Size, ArrayType::Normal, 0);
+ QualType IntArrayType =
+ Context->getConstantArrayType(Context->IntTy, Size, ArrayType::Normal, 0);
return Context->buildImplicitTypedef(IntArrayType, "__builtin_va_list");
}
@@ -6567,7 +6957,7 @@ ASTContext::getQualifiedTemplateName(NestedNameSpecifier *NNS,
QualifiedTemplateName *QTN =
QualifiedTemplateNames.FindNodeOrInsertPos(ID, InsertPos);
if (!QTN) {
- QTN = new (*this, llvm::alignOf<QualifiedTemplateName>())
+ QTN = new (*this, alignof(QualifiedTemplateName))
QualifiedTemplateName(NNS, TemplateKeyword, Template);
QualifiedTemplateNames.InsertNode(QTN, InsertPos);
}
@@ -6595,11 +6985,11 @@ ASTContext::getDependentTemplateName(NestedNameSpecifier *NNS,
NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS);
if (CanonNNS == NNS) {
- QTN = new (*this, llvm::alignOf<DependentTemplateName>())
+ QTN = new (*this, alignof(DependentTemplateName))
DependentTemplateName(NNS, Name);
} else {
TemplateName Canon = getDependentTemplateName(CanonNNS, Name);
- QTN = new (*this, llvm::alignOf<DependentTemplateName>())
+ QTN = new (*this, alignof(DependentTemplateName))
DependentTemplateName(NNS, Name, Canon);
DependentTemplateName *CheckQTN =
DependentTemplateNames.FindNodeOrInsertPos(ID, InsertPos);
@@ -6631,13 +7021,13 @@ ASTContext::getDependentTemplateName(NestedNameSpecifier *NNS,
NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS);
if (CanonNNS == NNS) {
- QTN = new (*this, llvm::alignOf<DependentTemplateName>())
+ QTN = new (*this, alignof(DependentTemplateName))
DependentTemplateName(NNS, Operator);
} else {
TemplateName Canon = getDependentTemplateName(CanonNNS, Operator);
- QTN = new (*this, llvm::alignOf<DependentTemplateName>())
+ QTN = new (*this, alignof(DependentTemplateName))
DependentTemplateName(NNS, Operator, Canon);
-
+
DependentTemplateName *CheckQTN
= DependentTemplateNames.FindNodeOrInsertPos(ID, InsertPos);
assert(!CheckQTN && "Dependent template name canonicalization broken");
@@ -7388,7 +7778,7 @@ bool ASTContext::typesAreCompatible(QualType LHS, QualType RHS,
bool CompareUnqualified) {
if (getLangOpts().CPlusPlus)
return hasSameType(LHS, RHS);
-
+
return !mergeTypes(LHS, RHS, false, CompareUnqualified).isNull();
}
@@ -7902,21 +8292,9 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
}
case Type::Pipe:
{
- // Merge two pointer types, while trying to preserve typedef info
- QualType LHSValue = LHS->getAs<PipeType>()->getElementType();
- QualType RHSValue = RHS->getAs<PipeType>()->getElementType();
- if (Unqualified) {
- LHSValue = LHSValue.getUnqualifiedType();
- RHSValue = RHSValue.getUnqualifiedType();
- }
- QualType ResultType = mergeTypes(LHSValue, RHSValue, false,
- Unqualified);
- if (ResultType.isNull()) return QualType();
- if (getCanonicalType(LHSValue) == getCanonicalType(ResultType))
- return LHS;
- if (getCanonicalType(RHSValue) == getCanonicalType(ResultType))
- return RHS;
- return getPipeType(ResultType);
+ assert(LHS != RHS &&
+ "Equivalent pipe types should have already been handled!");
+ return QualType();
}
}
@@ -8197,6 +8575,10 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context,
assert(HowLong == 0 && !Signed && !Unsigned && "Bad modifiers for 'z'!");
Type = Context.getSizeType();
break;
+ case 'w': // wchar_t.
+ assert(HowLong == 0 && !Signed && !Unsigned && "Bad modifiers for 'w'!");
+ Type = Context.getWideCharType();
+ break;
case 'F':
Type = Context.getCFConstantStringType();
break;
@@ -8385,13 +8767,16 @@ QualType ASTContext::GetBuiltinType(unsigned Id,
bool Variadic = (TypeStr[0] == '.');
- // We really shouldn't be making a no-proto type here, especially in C++.
- if (ArgTypes.empty() && Variadic)
+ // We really shouldn't be making a no-proto type here.
+ if (ArgTypes.empty() && Variadic && !getLangOpts().CPlusPlus)
return getFunctionNoProtoType(ResType, EI);
FunctionProtoType::ExtProtoInfo EPI;
EPI.ExtInfo = EI;
EPI.Variadic = Variadic;
+ if (getLangOpts().CPlusPlus && BuiltinInfo.isNoThrow(Id))
+ EPI.ExceptionSpec.Type =
+ getLangOpts().CPlusPlus11 ? EST_BasicNoexcept : EST_DynamicNone;
return getFunctionType(ResType, ArgTypes, EPI);
}
@@ -8576,6 +8961,8 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) {
return !D->getDeclContext()->isDependentContext();
else if (isa<OMPDeclareReductionDecl>(D))
return !D->getDeclContext()->isDependentContext();
+ else if (isa<ImportDecl>(D))
+ return true;
else
return false;
@@ -8613,15 +9000,10 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) {
}
}
- GVALinkage Linkage = GetGVALinkageForFunction(FD);
-
// static, static inline, always_inline, and extern inline functions can
// always be deferred. Normal inline functions can be deferred in C99/C++.
// Implicit template instantiations can also be deferred in C++.
- if (Linkage == GVA_Internal || Linkage == GVA_AvailableExternally ||
- Linkage == GVA_DiscardableODR)
- return false;
- return true;
+ return !isDiscardableGVALinkage(GetGVALinkageForFunction(FD));
}
const VarDecl *VD = cast<VarDecl>(D);
@@ -8632,9 +9014,7 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) {
return false;
// Variables that can be needed in other TUs are required.
- GVALinkage L = GetGVALinkageForVariable(VD);
- if (L != GVA_Internal && L != GVA_AvailableExternally &&
- L != GVA_DiscardableODR)
+ if (!isDiscardableGVALinkage(GetGVALinkageForVariable(VD)))
return true;
// Variables that have destruction with side-effects are required.
@@ -8646,6 +9026,14 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) {
!VD->evaluateValue())
return true;
+ // Likewise, variables with tuple-like bindings are required if their
+ // bindings have side-effects.
+ if (auto *DD = dyn_cast<DecompositionDecl>(VD))
+ for (auto *BD : DD->bindings())
+ if (auto *BindingVD = BD->getHoldingVar())
+ if (DeclMustBeEmitted(BindingVD))
+ return true;
+
return false;
}
@@ -8785,13 +9173,14 @@ unsigned ASTContext::getStaticLocalNumber(const VarDecl *VD) const {
MangleNumberingContext &
ASTContext::getManglingNumberContext(const DeclContext *DC) {
assert(LangOpts.CPlusPlus); // We don't need mangling numbers for plain C.
- MangleNumberingContext *&MCtx = MangleNumberingContexts[DC];
+ std::unique_ptr<MangleNumberingContext> &MCtx = MangleNumberingContexts[DC];
if (!MCtx)
MCtx = createMangleNumberingContext();
return *MCtx;
}
-MangleNumberingContext *ASTContext::createMangleNumberingContext() const {
+std::unique_ptr<MangleNumberingContext>
+ASTContext::createMangleNumberingContext() const {
return ABI->createMangleNumberingContext();
}
@@ -8808,18 +9197,6 @@ void ASTContext::addCopyConstructorForExceptionObject(CXXRecordDecl *RD,
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::addTypedefNameForUnnamedTagDecl(TagDecl *TD,
TypedefNameDecl *DD) {
return ABI->addTypedefNameForUnnamedTagDecl(TD, DD);
@@ -9098,6 +9475,16 @@ ASTContext::ObjCMethodsAreEqual(const ObjCMethodDecl *MethodDecl,
}
+uint64_t ASTContext::getTargetNullPointerValue(QualType QT) const {
+ unsigned AS;
+ if (QT->getUnqualifiedDesugaredType()->isNullPtrType())
+ AS = 0;
+ else
+ AS = QT->getPointeeType().getAddressSpace();
+
+ return getTargetInfo().getNullPointerValue(AS);
+}
+
// Explicitly instantiate this in case a Redeclarable<T> is used from a TU that
// doesn't include ASTContext.h
template
diff --git a/lib/AST/ASTDiagnostic.cpp b/lib/AST/ASTDiagnostic.cpp
index 0f5a8b5ae892..03e6115a0dba 100644
--- a/lib/AST/ASTDiagnostic.cpp
+++ b/lib/AST/ASTDiagnostic.cpp
@@ -20,7 +20,6 @@
#include "clang/AST/ExprCXX.h"
#include "clang/AST/TemplateBase.h"
#include "clang/AST/Type.h"
-#include "llvm/ADT/SmallString.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
@@ -937,6 +936,9 @@ class TemplateDiff {
++(*this);
}
+ /// Return true if the iterator is non-singular.
+ bool isValid() const { return TST; }
+
/// isEnd - Returns true if the iterator is one past the end.
bool isEnd() const {
assert(TST && "InternalIterator is invalid with a null TST.");
@@ -996,21 +998,21 @@ class TemplateDiff {
}
};
- bool UseDesugaredIterator;
InternalIterator SugaredIterator;
InternalIterator DesugaredIterator;
public:
TSTiterator(ASTContext &Context, const TemplateSpecializationType *TST)
- : UseDesugaredIterator(TST->isSugared() && !TST->isTypeAlias()),
- SugaredIterator(TST),
+ : SugaredIterator(TST),
DesugaredIterator(
- GetTemplateSpecializationType(Context, TST->desugar())) {}
+ (TST->isSugared() && !TST->isTypeAlias())
+ ? GetTemplateSpecializationType(Context, TST->desugar())
+ : nullptr) {}
/// &operator++ - Increment the iterator to the next template argument.
TSTiterator &operator++() {
++SugaredIterator;
- if (UseDesugaredIterator)
+ if (DesugaredIterator.isValid())
++DesugaredIterator;
return *this;
}
@@ -1033,12 +1035,12 @@ class TemplateDiff {
/// hasDesugaredTA - Returns true if there is another TemplateArgument
/// available.
bool hasDesugaredTA() const {
- return UseDesugaredIterator && !DesugaredIterator.isEnd();
+ return DesugaredIterator.isValid() && !DesugaredIterator.isEnd();
}
/// getDesugaredTA - Returns the desugared TemplateArgument.
reference getDesugaredTA() const {
- assert(UseDesugaredIterator &&
+ assert(DesugaredIterator.isValid() &&
"Desugared TemplateArgument should not be used.");
return *DesugaredIterator;
}
diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp
index 872ba356a9b2..62261ccc905b 100644
--- a/lib/AST/ASTDumper.cpp
+++ b/lib/AST/ASTDumper.cpp
@@ -428,6 +428,8 @@ namespace {
void VisitFunctionDecl(const FunctionDecl *D);
void VisitFieldDecl(const FieldDecl *D);
void VisitVarDecl(const VarDecl *D);
+ void VisitDecompositionDecl(const DecompositionDecl *D);
+ void VisitBindingDecl(const BindingDecl *D);
void VisitFileScopeAsmDecl(const FileScopeAsmDecl *D);
void VisitImportDecl(const ImportDecl *D);
void VisitPragmaCommentDecl(const PragmaCommentDecl *D);
@@ -515,6 +517,8 @@ namespace {
void VisitFloatingLiteral(const FloatingLiteral *Node);
void VisitStringLiteral(const StringLiteral *Str);
void VisitInitListExpr(const InitListExpr *ILE);
+ void VisitArrayInitLoopExpr(const ArrayInitLoopExpr *ILE);
+ void VisitArrayInitIndexExpr(const ArrayInitIndexExpr *ILE);
void VisitUnaryOperator(const UnaryOperator *Node);
void VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Node);
void VisitMemberExpr(const MemberExpr *Node);
@@ -543,6 +547,8 @@ namespace {
dumpDecl(Node->getLambdaClass());
}
void VisitSizeOfPackExpr(const SizeOfPackExpr *Node);
+ void
+ VisitCXXDependentScopeMemberExpr(const CXXDependentScopeMemberExpr *Node);
// ObjC
void VisitObjCAtCatchStmt(const ObjCAtCatchStmt *Node);
@@ -1133,8 +1139,15 @@ void ASTDumper::VisitFunctionDecl(const FunctionDecl *D) {
if (D->isPure())
OS << " pure";
- else if (D->isDeletedAsWritten())
+ if (D->isDefaulted()) {
+ OS << " default";
+ if (D->isDeleted())
+ OS << "_delete";
+ }
+ if (D->isDeletedAsWritten())
OS << " delete";
+ if (D->isTrivial())
+ OS << " trivial";
if (const FunctionProtoType *FPT = D->getType()->getAs<FunctionProtoType>()) {
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
@@ -1153,11 +1166,6 @@ void ASTDumper::VisitFunctionDecl(const FunctionDecl *D) {
D->getTemplateSpecializationInfo())
dumpTemplateArgumentList(*FTSI->TemplateArguments);
- for (ArrayRef<NamedDecl *>::iterator
- I = D->getDeclsInPrototypeScope().begin(),
- E = D->getDeclsInPrototypeScope().end(); I != E; ++I)
- dumpDecl(*I);
-
if (!D->param_begin() && D->getNumParams())
dumpChild([=] { OS << "<<NULL params x " << D->getNumParams() << ">>"; });
else
@@ -1217,6 +1225,19 @@ void ASTDumper::VisitVarDecl(const VarDecl *D) {
}
}
+void ASTDumper::VisitDecompositionDecl(const DecompositionDecl *D) {
+ VisitVarDecl(D);
+ for (auto *B : D->bindings())
+ dumpDecl(B);
+}
+
+void ASTDumper::VisitBindingDecl(const BindingDecl *D) {
+ dumpName(D);
+ dumpType(D->getType());
+ if (auto *E = D->getBinding())
+ dumpStmt(E);
+}
+
void ASTDumper::VisitFileScopeAsmDecl(const FileScopeAsmDecl *D) {
dumpStmt(D->getAsmString());
}
@@ -2005,6 +2026,14 @@ void ASTDumper::VisitInitListExpr(const InitListExpr *ILE) {
}
}
+void ASTDumper::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E) {
+ VisitExpr(E);
+}
+
+void ASTDumper::VisitArrayInitIndexExpr(const ArrayInitIndexExpr *E) {
+ VisitExpr(E);
+}
+
void ASTDumper::VisitUnaryOperator(const UnaryOperator *Node) {
VisitExpr(Node);
OS << " " << (Node->isPostfix() ? "postfix" : "prefix")
@@ -2179,6 +2208,11 @@ void ASTDumper::VisitSizeOfPackExpr(const SizeOfPackExpr *Node) {
dumpTemplateArgument(A);
}
+void ASTDumper::VisitCXXDependentScopeMemberExpr(
+ const CXXDependentScopeMemberExpr *Node) {
+ VisitExpr(Node);
+ OS << " " << (Node->isArrow() ? "->" : ".") << Node->getMember();
+}
//===----------------------------------------------------------------------===//
// Obj-C Expressions
@@ -2451,12 +2485,18 @@ void QualType::dump(const char *msg) const {
dump();
}
-LLVM_DUMP_METHOD void QualType::dump() const {
- ASTDumper Dumper(llvm::errs(), nullptr, nullptr);
+LLVM_DUMP_METHOD void QualType::dump() const { dump(llvm::errs()); }
+
+LLVM_DUMP_METHOD void QualType::dump(llvm::raw_ostream &OS) const {
+ ASTDumper Dumper(OS, nullptr, nullptr);
Dumper.dumpTypeAsChild(*this);
}
-LLVM_DUMP_METHOD void Type::dump() const { QualType(this, 0).dump(); }
+LLVM_DUMP_METHOD void Type::dump() const { dump(llvm::errs()); }
+
+LLVM_DUMP_METHOD void Type::dump(llvm::raw_ostream &OS) const {
+ QualType(this, 0).dump(OS);
+}
//===----------------------------------------------------------------------===//
// Decl method implementations
diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp
index bc1f9f96a06b..67e96ea828bd 100644
--- a/lib/AST/ASTImporter.cpp
+++ b/lib/AST/ASTImporter.cpp
@@ -39,7 +39,9 @@ namespace clang {
// Importing types
QualType VisitType(const Type *T);
+ QualType VisitAtomicType(const AtomicType *T);
QualType VisitBuiltinType(const BuiltinType *T);
+ QualType VisitDecayedType(const DecayedType *T);
QualType VisitComplexType(const ComplexType *T);
QualType VisitPointerType(const PointerType *T);
QualType VisitBlockPointerType(const BlockPointerType *T);
@@ -88,6 +90,8 @@ namespace clang {
DeclarationNameInfo& To);
void ImportDeclContext(DeclContext *FromDC, bool ForceImport = false);
+ bool ImportCastPath(CastExpr *E, CXXCastPath &Path);
+
typedef DesignatedInitExpr::Designator Designator;
Designator ImportDesignator(const Designator &D);
@@ -123,6 +127,8 @@ namespace clang {
TemplateParameterList *ImportTemplateParameterList(
TemplateParameterList *Params);
TemplateArgument ImportTemplateArgument(const TemplateArgument &From);
+ TemplateArgumentLoc ImportTemplateArgumentLoc(
+ const TemplateArgumentLoc &TALoc, bool &Error);
bool ImportTemplateArguments(const TemplateArgument *FromArgs,
unsigned NumFromArgs,
SmallVectorImpl<TemplateArgument> &ToArgs);
@@ -136,6 +142,7 @@ namespace clang {
bool IsStructuralMatch(VarTemplateDecl *From, VarTemplateDecl *To);
Decl *VisitDecl(Decl *D);
Decl *VisitAccessSpecDecl(AccessSpecDecl *D);
+ Decl *VisitStaticAssertDecl(StaticAssertDecl *D);
Decl *VisitTranslationUnitDecl(TranslationUnitDecl *D);
Decl *VisitNamespaceDecl(NamespaceDecl *D);
Decl *VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias);
@@ -152,6 +159,7 @@ namespace clang {
Decl *VisitCXXConversionDecl(CXXConversionDecl *D);
Decl *VisitFieldDecl(FieldDecl *D);
Decl *VisitIndirectFieldDecl(IndirectFieldDecl *D);
+ Decl *VisitFriendDecl(FriendDecl *D);
Decl *VisitObjCIvarDecl(ObjCIvarDecl *D);
Decl *VisitVarDecl(VarDecl *D);
Decl *VisitImplicitParamDecl(ImplicitParamDecl *D);
@@ -242,16 +250,32 @@ namespace clang {
Expr *VisitConditionalOperator(ConditionalOperator *E);
Expr *VisitBinaryConditionalOperator(BinaryConditionalOperator *E);
Expr *VisitOpaqueValueExpr(OpaqueValueExpr *E);
+ Expr *VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E);
+ Expr *VisitExpressionTraitExpr(ExpressionTraitExpr *E);
+ Expr *VisitArraySubscriptExpr(ArraySubscriptExpr *E);
Expr *VisitCompoundAssignOperator(CompoundAssignOperator *E);
Expr *VisitImplicitCastExpr(ImplicitCastExpr *E);
- Expr *VisitCStyleCastExpr(CStyleCastExpr *E);
+ Expr *VisitExplicitCastExpr(ExplicitCastExpr *E);
+ Expr *VisitOffsetOfExpr(OffsetOfExpr *OE);
+ Expr *VisitCXXThrowExpr(CXXThrowExpr *E);
+ Expr *VisitCXXNoexceptExpr(CXXNoexceptExpr *E);
+ Expr *VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E);
+ Expr *VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E);
+ Expr *VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E);
+ Expr *VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *CE);
+ Expr *VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E);
+ Expr *VisitCXXNewExpr(CXXNewExpr *CE);
+ Expr *VisitCXXDeleteExpr(CXXDeleteExpr *E);
Expr *VisitCXXConstructExpr(CXXConstructExpr *E);
Expr *VisitCXXMemberCallExpr(CXXMemberCallExpr *E);
+ Expr *VisitExprWithCleanups(ExprWithCleanups *EWC);
Expr *VisitCXXThisExpr(CXXThisExpr *E);
Expr *VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E);
Expr *VisitMemberExpr(MemberExpr *E);
Expr *VisitCallExpr(CallExpr *E);
Expr *VisitInitListExpr(InitListExpr *E);
+ Expr *VisitArrayInitLoopExpr(ArrayInitLoopExpr *E);
+ Expr *VisitArrayInitIndexExpr(ArrayInitIndexExpr *E);
Expr *VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E);
Expr *VisitCXXNamedCastExpr(CXXNamedCastExpr *E);
@@ -272,13 +296,26 @@ namespace clang {
bool Failed = false;
std::transform(Ibegin, Iend, Obegin,
[&ImporterRef, &Failed](ItemT *From) -> ItemT * {
- ItemT *To = ImporterRef.Import(From);
+ ItemT *To = cast_or_null<ItemT>(
+ ImporterRef.Import(From));
if (!To && From)
Failed = true;
return To;
});
return Failed;
}
+
+ template<typename InContainerTy, typename OutContainerTy>
+ bool ImportContainerChecked(const InContainerTy &InContainer,
+ OutContainerTy &OutContainer) {
+ return ImportArrayChecked(InContainer.begin(), InContainer.end(),
+ OutContainer.begin());
+ }
+
+ template<typename InContainerTy, typename OIter>
+ bool ImportArrayChecked(const InContainerTy &InContainer, OIter Obegin) {
+ return ImportArrayChecked(InContainer.begin(), InContainer.end(), Obegin);
+ }
};
}
@@ -897,6 +934,23 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
break;
}
+ case Type::ObjCTypeParam: {
+ const ObjCTypeParamType *Obj1 = cast<ObjCTypeParamType>(T1);
+ const ObjCTypeParamType *Obj2 = cast<ObjCTypeParamType>(T2);
+ if (!IsStructurallyEquivalent(Context, Obj1->getDecl(),
+ Obj2->getDecl()))
+ return false;
+
+ if (Obj1->getNumProtocols() != Obj2->getNumProtocols())
+ return false;
+ for (unsigned I = 0, N = Obj1->getNumProtocols(); I != N; ++I) {
+ if (!IsStructurallyEquivalent(Context,
+ Obj1->getProtocol(I),
+ Obj2->getProtocol(I)))
+ return false;
+ }
+ break;
+ }
case Type::ObjCObject: {
const ObjCObjectType *Obj1 = cast<ObjCObjectType>(T1);
const ObjCObjectType *Obj2 = cast<ObjCObjectType>(T2);
@@ -1549,6 +1603,14 @@ QualType ASTNodeImporter::VisitType(const Type *T) {
return QualType();
}
+QualType ASTNodeImporter::VisitAtomicType(const AtomicType *T){
+ QualType UnderlyingType = Importer.Import(T->getValueType());
+ if(UnderlyingType.isNull())
+ return QualType();
+
+ return Importer.getToContext().getAtomicType(UnderlyingType);
+}
+
QualType ASTNodeImporter::VisitBuiltinType(const BuiltinType *T) {
switch (T->getKind()) {
#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
@@ -1594,6 +1656,14 @@ QualType ASTNodeImporter::VisitBuiltinType(const BuiltinType *T) {
llvm_unreachable("Invalid BuiltinType Kind!");
}
+QualType ASTNodeImporter::VisitDecayedType(const DecayedType *T) {
+ QualType OrigT = Importer.Import(T->getOriginalType());
+ if (OrigT.isNull())
+ return QualType();
+
+ return Importer.getToContext().getDecayedType(OrigT);
+}
+
QualType ASTNodeImporter::VisitComplexType(const ComplexType *T) {
QualType ToElementType = Importer.Import(T->getElementType());
if (ToElementType.isNull())
@@ -2250,23 +2320,25 @@ bool ASTNodeImporter::ImportDefinition(EnumDecl *From, EnumDecl *To,
TemplateParameterList *ASTNodeImporter::ImportTemplateParameterList(
TemplateParameterList *Params) {
- SmallVector<NamedDecl *, 4> ToParams;
- ToParams.reserve(Params->size());
- for (TemplateParameterList::iterator P = Params->begin(),
- PEnd = Params->end();
- P != PEnd; ++P) {
- Decl *To = Importer.Import(*P);
- if (!To)
+ SmallVector<NamedDecl *, 4> ToParams(Params->size());
+ if (ImportContainerChecked(*Params, ToParams))
+ return nullptr;
+
+ Expr *ToRequiresClause;
+ if (Expr *const R = Params->getRequiresClause()) {
+ ToRequiresClause = Importer.Import(R);
+ if (!ToRequiresClause)
return nullptr;
-
- ToParams.push_back(cast<NamedDecl>(To));
+ } else {
+ ToRequiresClause = nullptr;
}
-
+
return TemplateParameterList::Create(Importer.getToContext(),
Importer.Import(Params->getTemplateLoc()),
Importer.Import(Params->getLAngleLoc()),
ToParams,
- Importer.Import(Params->getRAngleLoc()));
+ Importer.Import(Params->getRAngleLoc()),
+ ToRequiresClause);
}
TemplateArgument
@@ -2340,6 +2412,31 @@ ASTNodeImporter::ImportTemplateArgument(const TemplateArgument &From) {
llvm_unreachable("Invalid template argument kind");
}
+TemplateArgumentLoc ASTNodeImporter::ImportTemplateArgumentLoc(
+ const TemplateArgumentLoc &TALoc, bool &Error) {
+ Error = false;
+ TemplateArgument Arg = ImportTemplateArgument(TALoc.getArgument());
+ TemplateArgumentLocInfo FromInfo = TALoc.getLocInfo();
+ TemplateArgumentLocInfo ToInfo;
+ if (Arg.getKind() == TemplateArgument::Expression) {
+ Expr *E = Importer.Import(FromInfo.getAsExpr());
+ ToInfo = TemplateArgumentLocInfo(E);
+ if (!E)
+ Error = true;
+ } else if (Arg.getKind() == TemplateArgument::Type) {
+ if (TypeSourceInfo *TSI = Importer.Import(FromInfo.getAsTypeSourceInfo()))
+ ToInfo = TemplateArgumentLocInfo(TSI);
+ else
+ Error = true;
+ } else {
+ ToInfo = TemplateArgumentLocInfo(
+ Importer.Import(FromInfo.getTemplateQualifierLoc()),
+ Importer.Import(FromInfo.getTemplateNameLoc()),
+ Importer.Import(FromInfo.getTemplateEllipsisLoc()));
+ }
+ return TemplateArgumentLoc(Arg, ToInfo);
+}
+
bool ASTNodeImporter::ImportTemplateArguments(const TemplateArgument *FromArgs,
unsigned NumFromArgs,
SmallVectorImpl<TemplateArgument> &ToArgs) {
@@ -2454,6 +2551,35 @@ Decl *ASTNodeImporter::VisitAccessSpecDecl(AccessSpecDecl *D) {
return accessSpecDecl;
}
+Decl *ASTNodeImporter::VisitStaticAssertDecl(StaticAssertDecl *D) {
+ DeclContext *DC = Importer.ImportContext(D->getDeclContext());
+ if (!DC)
+ return nullptr;
+
+ DeclContext *LexicalDC = DC;
+
+ // Import the location of this declaration.
+ SourceLocation Loc = Importer.Import(D->getLocation());
+
+ Expr *AssertExpr = Importer.Import(D->getAssertExpr());
+ if (!AssertExpr)
+ return nullptr;
+
+ StringLiteral *FromMsg = D->getMessage();
+ StringLiteral *ToMsg = cast_or_null<StringLiteral>(Importer.Import(FromMsg));
+ if (!ToMsg && FromMsg)
+ return nullptr;
+
+ StaticAssertDecl *ToD = StaticAssertDecl::Create(
+ Importer.getToContext(), DC, Loc, AssertExpr, ToMsg,
+ Importer.Import(D->getRParenLoc()), D->isFailed());
+
+ ToD->setLexicalDeclContext(LexicalDC);
+ LexicalDC->addDeclInternal(ToD);
+ Importer.Imported(D, ToD);
+ return ToD;
+}
+
Decl *ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) {
// Import the major distinguishing characteristics of this namespace.
DeclContext *DC, *LexicalDC;
@@ -3303,6 +3429,70 @@ Decl *ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) {
return ToIndirectField;
}
+Decl *ASTNodeImporter::VisitFriendDecl(FriendDecl *D) {
+ // Import the major distinguishing characteristics of a declaration.
+ DeclContext *DC = Importer.ImportContext(D->getDeclContext());
+ DeclContext *LexicalDC = D->getDeclContext() == D->getLexicalDeclContext()
+ ? DC : Importer.ImportContext(D->getLexicalDeclContext());
+ if (!DC || !LexicalDC)
+ return nullptr;
+
+ // Determine whether we've already imported this decl.
+ // FriendDecl is not a NamedDecl so we cannot use localUncachedLookup.
+ auto *RD = cast<CXXRecordDecl>(DC);
+ FriendDecl *ImportedFriend = RD->getFirstFriend();
+ StructuralEquivalenceContext Context(
+ Importer.getFromContext(), Importer.getToContext(),
+ Importer.getNonEquivalentDecls(), false, false);
+
+ while (ImportedFriend) {
+ if (D->getFriendDecl() && ImportedFriend->getFriendDecl()) {
+ if (Context.IsStructurallyEquivalent(D->getFriendDecl(),
+ ImportedFriend->getFriendDecl()))
+ return Importer.Imported(D, ImportedFriend);
+
+ } else if (D->getFriendType() && ImportedFriend->getFriendType()) {
+ if (Importer.IsStructurallyEquivalent(
+ D->getFriendType()->getType(),
+ ImportedFriend->getFriendType()->getType(), true))
+ return Importer.Imported(D, ImportedFriend);
+ }
+ ImportedFriend = ImportedFriend->getNextFriend();
+ }
+
+ // Not found. Create it.
+ FriendDecl::FriendUnion ToFU;
+ if (NamedDecl *FriendD = D->getFriendDecl())
+ ToFU = cast_or_null<NamedDecl>(Importer.Import(FriendD));
+ else
+ ToFU = Importer.Import(D->getFriendType());
+ if (!ToFU)
+ return nullptr;
+
+ SmallVector<TemplateParameterList *, 1> ToTPLists(D->NumTPLists);
+ TemplateParameterList **FromTPLists =
+ D->getTrailingObjects<TemplateParameterList *>();
+ for (unsigned I = 0; I < D->NumTPLists; I++) {
+ TemplateParameterList *List = ImportTemplateParameterList(FromTPLists[I]);
+ if (!List)
+ return nullptr;
+ ToTPLists[I] = List;
+ }
+
+ FriendDecl *FrD = FriendDecl::Create(Importer.getToContext(), DC,
+ Importer.Import(D->getLocation()),
+ ToFU, Importer.Import(D->getFriendLoc()),
+ ToTPLists);
+
+ Importer.Imported(D, FrD);
+ RD->pushFriendDecl(FrD);
+
+ FrD->setAccess(D->getAccess());
+ FrD->setLexicalDeclContext(LexicalDC);
+ LexicalDC->addDeclInternal(FrD);
+ return FrD;
+}
+
Decl *ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) {
// Import the major distinguishing characteristics of an ivar.
DeclContext *DC, *LexicalDC;
@@ -4859,11 +5049,10 @@ Stmt *ASTNodeImporter::VisitGCCAsmStmt(GCCAsmStmt *S) {
}
SmallVector<Expr *, 4> Exprs(S->getNumOutputs() + S->getNumInputs());
- if (ImportArrayChecked(S->begin_outputs(), S->end_outputs(), Exprs.begin()))
+ if (ImportContainerChecked(S->outputs(), Exprs))
return nullptr;
- if (ImportArrayChecked(S->begin_inputs(), S->end_inputs(),
- Exprs.begin() + S->getNumOutputs()))
+ if (ImportArrayChecked(S->inputs(), Exprs.begin() + S->getNumOutputs()))
return nullptr;
StringLiteral *AsmStr = cast_or_null<StringLiteral>(
@@ -4906,8 +5095,8 @@ Stmt *ASTNodeImporter::VisitNullStmt(NullStmt *S) {
Stmt *ASTNodeImporter::VisitCompoundStmt(CompoundStmt *S) {
llvm::SmallVector<Stmt *, 8> ToStmts(S->size());
-
- if (ImportArrayChecked(S->body_begin(), S->body_end(), ToStmts.begin()))
+
+ if (ImportContainerChecked(S->body(), ToStmts))
return nullptr;
SourceLocation ToLBraceLoc = Importer.Import(S->getLBracLoc());
@@ -5361,7 +5550,7 @@ Expr *ASTNodeImporter::VisitGNUNullExpr(GNUNullExpr *E) {
return nullptr;
return new (Importer.getToContext()) GNUNullExpr(
- T, Importer.Import(E->getExprLoc()));
+ T, Importer.Import(E->getLocStart()));
}
Expr *ASTNodeImporter::VisitPredefinedExpr(PredefinedExpr *E) {
@@ -5375,7 +5564,7 @@ Expr *ASTNodeImporter::VisitPredefinedExpr(PredefinedExpr *E) {
return nullptr;
return new (Importer.getToContext()) PredefinedExpr(
- Importer.Import(E->getExprLoc()), T, E->getIdentType(), SL);
+ Importer.Import(E->getLocStart()), T, E->getIdentType(), SL);
}
Expr *ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) {
@@ -5394,6 +5583,20 @@ Expr *ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) {
if (T.isNull())
return nullptr;
+
+ TemplateArgumentListInfo ToTAInfo;
+ TemplateArgumentListInfo *ResInfo = nullptr;
+ if (E->hasExplicitTemplateArgs()) {
+ for (const auto &FromLoc : E->template_arguments()) {
+ bool Error = false;
+ TemplateArgumentLoc ToTALoc = ImportTemplateArgumentLoc(FromLoc, Error);
+ if (Error)
+ return nullptr;
+ ToTAInfo.addArgument(ToTALoc);
+ }
+ ResInfo = &ToTAInfo;
+ }
+
DeclRefExpr *DRE = DeclRefExpr::Create(Importer.getToContext(),
Importer.Import(E->getQualifierLoc()),
Importer.Import(E->getTemplateKeywordLoc()),
@@ -5401,8 +5604,7 @@ Expr *ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) {
E->refersToEnclosingVariableOrCapture(),
Importer.Import(E->getLocation()),
T, E->getValueKind(),
- FoundD,
- /*FIXME:TemplateArgs=*/nullptr);
+ FoundD, ResInfo);
if (E->hadMultipleCandidates())
DRE->setHadMultipleCandidates(true);
return DRE;
@@ -5411,7 +5613,7 @@ Expr *ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) {
Expr *ASTNodeImporter::VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) {
QualType T = Importer.Import(E->getType());
if (T.isNull())
- return NULL;
+ return nullptr;
return new (Importer.getToContext()) ImplicitValueInitExpr(T);
}
@@ -5580,8 +5782,7 @@ Expr *ASTNodeImporter::VisitParenExpr(ParenExpr *E) {
Expr *ASTNodeImporter::VisitParenListExpr(ParenListExpr *E) {
SmallVector<Expr *, 4> Exprs(E->getNumExprs());
- if (ImportArrayChecked(
- E->getExprs(), E->getExprs() + E->getNumExprs(), Exprs.begin()))
+ if (ImportContainerChecked(E->exprs(), Exprs))
return nullptr;
return new (Importer.getToContext()) ParenListExpr(
@@ -5719,6 +5920,38 @@ Expr *ASTNodeImporter::VisitBinaryConditionalOperator(
T, E->getValueKind(), E->getObjectKind());
}
+Expr *ASTNodeImporter::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) {
+ QualType T = Importer.Import(E->getType());
+ if (T.isNull())
+ return nullptr;
+
+ TypeSourceInfo *ToQueried = Importer.Import(E->getQueriedTypeSourceInfo());
+ if (!ToQueried)
+ return nullptr;
+
+ Expr *Dim = Importer.Import(E->getDimensionExpression());
+ if (!Dim && E->getDimensionExpression())
+ return nullptr;
+
+ return new (Importer.getToContext()) ArrayTypeTraitExpr(
+ Importer.Import(E->getLocStart()), E->getTrait(), ToQueried,
+ E->getValue(), Dim, Importer.Import(E->getLocEnd()), T);
+}
+
+Expr *ASTNodeImporter::VisitExpressionTraitExpr(ExpressionTraitExpr *E) {
+ QualType T = Importer.Import(E->getType());
+ if (T.isNull())
+ return nullptr;
+
+ Expr *ToQueried = Importer.Import(E->getQueriedExpression());
+ if (!ToQueried)
+ return nullptr;
+
+ return new (Importer.getToContext()) ExpressionTraitExpr(
+ Importer.Import(E->getLocStart()), E->getTrait(), ToQueried,
+ E->getValue(), Importer.Import(E->getLocEnd()), T);
+}
+
Expr *ASTNodeImporter::VisitOpaqueValueExpr(OpaqueValueExpr *E) {
QualType T = Importer.Import(E->getType());
if (T.isNull())
@@ -5729,10 +5962,28 @@ Expr *ASTNodeImporter::VisitOpaqueValueExpr(OpaqueValueExpr *E) {
return nullptr;
return new (Importer.getToContext()) OpaqueValueExpr(
- Importer.Import(E->getExprLoc()), T, E->getValueKind(),
+ Importer.Import(E->getLocation()), T, E->getValueKind(),
E->getObjectKind(), SourceExpr);
}
+Expr *ASTNodeImporter::VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
+ QualType T = Importer.Import(E->getType());
+ if (T.isNull())
+ return nullptr;
+
+ Expr *ToLHS = Importer.Import(E->getLHS());
+ if (!ToLHS)
+ return nullptr;
+
+ Expr *ToRHS = Importer.Import(E->getRHS());
+ if (!ToRHS)
+ return nullptr;
+
+ return new (Importer.getToContext()) ArraySubscriptExpr(
+ ToLHS, ToRHS, T, E->getValueKind(), E->getObjectKind(),
+ Importer.Import(E->getRBracketLoc()));
+}
+
Expr *ASTNodeImporter::VisitCompoundAssignOperator(CompoundAssignOperator *E) {
QualType T = Importer.Import(E->getType());
if (T.isNull())
@@ -5763,11 +6014,14 @@ Expr *ASTNodeImporter::VisitCompoundAssignOperator(CompoundAssignOperator *E) {
E->isFPContractable());
}
-static bool ImportCastPath(CastExpr *E, CXXCastPath &Path) {
- if (E->path_empty()) return false;
-
- // TODO: import cast paths
- return true;
+bool ASTNodeImporter::ImportCastPath(CastExpr *CE, CXXCastPath &Path) {
+ for (auto I = CE->path_begin(), E = CE->path_end(); I != E; ++I) {
+ if (CXXBaseSpecifier *Spec = Importer.Import(*I))
+ Path.push_back(Spec);
+ else
+ return true;
+ }
+ return false;
}
Expr *ASTNodeImporter::VisitImplicitCastExpr(ImplicitCastExpr *E) {
@@ -5787,7 +6041,7 @@ Expr *ASTNodeImporter::VisitImplicitCastExpr(ImplicitCastExpr *E) {
SubExpr, &BasePath, E->getValueKind());
}
-Expr *ASTNodeImporter::VisitCStyleCastExpr(CStyleCastExpr *E) {
+Expr *ASTNodeImporter::VisitExplicitCastExpr(ExplicitCastExpr *E) {
QualType T = Importer.Import(E->getType());
if (T.isNull())
return nullptr;
@@ -5804,11 +6058,320 @@ Expr *ASTNodeImporter::VisitCStyleCastExpr(CStyleCastExpr *E) {
if (ImportCastPath(E, BasePath))
return nullptr;
- return CStyleCastExpr::Create(Importer.getToContext(), T,
- E->getValueKind(), E->getCastKind(),
- SubExpr, &BasePath, TInfo,
- Importer.Import(E->getLParenLoc()),
- Importer.Import(E->getRParenLoc()));
+ switch (E->getStmtClass()) {
+ case Stmt::CStyleCastExprClass: {
+ CStyleCastExpr *CCE = cast<CStyleCastExpr>(E);
+ return CStyleCastExpr::Create(Importer.getToContext(), T,
+ E->getValueKind(), E->getCastKind(),
+ SubExpr, &BasePath, TInfo,
+ Importer.Import(CCE->getLParenLoc()),
+ Importer.Import(CCE->getRParenLoc()));
+ }
+
+ case Stmt::CXXFunctionalCastExprClass: {
+ CXXFunctionalCastExpr *FCE = cast<CXXFunctionalCastExpr>(E);
+ return CXXFunctionalCastExpr::Create(Importer.getToContext(), T,
+ E->getValueKind(), TInfo,
+ E->getCastKind(), SubExpr, &BasePath,
+ Importer.Import(FCE->getLParenLoc()),
+ Importer.Import(FCE->getRParenLoc()));
+ }
+
+ case Stmt::ObjCBridgedCastExprClass: {
+ ObjCBridgedCastExpr *OCE = cast<ObjCBridgedCastExpr>(E);
+ return new (Importer.getToContext()) ObjCBridgedCastExpr(
+ Importer.Import(OCE->getLParenLoc()), OCE->getBridgeKind(),
+ E->getCastKind(), Importer.Import(OCE->getBridgeKeywordLoc()),
+ TInfo, SubExpr);
+ }
+ default:
+ break; // just fall through
+ }
+
+ CXXNamedCastExpr *Named = cast<CXXNamedCastExpr>(E);
+ SourceLocation ExprLoc = Importer.Import(Named->getOperatorLoc()),
+ RParenLoc = Importer.Import(Named->getRParenLoc());
+ SourceRange Brackets = Importer.Import(Named->getAngleBrackets());
+
+ switch (E->getStmtClass()) {
+ case Stmt::CXXStaticCastExprClass:
+ return CXXStaticCastExpr::Create(Importer.getToContext(), T,
+ E->getValueKind(), E->getCastKind(),
+ SubExpr, &BasePath, TInfo,
+ ExprLoc, RParenLoc, Brackets);
+
+ case Stmt::CXXDynamicCastExprClass:
+ return CXXDynamicCastExpr::Create(Importer.getToContext(), T,
+ E->getValueKind(), E->getCastKind(),
+ SubExpr, &BasePath, TInfo,
+ ExprLoc, RParenLoc, Brackets);
+
+ case Stmt::CXXReinterpretCastExprClass:
+ return CXXReinterpretCastExpr::Create(Importer.getToContext(), T,
+ E->getValueKind(), E->getCastKind(),
+ SubExpr, &BasePath, TInfo,
+ ExprLoc, RParenLoc, Brackets);
+
+ case Stmt::CXXConstCastExprClass:
+ return CXXConstCastExpr::Create(Importer.getToContext(), T,
+ E->getValueKind(), SubExpr, TInfo, ExprLoc,
+ RParenLoc, Brackets);
+ default:
+ llvm_unreachable("Cast expression of unsupported type!");
+ return nullptr;
+ }
+}
+
+Expr *ASTNodeImporter::VisitOffsetOfExpr(OffsetOfExpr *OE) {
+ QualType T = Importer.Import(OE->getType());
+ if (T.isNull())
+ return nullptr;
+
+ SmallVector<OffsetOfNode, 4> Nodes;
+ for (int I = 0, E = OE->getNumComponents(); I < E; ++I) {
+ const OffsetOfNode &Node = OE->getComponent(I);
+
+ switch (Node.getKind()) {
+ case OffsetOfNode::Array:
+ Nodes.push_back(OffsetOfNode(Importer.Import(Node.getLocStart()),
+ Node.getArrayExprIndex(),
+ Importer.Import(Node.getLocEnd())));
+ break;
+
+ case OffsetOfNode::Base: {
+ CXXBaseSpecifier *BS = Importer.Import(Node.getBase());
+ if (!BS && Node.getBase())
+ return nullptr;
+ Nodes.push_back(OffsetOfNode(BS));
+ break;
+ }
+ case OffsetOfNode::Field: {
+ FieldDecl *FD = cast_or_null<FieldDecl>(Importer.Import(Node.getField()));
+ if (!FD)
+ return nullptr;
+ Nodes.push_back(OffsetOfNode(Importer.Import(Node.getLocStart()), FD,
+ Importer.Import(Node.getLocEnd())));
+ break;
+ }
+ case OffsetOfNode::Identifier: {
+ IdentifierInfo *ToII = Importer.Import(Node.getFieldName());
+ if (!ToII)
+ return nullptr;
+ Nodes.push_back(OffsetOfNode(Importer.Import(Node.getLocStart()), ToII,
+ Importer.Import(Node.getLocEnd())));
+ break;
+ }
+ }
+ }
+
+ SmallVector<Expr *, 4> Exprs(OE->getNumExpressions());
+ for (int I = 0, E = OE->getNumExpressions(); I < E; ++I) {
+ Expr *ToIndexExpr = Importer.Import(OE->getIndexExpr(I));
+ if (!ToIndexExpr)
+ return nullptr;
+ Exprs[I] = ToIndexExpr;
+ }
+
+ TypeSourceInfo *TInfo = Importer.Import(OE->getTypeSourceInfo());
+ if (!TInfo && OE->getTypeSourceInfo())
+ return nullptr;
+
+ return OffsetOfExpr::Create(Importer.getToContext(), T,
+ Importer.Import(OE->getOperatorLoc()),
+ TInfo, Nodes, Exprs,
+ Importer.Import(OE->getRParenLoc()));
+}
+
+Expr *ASTNodeImporter::VisitCXXNoexceptExpr(CXXNoexceptExpr *E) {
+ QualType T = Importer.Import(E->getType());
+ if (T.isNull())
+ return nullptr;
+
+ Expr *Operand = Importer.Import(E->getOperand());
+ if (!Operand)
+ return nullptr;
+
+ CanThrowResult CanThrow;
+ if (E->isValueDependent())
+ CanThrow = CT_Dependent;
+ else
+ CanThrow = E->getValue() ? CT_Can : CT_Cannot;
+
+ return new (Importer.getToContext()) CXXNoexceptExpr(
+ T, Operand, CanThrow,
+ Importer.Import(E->getLocStart()), Importer.Import(E->getLocEnd()));
+}
+
+Expr *ASTNodeImporter::VisitCXXThrowExpr(CXXThrowExpr *E) {
+ QualType T = Importer.Import(E->getType());
+ if (T.isNull())
+ return nullptr;
+
+ Expr *SubExpr = Importer.Import(E->getSubExpr());
+ if (!SubExpr && E->getSubExpr())
+ return nullptr;
+
+ return new (Importer.getToContext()) CXXThrowExpr(
+ SubExpr, T, Importer.Import(E->getThrowLoc()),
+ E->isThrownVariableInScope());
+}
+
+Expr *ASTNodeImporter::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) {
+ ParmVarDecl *Param = cast_or_null<ParmVarDecl>(
+ Importer.Import(E->getParam()));
+ if (!Param)
+ return nullptr;
+
+ return CXXDefaultArgExpr::Create(
+ Importer.getToContext(), Importer.Import(E->getUsedLocation()), Param);
+}
+
+Expr *ASTNodeImporter::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) {
+ QualType T = Importer.Import(E->getType());
+ if (T.isNull())
+ return nullptr;
+
+ TypeSourceInfo *TypeInfo = Importer.Import(E->getTypeSourceInfo());
+ if (!TypeInfo)
+ return nullptr;
+
+ return new (Importer.getToContext()) CXXScalarValueInitExpr(
+ T, TypeInfo, Importer.Import(E->getRParenLoc()));
+}
+
+Expr *ASTNodeImporter::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) {
+ Expr *SubExpr = Importer.Import(E->getSubExpr());
+ if (!SubExpr)
+ return nullptr;
+
+ auto *Dtor = cast_or_null<CXXDestructorDecl>(
+ Importer.Import(const_cast<CXXDestructorDecl *>(
+ E->getTemporary()->getDestructor())));
+ if (!Dtor)
+ return nullptr;
+
+ ASTContext &ToCtx = Importer.getToContext();
+ CXXTemporary *Temp = CXXTemporary::Create(ToCtx, Dtor);
+ return CXXBindTemporaryExpr::Create(ToCtx, Temp, SubExpr);
+}
+
+Expr *ASTNodeImporter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *CE) {
+ QualType T = Importer.Import(CE->getType());
+ if (T.isNull())
+ return nullptr;
+
+ SmallVector<Expr *, 8> Args(CE->getNumArgs());
+ if (ImportContainerChecked(CE->arguments(), Args))
+ return nullptr;
+
+ auto *Ctor = cast_or_null<CXXConstructorDecl>(
+ Importer.Import(CE->getConstructor()));
+ if (!Ctor)
+ return nullptr;
+
+ return CXXTemporaryObjectExpr::Create(
+ Importer.getToContext(), T,
+ Importer.Import(CE->getLocStart()),
+ Ctor,
+ CE->isElidable(),
+ Args,
+ CE->hadMultipleCandidates(),
+ CE->isListInitialization(),
+ CE->isStdInitListInitialization(),
+ CE->requiresZeroInitialization(),
+ CE->getConstructionKind(),
+ Importer.Import(CE->getParenOrBraceRange()));
+}
+
+Expr *
+ASTNodeImporter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) {
+ QualType T = Importer.Import(E->getType());
+ if (T.isNull())
+ return nullptr;
+
+ Expr *TempE = Importer.Import(E->GetTemporaryExpr());
+ if (!TempE)
+ return nullptr;
+
+ ValueDecl *ExtendedBy = cast_or_null<ValueDecl>(
+ Importer.Import(const_cast<ValueDecl *>(E->getExtendingDecl())));
+ if (!ExtendedBy && E->getExtendingDecl())
+ return nullptr;
+
+ auto *ToMTE = new (Importer.getToContext()) MaterializeTemporaryExpr(
+ T, TempE, E->isBoundToLvalueReference());
+
+ // FIXME: Should ManglingNumber get numbers associated with 'to' context?
+ ToMTE->setExtendingDecl(ExtendedBy, E->getManglingNumber());
+ return ToMTE;
+}
+
+Expr *ASTNodeImporter::VisitCXXNewExpr(CXXNewExpr *CE) {
+ QualType T = Importer.Import(CE->getType());
+ if (T.isNull())
+ return nullptr;
+
+ SmallVector<Expr *, 4> PlacementArgs(CE->getNumPlacementArgs());
+ if (ImportContainerChecked(CE->placement_arguments(), PlacementArgs))
+ return nullptr;
+
+ FunctionDecl *OperatorNewDecl = cast_or_null<FunctionDecl>(
+ Importer.Import(CE->getOperatorNew()));
+ if (!OperatorNewDecl && CE->getOperatorNew())
+ return nullptr;
+
+ FunctionDecl *OperatorDeleteDecl = cast_or_null<FunctionDecl>(
+ Importer.Import(CE->getOperatorDelete()));
+ if (!OperatorDeleteDecl && CE->getOperatorDelete())
+ return nullptr;
+
+ Expr *ToInit = Importer.Import(CE->getInitializer());
+ if (!ToInit && CE->getInitializer())
+ return nullptr;
+
+ TypeSourceInfo *TInfo = Importer.Import(CE->getAllocatedTypeSourceInfo());
+ if (!TInfo)
+ return nullptr;
+
+ Expr *ToArrSize = Importer.Import(CE->getArraySize());
+ if (!ToArrSize && CE->getArraySize())
+ return nullptr;
+
+ return new (Importer.getToContext()) CXXNewExpr(
+ Importer.getToContext(),
+ CE->isGlobalNew(),
+ OperatorNewDecl, OperatorDeleteDecl,
+ CE->passAlignment(),
+ CE->doesUsualArrayDeleteWantSize(),
+ PlacementArgs,
+ Importer.Import(CE->getTypeIdParens()),
+ ToArrSize, CE->getInitializationStyle(), ToInit, T, TInfo,
+ Importer.Import(CE->getSourceRange()),
+ Importer.Import(CE->getDirectInitRange()));
+}
+
+Expr *ASTNodeImporter::VisitCXXDeleteExpr(CXXDeleteExpr *E) {
+ QualType T = Importer.Import(E->getType());
+ if (T.isNull())
+ return nullptr;
+
+ FunctionDecl *OperatorDeleteDecl = cast_or_null<FunctionDecl>(
+ Importer.Import(E->getOperatorDelete()));
+ if (!OperatorDeleteDecl && E->getOperatorDelete())
+ return nullptr;
+
+ Expr *ToArg = Importer.Import(E->getArgument());
+ if (!ToArg && E->getArgument())
+ return nullptr;
+
+ return new (Importer.getToContext()) CXXDeleteExpr(
+ T, E->isGlobalDelete(),
+ E->isArrayForm(),
+ E->isArrayFormAsWritten(),
+ E->doesUsualArrayDeleteWantSize(),
+ OperatorDeleteDecl,
+ ToArg,
+ Importer.Import(E->getLocStart()));
}
Expr *ASTNodeImporter::VisitCXXConstructExpr(CXXConstructExpr *E) {
@@ -5822,8 +6385,7 @@ Expr *ASTNodeImporter::VisitCXXConstructExpr(CXXConstructExpr *E) {
return nullptr;
SmallVector<Expr *, 6> ToArgs(E->getNumArgs());
- if (ImportArrayChecked(E->getArgs(), E->getArgs() + E->getNumArgs(),
- ToArgs.begin()))
+ if (ImportContainerChecked(E->arguments(), ToArgs))
return nullptr;
return CXXConstructExpr::Create(Importer.getToContext(), T,
@@ -5837,6 +6399,24 @@ Expr *ASTNodeImporter::VisitCXXConstructExpr(CXXConstructExpr *E) {
Importer.Import(E->getParenOrBraceRange()));
}
+Expr *ASTNodeImporter::VisitExprWithCleanups(ExprWithCleanups *EWC) {
+ Expr *SubExpr = Importer.Import(EWC->getSubExpr());
+ if (!SubExpr && EWC->getSubExpr())
+ return nullptr;
+
+ SmallVector<ExprWithCleanups::CleanupObject, 8> Objs(EWC->getNumObjects());
+ for (unsigned I = 0, E = EWC->getNumObjects(); I < E; I++)
+ if (ExprWithCleanups::CleanupObject Obj =
+ cast_or_null<BlockDecl>(Importer.Import(EWC->getObject(I))))
+ Objs[I] = Obj;
+ else
+ return nullptr;
+
+ return ExprWithCleanups::Create(Importer.getToContext(),
+ SubExpr, EWC->cleanupsHaveSideEffects(),
+ Objs);
+}
+
Expr *ASTNodeImporter::VisitCXXMemberCallExpr(CXXMemberCallExpr *E) {
QualType T = Importer.Import(E->getType());
if (T.isNull())
@@ -5847,8 +6427,7 @@ Expr *ASTNodeImporter::VisitCXXMemberCallExpr(CXXMemberCallExpr *E) {
return nullptr;
SmallVector<Expr *, 4> ToArgs(E->getNumArgs());
-
- if (ImportArrayChecked(E->arg_begin(), E->arg_end(), ToArgs.begin()))
+ if (ImportContainerChecked(E->arguments(), ToArgs))
return nullptr;
return new (Importer.getToContext()) CXXMemberCallExpr(
@@ -5949,8 +6528,7 @@ Expr *ASTNodeImporter::VisitInitListExpr(InitListExpr *ILE) {
return nullptr;
llvm::SmallVector<Expr *, 4> Exprs(ILE->getNumInits());
- if (ImportArrayChecked(
- ILE->getInits(), ILE->getInits() + ILE->getNumInits(), Exprs.begin()))
+ if (ImportContainerChecked(ILE->inits(), Exprs))
return nullptr;
ASTContext &ToCtx = Importer.getToContext();
@@ -5988,6 +6566,30 @@ Expr *ASTNodeImporter::VisitInitListExpr(InitListExpr *ILE) {
return To;
}
+Expr *ASTNodeImporter::VisitArrayInitLoopExpr(ArrayInitLoopExpr *E) {
+ QualType ToType = Importer.Import(E->getType());
+ if (ToType.isNull())
+ return nullptr;
+
+ Expr *ToCommon = Importer.Import(E->getCommonExpr());
+ if (!ToCommon && E->getCommonExpr())
+ return nullptr;
+
+ Expr *ToSubExpr = Importer.Import(E->getSubExpr());
+ if (!ToSubExpr && E->getSubExpr())
+ return nullptr;
+
+ return new (Importer.getToContext())
+ ArrayInitLoopExpr(ToType, ToCommon, ToSubExpr);
+}
+
+Expr *ASTNodeImporter::VisitArrayInitIndexExpr(ArrayInitIndexExpr *E) {
+ QualType ToType = Importer.Import(E->getType());
+ if (ToType.isNull())
+ return nullptr;
+ return new (Importer.getToContext()) ArrayInitIndexExpr(ToType);
+}
+
Expr *ASTNodeImporter::VisitCXXDefaultInitExpr(CXXDefaultInitExpr *DIE) {
FieldDecl *ToField = llvm::dyn_cast_or_null<FieldDecl>(
Importer.Import(DIE->getField()));
@@ -6376,10 +6978,10 @@ SourceLocation ASTImporter::Import(SourceLocation FromLoc) {
SourceManager &FromSM = FromContext.getSourceManager();
- // For now, map everything down to its spelling location, so that we
+ // For now, map everything down to its file location, so that we
// don't have to import macro expansions.
// FIXME: Import macro expansions!
- FromLoc = FromSM.getSpellingLoc(FromLoc);
+ FromLoc = FromSM.getFileLoc(FromLoc);
std::pair<FileID, unsigned> Decomposed = FromSM.getDecomposedLoc(FromLoc);
SourceManager &ToSM = ToContext.getSourceManager();
FileID ToFileID = Import(Decomposed.first);
@@ -6478,31 +7080,27 @@ CXXCtorInitializer *ASTImporter::Import(CXXCtorInitializer *From) {
return new (ToContext)
CXXCtorInitializer(ToContext, ToTInfo, Import(From->getLParenLoc()),
ToExpr, Import(From->getRParenLoc()));
- } else if (unsigned NumArrayIndices = From->getNumArrayIndices()) {
- FieldDecl *ToField =
- llvm::cast_or_null<FieldDecl>(Import(From->getMember()));
- if (!ToField && From->getMember())
- return nullptr;
-
- SmallVector<VarDecl *, 4> ToAIs(NumArrayIndices);
-
- for (unsigned AII = 0; AII < NumArrayIndices; ++AII) {
- VarDecl *ToArrayIndex =
- dyn_cast_or_null<VarDecl>(Import(From->getArrayIndex(AII)));
- if (!ToArrayIndex && From->getArrayIndex(AII))
- return nullptr;
- }
-
- return CXXCtorInitializer::Create(
- ToContext, ToField, Import(From->getMemberLocation()),
- Import(From->getLParenLoc()), ToExpr, Import(From->getRParenLoc()),
- ToAIs.data(), NumArrayIndices);
} else {
return nullptr;
}
}
+CXXBaseSpecifier *ASTImporter::Import(const CXXBaseSpecifier *BaseSpec) {
+ auto Pos = ImportedCXXBaseSpecifiers.find(BaseSpec);
+ if (Pos != ImportedCXXBaseSpecifiers.end())
+ return Pos->second;
+
+ CXXBaseSpecifier *Imported = new (ToContext) CXXBaseSpecifier(
+ Import(BaseSpec->getSourceRange()),
+ BaseSpec->isVirtual(), BaseSpec->isBaseOfClass(),
+ BaseSpec->getAccessSpecifierAsWritten(),
+ Import(BaseSpec->getTypeSourceInfo()),
+ Import(BaseSpec->getEllipsisLoc()));
+ ImportedCXXBaseSpecifiers[BaseSpec] = Imported;
+ return Imported;
+}
+
void ASTImporter::ImportDefinition(Decl *From) {
Decl *To = Import(From);
if (!To)
diff --git a/lib/AST/ASTTypeTraits.cpp b/lib/AST/ASTTypeTraits.cpp
index 2336c98fe049..461084ce707c 100644
--- a/lib/AST/ASTTypeTraits.cpp
+++ b/lib/AST/ASTTypeTraits.cpp
@@ -23,6 +23,7 @@ namespace ast_type_traits {
const ASTNodeKind::KindInfo ASTNodeKind::AllKindInfo[] = {
{ NKI_None, "<None>" },
{ NKI_None, "TemplateArgument" },
+ { NKI_None, "TemplateName" },
{ NKI_None, "NestedNameSpecifierLoc" },
{ NKI_None, "QualType" },
{ NKI_None, "TypeLoc" },
@@ -109,6 +110,8 @@ void DynTypedNode::print(llvm::raw_ostream &OS,
const PrintingPolicy &PP) const {
if (const TemplateArgument *TA = get<TemplateArgument>())
TA->print(PP, OS);
+ else if (const TemplateName *TN = get<TemplateName>())
+ TN->print(OS, PP);
else if (const NestedNameSpecifier *NNS = get<NestedNameSpecifier>())
NNS->print(OS, PP);
else if (const NestedNameSpecifierLoc *NNSL = get<NestedNameSpecifierLoc>())
@@ -132,6 +135,8 @@ void DynTypedNode::dump(llvm::raw_ostream &OS, SourceManager &SM) const {
D->dump(OS);
else if (const Stmt *S = get<Stmt>())
S->dump(OS, SM);
+ else if (const Type *T = get<Type>())
+ T->dump(OS);
else
OS << "Unable to dump values of type " << NodeKind.asStringRef() << "\n";
}
diff --git a/lib/AST/AttrImpl.cpp b/lib/AST/AttrImpl.cpp
index cb608700133c..b06b50c9b4b8 100644
--- a/lib/AST/AttrImpl.cpp
+++ b/lib/AST/AttrImpl.cpp
@@ -11,11 +11,10 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/AST/Attr.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/Attr.h"
#include "clang/AST/Expr.h"
#include "clang/AST/Type.h"
-#include "llvm/ADT/StringSwitch.h"
using namespace clang;
#include "clang/AST/AttrImpl.inc"
diff --git a/lib/AST/CXXABI.h b/lib/AST/CXXABI.h
index c23b9191c7ab..924ef00e8147 100644
--- a/lib/AST/CXXABI.h
+++ b/lib/AST/CXXABI.h
@@ -43,7 +43,8 @@ public:
virtual bool isNearlyEmpty(const CXXRecordDecl *RD) const = 0;
/// Returns a new mangling number context for this C++ ABI.
- virtual MangleNumberingContext *createMangleNumberingContext() const = 0;
+ virtual std::unique_ptr<MangleNumberingContext>
+ createMangleNumberingContext() const = 0;
/// Adds a mapping from class to copy constructor for this C++ ABI.
virtual void addCopyConstructorForExceptionObject(CXXRecordDecl *,
@@ -53,12 +54,6 @@ public:
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;
-
virtual void addTypedefNameForUnnamedTagDecl(TagDecl *TD,
TypedefNameDecl *DD) = 0;
diff --git a/lib/AST/CXXInheritance.cpp b/lib/AST/CXXInheritance.cpp
index 6a6ca76a0165..a97d6a22e7b3 100644
--- a/lib/AST/CXXInheritance.cpp
+++ b/lib/AST/CXXInheritance.cpp
@@ -16,7 +16,6 @@
#include "clang/AST/RecordLayout.h"
#include "llvm/ADT/SetVector.h"
#include <algorithm>
-#include <set>
using namespace clang;
diff --git a/lib/AST/Comment.cpp b/lib/AST/Comment.cpp
index 893bdc5c17bf..7a7d3dd8304e 100644
--- a/lib/AST/Comment.cpp
+++ b/lib/AST/Comment.cpp
@@ -7,14 +7,13 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/AST/ASTContext.h"
#include "clang/AST/Comment.h"
+#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/Basic/CharInfo.h"
#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/raw_ostream.h"
namespace clang {
namespace comments {
@@ -114,6 +113,65 @@ bool ParagraphComment::isWhitespaceNoCache() const {
return true;
}
+static TypeLoc lookThroughTypedefOrTypeAliasLocs(TypeLoc &SrcTL) {
+ TypeLoc TL = SrcTL.IgnoreParens();
+
+ // Look through qualified types.
+ if (QualifiedTypeLoc QualifiedTL = TL.getAs<QualifiedTypeLoc>())
+ return QualifiedTL.getUnqualifiedLoc();
+ // Look through pointer types.
+ if (PointerTypeLoc PointerTL = TL.getAs<PointerTypeLoc>())
+ return PointerTL.getPointeeLoc().getUnqualifiedLoc();
+ // Look through reference types.
+ if (ReferenceTypeLoc ReferenceTL = TL.getAs<ReferenceTypeLoc>())
+ return ReferenceTL.getPointeeLoc().getUnqualifiedLoc();
+ // Look through adjusted types.
+ if (AdjustedTypeLoc ATL = TL.getAs<AdjustedTypeLoc>())
+ return ATL.getOriginalLoc();
+ if (BlockPointerTypeLoc BlockPointerTL = TL.getAs<BlockPointerTypeLoc>())
+ return BlockPointerTL.getPointeeLoc().getUnqualifiedLoc();
+ if (MemberPointerTypeLoc MemberPointerTL = TL.getAs<MemberPointerTypeLoc>())
+ return MemberPointerTL.getPointeeLoc().getUnqualifiedLoc();
+ if (ElaboratedTypeLoc ETL = TL.getAs<ElaboratedTypeLoc>())
+ return ETL.getNamedTypeLoc();
+
+ return TL;
+}
+
+static bool getFunctionTypeLoc(TypeLoc TL, FunctionTypeLoc &ResFTL) {
+ TypeLoc PrevTL;
+ while (PrevTL != TL) {
+ PrevTL = TL;
+ TL = lookThroughTypedefOrTypeAliasLocs(TL);
+ }
+
+ if (FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>()) {
+ ResFTL = FTL;
+ return true;
+ }
+
+ if (TemplateSpecializationTypeLoc STL =
+ TL.getAs<TemplateSpecializationTypeLoc>()) {
+ // If we have a typedef to a template specialization with exactly one
+ // template argument of a function type, this looks like std::function,
+ // boost::function, or other function wrapper. Treat these typedefs as
+ // functions.
+ if (STL.getNumArgs() != 1)
+ return false;
+ TemplateArgumentLoc MaybeFunction = STL.getArgLoc(0);
+ if (MaybeFunction.getArgument().getKind() != TemplateArgument::Type)
+ return false;
+ TypeSourceInfo *MaybeFunctionTSI = MaybeFunction.getTypeSourceInfo();
+ TypeLoc TL = MaybeFunctionTSI->getTypeLoc().getUnqualifiedLoc();
+ if (FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>()) {
+ ResFTL = FTL;
+ return true;
+ }
+ }
+
+ return false;
+}
+
const char *ParamCommandComment::getDirectionAsString(PassDirection D) {
switch (D) {
case ParamCommandComment::In:
@@ -227,90 +285,45 @@ void DeclInfo::fill() {
case Decl::Namespace:
Kind = NamespaceKind;
break;
+ case Decl::TypeAlias:
case Decl::Typedef: {
Kind = TypedefKind;
- // If this is a typedef to something we consider a function, extract
+ // If this is a typedef / using to something we consider a function, extract
// arguments and return type.
- const TypedefDecl *TD = cast<TypedefDecl>(CommentDecl);
- const TypeSourceInfo *TSI = TD->getTypeSourceInfo();
+ const TypeSourceInfo *TSI =
+ K == Decl::Typedef
+ ? cast<TypedefDecl>(CommentDecl)->getTypeSourceInfo()
+ : cast<TypeAliasDecl>(CommentDecl)->getTypeSourceInfo();
if (!TSI)
break;
TypeLoc TL = TSI->getTypeLoc().getUnqualifiedLoc();
- while (true) {
- TL = TL.IgnoreParens();
- // Look through qualified types.
- if (QualifiedTypeLoc QualifiedTL = TL.getAs<QualifiedTypeLoc>()) {
- TL = QualifiedTL.getUnqualifiedLoc();
- continue;
- }
- // Look through pointer types.
- if (PointerTypeLoc PointerTL = TL.getAs<PointerTypeLoc>()) {
- TL = PointerTL.getPointeeLoc().getUnqualifiedLoc();
- continue;
- }
- // Look through reference types.
- if (ReferenceTypeLoc ReferenceTL = TL.getAs<ReferenceTypeLoc>()) {
- TL = ReferenceTL.getPointeeLoc().getUnqualifiedLoc();
- continue;
- }
- // Look through adjusted types.
- if (AdjustedTypeLoc ATL = TL.getAs<AdjustedTypeLoc>()) {
- TL = ATL.getOriginalLoc();
- continue;
- }
- if (BlockPointerTypeLoc BlockPointerTL =
- TL.getAs<BlockPointerTypeLoc>()) {
- TL = BlockPointerTL.getPointeeLoc().getUnqualifiedLoc();
- continue;
- }
- if (MemberPointerTypeLoc MemberPointerTL =
- TL.getAs<MemberPointerTypeLoc>()) {
- TL = MemberPointerTL.getPointeeLoc().getUnqualifiedLoc();
- continue;
- }
- if (ElaboratedTypeLoc ETL = TL.getAs<ElaboratedTypeLoc>()) {
- TL = ETL.getNamedTypeLoc();
- continue;
- }
- // Is this a typedef for a function type?
- if (FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>()) {
- Kind = FunctionKind;
- ParamVars = FTL.getParams();
- ReturnType = FTL.getReturnLoc().getType();
- break;
- }
- if (TemplateSpecializationTypeLoc STL =
- TL.getAs<TemplateSpecializationTypeLoc>()) {
- // If we have a typedef to a template specialization with exactly one
- // template argument of a function type, this looks like std::function,
- // boost::function, or other function wrapper. Treat these typedefs as
- // functions.
- if (STL.getNumArgs() != 1)
- break;
- TemplateArgumentLoc MaybeFunction = STL.getArgLoc(0);
- if (MaybeFunction.getArgument().getKind() != TemplateArgument::Type)
- break;
- TypeSourceInfo *MaybeFunctionTSI = MaybeFunction.getTypeSourceInfo();
- TypeLoc TL = MaybeFunctionTSI->getTypeLoc().getUnqualifiedLoc();
- if (FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>()) {
- Kind = FunctionKind;
- ParamVars = FTL.getParams();
- ReturnType = FTL.getReturnLoc().getType();
- }
- break;
- }
- break;
+ FunctionTypeLoc FTL;
+ if (getFunctionTypeLoc(TL, FTL)) {
+ Kind = FunctionKind;
+ ParamVars = FTL.getParams();
+ ReturnType = FTL.getReturnLoc().getType();
}
break;
}
- case Decl::TypeAlias:
- Kind = TypedefKind;
- break;
case Decl::TypeAliasTemplate: {
const TypeAliasTemplateDecl *TAT = cast<TypeAliasTemplateDecl>(CommentDecl);
Kind = TypedefKind;
TemplateKind = Template;
TemplateParameters = TAT->getTemplateParameters();
+ TypeAliasDecl *TAD = TAT->getTemplatedDecl();
+ if (!TAD)
+ break;
+
+ const TypeSourceInfo *TSI = TAD->getTypeSourceInfo();
+ if (!TSI)
+ break;
+ TypeLoc TL = TSI->getTypeLoc().getUnqualifiedLoc();
+ FunctionTypeLoc FTL;
+ if (getFunctionTypeLoc(TL, FTL)) {
+ Kind = FunctionKind;
+ ParamVars = FTL.getParams();
+ ReturnType = FTL.getReturnLoc().getType();
+ }
break;
}
case Decl::Enum:
diff --git a/lib/AST/CommentBriefParser.cpp b/lib/AST/CommentBriefParser.cpp
index 090b9211d4c1..eecea8fc11df 100644
--- a/lib/AST/CommentBriefParser.cpp
+++ b/lib/AST/CommentBriefParser.cpp
@@ -9,7 +9,6 @@
#include "clang/AST/CommentBriefParser.h"
#include "clang/AST/CommentCommandTraits.h"
-#include "llvm/ADT/StringSwitch.h"
namespace clang {
namespace comments {
diff --git a/lib/AST/CommentLexer.cpp b/lib/AST/CommentLexer.cpp
index 57bfef08df6e..65d0f56f09ab 100644
--- a/lib/AST/CommentLexer.cpp
+++ b/lib/AST/CommentLexer.cpp
@@ -378,15 +378,17 @@ void Lexer::lexCommentText(Token &T) {
if ((Info = Traits.getTypoCorrectCommandInfo(CommandName))) {
StringRef CorrectedName = Info->Name;
SourceLocation Loc = getSourceLocation(BufferPtr);
- SourceRange CommandRange(Loc.getLocWithOffset(1),
- getSourceLocation(TokenPtr));
+ SourceLocation EndLoc = getSourceLocation(TokenPtr);
+ SourceRange FullRange = SourceRange(Loc, EndLoc);
+ SourceRange CommandRange(Loc.getLocWithOffset(1), EndLoc);
Diag(Loc, diag::warn_correct_comment_command_name)
- << CommandName << CorrectedName
+ << FullRange << CommandName << CorrectedName
<< FixItHint::CreateReplacement(CommandRange, CorrectedName);
} else {
formTokenWithChars(T, TokenPtr, tok::unknown_command);
T.setUnknownCommandName(CommandName);
- Diag(T.getLocation(), diag::warn_unknown_comment_command_name);
+ Diag(T.getLocation(), diag::warn_unknown_comment_command_name)
+ << SourceRange(T.getLocation(), T.getEndLocation());
return;
}
}
diff --git a/lib/AST/CommentParser.cpp b/lib/AST/CommentParser.cpp
index cb37ec35f4d3..c1c04239f58e 100644
--- a/lib/AST/CommentParser.cpp
+++ b/lib/AST/CommentParser.cpp
@@ -40,11 +40,11 @@ class TextTokenRetokenizer {
/// A position in \c Toks.
struct Position {
- unsigned CurToken;
const char *BufferStart;
const char *BufferEnd;
const char *BufferPtr;
SourceLocation BufferStartLoc;
+ unsigned CurToken;
};
/// Current position in Toks.
diff --git a/lib/AST/CommentSema.cpp b/lib/AST/CommentSema.cpp
index f5f4f70dcbbf..d39a9b26b2a8 100644
--- a/lib/AST/CommentSema.cpp
+++ b/lib/AST/CommentSema.cpp
@@ -950,20 +950,19 @@ unsigned Sema::resolveParmVarReference(StringRef Name,
namespace {
class SimpleTypoCorrector {
+ const NamedDecl *BestDecl;
+
StringRef Typo;
const unsigned MaxEditDistance;
- const NamedDecl *BestDecl;
unsigned BestEditDistance;
unsigned BestIndex;
unsigned NextIndex;
public:
- SimpleTypoCorrector(StringRef Typo) :
- Typo(Typo), MaxEditDistance((Typo.size() + 2) / 3),
- BestDecl(nullptr), BestEditDistance(MaxEditDistance + 1),
- BestIndex(0), NextIndex(0)
- { }
+ explicit SimpleTypoCorrector(StringRef Typo)
+ : BestDecl(nullptr), Typo(Typo), MaxEditDistance((Typo.size() + 2) / 3),
+ BestEditDistance(MaxEditDistance + 1), BestIndex(0), NextIndex(0) {}
void addDecl(const NamedDecl *ND);
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index d1e8d25ea044..c3fa1c87affd 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -1395,6 +1395,10 @@ static LinkageInfo getLVForDecl(const NamedDecl *D,
return clang::LinkageComputer::getLVForDecl(D, computation);
}
+void NamedDecl::printName(raw_ostream &os) const {
+ os << Name;
+}
+
std::string NamedDecl::getQualifiedNameAsString() const {
std::string QualName;
llvm::raw_string_ostream OS(QualName);
@@ -1481,7 +1485,7 @@ void NamedDecl::printQualifiedName(raw_ostream &OS,
OS << "::";
}
- if (getDeclName())
+ if (getDeclName() || isa<DecompositionDecl>(this))
OS << *this;
else
OS << "(anonymous)";
@@ -1922,6 +1926,9 @@ VarDecl::isThisDeclarationADefinition(ASTContext &C) const {
//
// FIXME: How do you declare (but not define) a partial specialization of
// a static data member template outside the containing class?
+ if (isThisDeclarationADemotedDefinition())
+ return DeclarationOnly;
+
if (isStaticDataMember()) {
if (isOutOfLine() &&
!(getCanonicalDecl()->isInline() &&
@@ -2246,6 +2253,56 @@ bool VarDecl::checkInitIsICE() const {
return Eval->IsICE;
}
+VarDecl *VarDecl::getTemplateInstantiationPattern() const {
+ // If it's a variable template specialization, find the template or partial
+ // specialization from which it was instantiated.
+ if (auto *VDTemplSpec = dyn_cast<VarTemplateSpecializationDecl>(this)) {
+ auto From = VDTemplSpec->getInstantiatedFrom();
+ if (auto *VTD = From.dyn_cast<VarTemplateDecl *>()) {
+ while (auto *NewVTD = VTD->getInstantiatedFromMemberTemplate()) {
+ if (NewVTD->isMemberSpecialization())
+ break;
+ VTD = NewVTD;
+ }
+ return VTD->getTemplatedDecl()->getDefinition();
+ }
+ if (auto *VTPSD =
+ From.dyn_cast<VarTemplatePartialSpecializationDecl *>()) {
+ while (auto *NewVTPSD = VTPSD->getInstantiatedFromMember()) {
+ if (NewVTPSD->isMemberSpecialization())
+ break;
+ VTPSD = NewVTPSD;
+ }
+ return VTPSD->getDefinition();
+ }
+ }
+
+ if (MemberSpecializationInfo *MSInfo = getMemberSpecializationInfo()) {
+ if (isTemplateInstantiation(MSInfo->getTemplateSpecializationKind())) {
+ VarDecl *VD = getInstantiatedFromStaticDataMember();
+ while (auto *NewVD = VD->getInstantiatedFromStaticDataMember())
+ VD = NewVD;
+ return VD->getDefinition();
+ }
+ }
+
+ if (VarTemplateDecl *VarTemplate = getDescribedVarTemplate()) {
+
+ while (VarTemplate->getInstantiatedFromMemberTemplate()) {
+ if (VarTemplate->isMemberSpecialization())
+ break;
+ VarTemplate = VarTemplate->getInstantiatedFromMemberTemplate();
+ }
+
+ assert((!VarTemplate->getTemplatedDecl() ||
+ !isTemplateInstantiation(getTemplateSpecializationKind())) &&
+ "couldn't find pattern for variable instantiation");
+
+ return VarTemplate->getTemplatedDecl();
+ }
+ return nullptr;
+}
+
VarDecl *VarDecl::getInstantiatedFromStaticDataMember() const {
if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo())
return cast<VarDecl>(MSI->getInstantiatedFrom());
@@ -2592,7 +2649,7 @@ bool FunctionDecl::isReplaceableGlobalAllocationFunction() const {
return false;
const auto *FPT = getType()->castAs<FunctionProtoType>();
- if (FPT->getNumParams() == 0 || FPT->getNumParams() > 2 || FPT->isVariadic())
+ if (FPT->getNumParams() == 0 || FPT->getNumParams() > 3 || FPT->isVariadic())
return false;
// If this is a single-parameter function, it must be a replaceable global
@@ -2600,20 +2657,42 @@ bool FunctionDecl::isReplaceableGlobalAllocationFunction() const {
if (FPT->getNumParams() == 1)
return true;
- // Otherwise, we're looking for a second parameter whose type is
- // 'const std::nothrow_t &', or, in C++1y, 'std::size_t'.
- QualType Ty = FPT->getParamType(1);
+ unsigned Params = 1;
+ QualType Ty = FPT->getParamType(Params);
ASTContext &Ctx = getASTContext();
+
+ auto Consume = [&] {
+ ++Params;
+ Ty = Params < FPT->getNumParams() ? FPT->getParamType(Params) : QualType();
+ };
+
+ // In C++14, the next parameter can be a 'std::size_t' for sized delete.
+ bool IsSizedDelete = false;
if (Ctx.getLangOpts().SizedDeallocation &&
- Ctx.hasSameType(Ty, Ctx.getSizeType()))
- return true;
- if (!Ty->isReferenceType())
- return false;
- Ty = Ty->getPointeeType();
- if (Ty.getCVRQualifiers() != Qualifiers::Const)
- return false;
- const CXXRecordDecl *RD = Ty->getAsCXXRecordDecl();
- return RD && isNamed(RD, "nothrow_t") && RD->isInStdNamespace();
+ (getDeclName().getCXXOverloadedOperator() == OO_Delete ||
+ getDeclName().getCXXOverloadedOperator() == OO_Array_Delete) &&
+ Ctx.hasSameType(Ty, Ctx.getSizeType())) {
+ IsSizedDelete = true;
+ Consume();
+ }
+
+ // In C++17, the next parameter can be a 'std::align_val_t' for aligned
+ // new/delete.
+ if (Ctx.getLangOpts().AlignedAllocation && !Ty.isNull() && Ty->isAlignValT())
+ Consume();
+
+ // Finally, if this is not a sized delete, the final parameter can
+ // be a 'const std::nothrow_t&'.
+ if (!IsSizedDelete && !Ty.isNull() && Ty->isReferenceType()) {
+ Ty = Ty->getPointeeType();
+ if (Ty.getCVRQualifiers() != Qualifiers::Const)
+ return false;
+ const CXXRecordDecl *RD = Ty->getAsCXXRecordDecl();
+ if (RD && isNamed(RD, "nothrow_t") && RD->isInStdNamespace())
+ Consume();
+ }
+
+ return Params == FPT->getNumParams();
}
LanguageLinkage FunctionDecl::getLanguageLinkage() const {
@@ -2653,9 +2732,14 @@ bool FunctionDecl::isGlobal() const {
}
bool FunctionDecl::isNoReturn() const {
- return hasAttr<NoReturnAttr>() || hasAttr<CXX11NoReturnAttr>() ||
- hasAttr<C11NoReturnAttr>() ||
- getType()->getAs<FunctionType>()->getNoReturnAttr();
+ if (hasAttr<NoReturnAttr>() || hasAttr<CXX11NoReturnAttr>() ||
+ hasAttr<C11NoReturnAttr>())
+ return true;
+
+ if (auto *FnTy = getType()->getAs<FunctionType>())
+ return FnTy->getNoReturnAttr();
+
+ return false;
}
void
@@ -2756,28 +2840,6 @@ void FunctionDecl::setParams(ASTContext &C,
}
}
-void FunctionDecl::setDeclsInPrototypeScope(ArrayRef<NamedDecl *> NewDecls) {
- assert(DeclsInPrototypeScope.empty() && "Already has prototype decls!");
-
- if (!NewDecls.empty()) {
- NamedDecl **A = new (getASTContext()) NamedDecl*[NewDecls.size()];
- std::copy(NewDecls.begin(), NewDecls.end(), A);
- DeclsInPrototypeScope = llvm::makeArrayRef(A, NewDecls.size());
- // Move declarations introduced in prototype to the function context.
- for (auto I : NewDecls) {
- DeclContext *DC = I->getDeclContext();
- // Forward-declared reference to an enumeration is not added to
- // declaration scope, so skip declaration that is absent from its
- // declaration contexts.
- if (DC->containsDecl(I)) {
- DC->removeDecl(I);
- I->setDeclContext(this);
- addDecl(I);
- }
- }
- }
-}
-
/// getMinRequiredArguments - Returns the minimum number of arguments
/// needed to call this function. This may be fewer than the number of
/// function parameters, if some of the parameters have default
@@ -2964,7 +3026,8 @@ const Attr *FunctionDecl::getUnusedResultAttr() const {
/// an externally visible symbol, but "extern inline" will not create an
/// externally visible symbol.
bool FunctionDecl::isInlineDefinitionExternallyVisible() const {
- assert(doesThisDeclarationHaveABody() && "Must have the function definition");
+ assert((doesThisDeclarationHaveABody() || willHaveBody()) &&
+ "Must be a function definition");
assert(isInlined() && "Function must be inline");
ASTContext &Context = getASTContext();
@@ -3408,6 +3471,10 @@ unsigned FunctionDecl::getMemoryFunctionKind() const {
case Builtin::BIstrlen:
return Builtin::BIstrlen;
+ case Builtin::BI__builtin_bzero:
+ case Builtin::BIbzero:
+ return Builtin::BIbzero;
+
default:
if (isExternC()) {
if (FnInfo->isStr("memset"))
@@ -3430,6 +3497,8 @@ unsigned FunctionDecl::getMemoryFunctionKind() const {
return Builtin::BIstrndup;
else if (FnInfo->isStr("strlen"))
return Builtin::BIstrlen;
+ else if (FnInfo->isStr("bzero"))
+ return Builtin::BIbzero;
}
break;
}
@@ -4281,3 +4350,18 @@ SourceRange ImportDecl::getSourceRange() const {
return SourceRange(getLocation(), getIdentifierLocs().back());
}
+
+//===----------------------------------------------------------------------===//
+// ExportDecl Implementation
+//===----------------------------------------------------------------------===//
+
+void ExportDecl::anchor() {}
+
+ExportDecl *ExportDecl::Create(ASTContext &C, DeclContext *DC,
+ SourceLocation ExportLoc) {
+ return new (C, DC) ExportDecl(DC, ExportLoc);
+}
+
+ExportDecl *ExportDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
+ return new (C, ID) ExportDecl(nullptr, SourceLocation());
+}
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index bfb7d02b2955..6111abab646e 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -28,7 +28,6 @@
#include "clang/AST/StmtCXX.h"
#include "clang/AST/Type.h"
#include "clang/Basic/TargetInfo.h"
-#include "llvm/ADT/DenseMap.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
using namespace clang;
@@ -46,8 +45,7 @@ void Decl::updateOutOfDate(IdentifierInfo &II) const {
}
#define DECL(DERIVED, BASE) \
- static_assert(llvm::AlignOf<Decl>::Alignment >= \
- llvm::AlignOf<DERIVED##Decl>::Alignment, \
+ static_assert(alignof(Decl) >= alignof(DERIVED##Decl), \
"Alignment sufficient after objects prepended to " #DERIVED);
#define ABSTRACT_DECL(DECL)
#include "clang/AST/DeclNodes.inc"
@@ -56,7 +54,7 @@ void *Decl::operator new(std::size_t Size, const ASTContext &Context,
unsigned ID, std::size_t Extra) {
// Allocate an extra 8 bytes worth of storage, which ensures that the
// resulting pointer will still be 8-byte aligned.
- static_assert(sizeof(unsigned) * 2 >= llvm::AlignOf<Decl>::Alignment,
+ static_assert(sizeof(unsigned) * 2 >= alignof(Decl),
"Decl won't be misaligned");
void *Start = Context.Allocate(Size + Extra + 8);
void *Result = (char*)Start + 8;
@@ -81,8 +79,7 @@ void *Decl::operator new(std::size_t Size, const ASTContext &Ctx,
// Ensure required alignment of the resulting object by adding extra
// padding at the start if required.
size_t ExtraAlign =
- llvm::OffsetToAlignment(sizeof(Module *),
- llvm::AlignOf<Decl>::Alignment);
+ llvm::OffsetToAlignment(sizeof(Module *), alignof(Decl));
char *Buffer = reinterpret_cast<char *>(
::operator new(ExtraAlign + sizeof(Module *) + Size + Extra, Ctx));
Buffer += ExtraAlign;
@@ -112,12 +109,24 @@ const char *Decl::getDeclKindName() const {
void Decl::setInvalidDecl(bool Invalid) {
InvalidDecl = Invalid;
assert(!isa<TagDecl>(this) || !cast<TagDecl>(this)->isCompleteDefinition());
- if (Invalid && !isa<ParmVarDecl>(this)) {
+ if (!Invalid) {
+ return;
+ }
+
+ if (!isa<ParmVarDecl>(this)) {
// Defensive maneuver for ill-formed code: we're likely not to make it to
// a point where we set the access specifier, so default it to "public"
// to avoid triggering asserts elsewhere in the front end.
setAccess(AS_public);
}
+
+ // Marking a DecompositionDecl as invalid implies all the child BindingDecl's
+ // are invalid too.
+ if (DecompositionDecl *DD = dyn_cast<DecompositionDecl>(this)) {
+ for (BindingDecl *Binding : DD->bindings()) {
+ Binding->setInvalidDecl();
+ }
+ }
}
const char *DeclContext::getDeclKindName() const {
@@ -378,6 +387,22 @@ bool Decl::isReferenced() const {
return false;
}
+bool Decl::isExported() const {
+ if (isModulePrivate())
+ return false;
+ // Namespaces are always exported.
+ if (isa<TranslationUnitDecl>(this) || isa<NamespaceDecl>(this))
+ return true;
+ // Otherwise, this is a strictly lexical check.
+ for (auto *DC = getLexicalDeclContext(); DC; DC = DC->getLexicalParent()) {
+ if (cast<Decl>(DC)->isModulePrivate())
+ return false;
+ if (isa<ExportDecl>(DC))
+ return true;
+ }
+ return false;
+}
+
bool Decl::hasDefiningAttr() const {
return hasAttr<AliasAttr>() || hasAttr<IFuncAttr>();
}
@@ -401,11 +426,12 @@ const Attr *Decl::getDefiningAttr() const {
/// diagnostics.
static AvailabilityResult CheckAvailability(ASTContext &Context,
const AvailabilityAttr *A,
- std::string *Message) {
- VersionTuple TargetMinVersion =
- Context.getTargetInfo().getPlatformMinVersion();
+ std::string *Message,
+ VersionTuple EnclosingVersion) {
+ if (EnclosingVersion.empty())
+ EnclosingVersion = Context.getTargetInfo().getPlatformMinVersion();
- if (TargetMinVersion.empty())
+ if (EnclosingVersion.empty())
return AR_Available;
// Check if this is an App Extension "platform", and if so chop off
@@ -450,7 +476,7 @@ static AvailabilityResult CheckAvailability(ASTContext &Context,
// Make sure that this declaration has already been introduced.
if (!A->getIntroduced().empty() &&
- TargetMinVersion < A->getIntroduced()) {
+ EnclosingVersion < A->getIntroduced()) {
if (Message) {
Message->clear();
llvm::raw_string_ostream Out(*Message);
@@ -464,7 +490,7 @@ static AvailabilityResult CheckAvailability(ASTContext &Context,
}
// Make sure that this declaration hasn't been obsoleted.
- if (!A->getObsoleted().empty() && TargetMinVersion >= A->getObsoleted()) {
+ if (!A->getObsoleted().empty() && EnclosingVersion >= A->getObsoleted()) {
if (Message) {
Message->clear();
llvm::raw_string_ostream Out(*Message);
@@ -478,7 +504,7 @@ static AvailabilityResult CheckAvailability(ASTContext &Context,
}
// Make sure that this declaration hasn't been deprecated.
- if (!A->getDeprecated().empty() && TargetMinVersion >= A->getDeprecated()) {
+ if (!A->getDeprecated().empty() && EnclosingVersion >= A->getDeprecated()) {
if (Message) {
Message->clear();
llvm::raw_string_ostream Out(*Message);
@@ -494,9 +520,10 @@ static AvailabilityResult CheckAvailability(ASTContext &Context,
return AR_Available;
}
-AvailabilityResult Decl::getAvailability(std::string *Message) const {
+AvailabilityResult Decl::getAvailability(std::string *Message,
+ VersionTuple EnclosingVersion) const {
if (auto *FTD = dyn_cast<FunctionTemplateDecl>(this))
- return FTD->getTemplatedDecl()->getAvailability(Message);
+ return FTD->getTemplatedDecl()->getAvailability(Message, EnclosingVersion);
AvailabilityResult Result = AR_Available;
std::string ResultMessage;
@@ -521,7 +548,7 @@ AvailabilityResult Decl::getAvailability(std::string *Message) const {
if (const auto *Availability = dyn_cast<AvailabilityAttr>(A)) {
AvailabilityResult AR = CheckAvailability(getASTContext(), Availability,
- Message);
+ Message, EnclosingVersion);
if (AR == AR_Unavailable)
return AR_Unavailable;
@@ -580,8 +607,8 @@ bool Decl::isWeakImported() const {
return true;
if (const auto *Availability = dyn_cast<AvailabilityAttr>(A)) {
- if (CheckAvailability(getASTContext(), Availability,
- nullptr) == AR_NotYetIntroduced)
+ if (CheckAvailability(getASTContext(), Availability, nullptr,
+ VersionTuple()) == AR_NotYetIntroduced)
return true;
}
}
@@ -599,6 +626,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
case CXXConversion:
case EnumConstant:
case Var:
+ case Binding:
case ImplicitParam:
case ParmVar:
case ObjCMethod:
@@ -623,11 +651,13 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
case Typedef:
case TypeAlias:
case TypeAliasTemplate:
- case UnresolvedUsingTypename:
case TemplateTypeParm:
case ObjCTypeParam:
return IDNS_Ordinary | IDNS_Type;
+ case UnresolvedUsingTypename:
+ return IDNS_Ordinary | IDNS_Type | IDNS_Using;
+
case UsingShadow:
return 0; // we'll actually overwrite this later
@@ -635,6 +665,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
return IDNS_Ordinary | IDNS_Using;
case Using:
+ case UsingPack:
return IDNS_Using;
case ObjCProtocol:
@@ -670,6 +701,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
case FriendTemplate:
case AccessSpec:
case LinkageSpec:
+ case Export:
case FileScopeAsm:
case StaticAssert:
case ObjCPropertyImpl:
@@ -679,6 +711,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
case Captured:
case TranslationUnit:
case ExternCContext:
+ case Decomposition:
case UsingDirective:
case BuiltinTemplate:
@@ -954,7 +987,7 @@ bool DeclContext::isDependentContext() const {
bool DeclContext::isTransparentContext() const {
if (DeclKind == Decl::Enum)
return !cast<EnumDecl>(this)->isScoped();
- else if (DeclKind == Decl::LinkageSpec)
+ else if (DeclKind == Decl::LinkageSpec || DeclKind == Decl::Export)
return true;
return false;
@@ -974,6 +1007,18 @@ bool DeclContext::isExternCContext() const {
return isLinkageSpecContext(this, clang::LinkageSpecDecl::lang_c);
}
+const LinkageSpecDecl *DeclContext::getExternCContext() const {
+ const DeclContext *DC = this;
+ while (DC->getDeclKind() != Decl::TranslationUnit) {
+ if (DC->getDeclKind() == Decl::LinkageSpec &&
+ cast<LinkageSpecDecl>(DC)->getLanguage() ==
+ clang::LinkageSpecDecl::lang_c)
+ return cast<LinkageSpecDecl>(DC);
+ DC = DC->getLexicalParent();
+ }
+ return nullptr;
+}
+
bool DeclContext::isExternCXXContext() const {
return isLinkageSpecContext(this, clang::LinkageSpecDecl::lang_cxx);
}
@@ -993,6 +1038,7 @@ DeclContext *DeclContext::getPrimaryContext() {
case Decl::TranslationUnit:
case Decl::ExternCContext:
case Decl::LinkageSpec:
+ case Decl::Export:
case Decl::Block:
case Decl::Captured:
case Decl::OMPDeclareReduction:
@@ -1405,8 +1451,8 @@ NamedDecl *const DeclContextLookupResult::SingleElementDummyList = nullptr;
DeclContext::lookup_result
DeclContext::lookup(DeclarationName Name) const {
- assert(DeclKind != Decl::LinkageSpec &&
- "Should not perform lookups into linkage specs!");
+ assert(DeclKind != Decl::LinkageSpec && DeclKind != Decl::Export &&
+ "should not perform lookups into transparent contexts");
const DeclContext *PrimaryContext = getPrimaryContext();
if (PrimaryContext != this)
@@ -1467,8 +1513,8 @@ DeclContext::lookup(DeclarationName Name) const {
DeclContext::lookup_result
DeclContext::noload_lookup(DeclarationName Name) {
- assert(DeclKind != Decl::LinkageSpec &&
- "Should not perform lookups into linkage specs!");
+ assert(DeclKind != Decl::LinkageSpec && DeclKind != Decl::Export &&
+ "should not perform lookups into transparent contexts");
DeclContext *PrimaryContext = getPrimaryContext();
if (PrimaryContext != this)
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 81f94148d6ed..a9db65a51518 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -533,6 +533,12 @@ void CXXRecordDecl::addedMember(Decl *D) {
} else if (Constructor->isMoveConstructor())
SMKind |= SMF_MoveConstructor;
}
+
+ // C++11 [dcl.init.aggr]p1: DR1518
+ // An aggregate is an array or a class with no user-provided, explicit, or
+ // inherited constructors
+ if (Constructor->isUserProvided() || Constructor->isExplicit())
+ data().Aggregate = false;
}
// Handle constructors, including those inherited from base classes.
@@ -546,20 +552,6 @@ void CXXRecordDecl::addedMember(Decl *D) {
// constructor [...]
if (Constructor->isConstexpr() && !Constructor->isCopyOrMoveConstructor())
data().HasConstexprNonCopyMoveConstructor = true;
-
- // C++ [dcl.init.aggr]p1:
- // An aggregate is an array or a class with no user-declared
- // constructors [...].
- // C++11 [dcl.init.aggr]p1:
- // An aggregate is an array or a class with no user-provided
- // constructors [...].
- // C++11 [dcl.init.aggr]p1:
- // An aggregate is an array or a class with no user-provided
- // constructors (including those inherited from a base class) [...].
- if (getASTContext().getLangOpts().CPlusPlus11
- ? Constructor->isUserProvided()
- : !Constructor->isImplicit())
- data().Aggregate = false;
}
// Handle destructors.
@@ -739,7 +731,7 @@ void CXXRecordDecl::addedMember(Decl *D) {
}
if (!Field->hasInClassInitializer() && !Field->isMutable()) {
- if (CXXRecordDecl *FieldType = Field->getType()->getAsCXXRecordDecl()) {
+ if (CXXRecordDecl *FieldType = T->getAsCXXRecordDecl()) {
if (FieldType->hasDefinition() && !FieldType->allowConstDefaultInit())
data().HasUninitializedFields = true;
} else {
@@ -989,8 +981,12 @@ void CXXRecordDecl::addedMember(Decl *D) {
if (UsingDecl *Using = dyn_cast<UsingDecl>(D)) {
if (Using->getDeclName().getNameKind() ==
- DeclarationName::CXXConstructorName)
+ DeclarationName::CXXConstructorName) {
data().HasInheritedConstructor = true;
+ // C++1z [dcl.init.aggr]p1:
+ // An aggregate is [...] a class [...] with no inherited constructors
+ data().Aggregate = false;
+ }
if (Using->getDeclName().getCXXOverloadedOperator() == OO_Equal)
data().HasInheritedAssignment = true;
@@ -1107,6 +1103,12 @@ CXXRecordDecl::getGenericLambdaTemplateParameterList() const {
return nullptr;
}
+Decl *CXXRecordDecl::getLambdaContextDecl() const {
+ assert(isLambda() && "Not a lambda closure type!");
+ ExternalASTSource *Source = getParentASTContext().getExternalSource();
+ return getLambdaData().ContextDecl.get(Source);
+}
+
static CanQualType GetConversionType(ASTContext &Context, NamedDecl *Conv) {
QualType T =
cast<CXXConversionDecl>(Conv->getUnderlyingDecl()->getAsFunction())
@@ -1571,17 +1573,35 @@ bool CXXMethodDecl::isUsualDeallocationFunction() const {
// deallocation function. [...]
if (getNumParams() == 1)
return true;
-
- // C++ [basic.stc.dynamic.deallocation]p2:
+ unsigned UsualParams = 1;
+
+ // C++ <=14 [basic.stc.dynamic.deallocation]p2:
// [...] If class T does not declare such an operator delete but does
// declare a member deallocation function named operator delete with
// exactly two parameters, the second of which has type std::size_t (18.1),
// then this function is a usual deallocation function.
+ //
+ // C++17 says a usual deallocation function is one with the signature
+ // (void* [, size_t] [, std::align_val_t] [, ...])
+ // and all such functions are usual deallocation functions. It's not clear
+ // that allowing varargs functions was intentional.
ASTContext &Context = getASTContext();
- if (getNumParams() != 2 ||
- !Context.hasSameUnqualifiedType(getParamDecl(1)->getType(),
- Context.getSizeType()))
+ if (UsualParams < getNumParams() &&
+ Context.hasSameUnqualifiedType(getParamDecl(UsualParams)->getType(),
+ Context.getSizeType()))
+ ++UsualParams;
+
+ if (UsualParams < getNumParams() &&
+ getParamDecl(UsualParams)->getType()->isAlignValT())
+ ++UsualParams;
+
+ if (UsualParams != getNumParams())
return false;
+
+ // In C++17 onwards, all potential usual deallocation functions are actual
+ // usual deallocation functions.
+ if (Context.getLangOpts().AlignedAllocation)
+ return true;
// This function is a usual deallocation function if there are no
// single-parameter deallocation functions of the same kind.
@@ -1714,7 +1734,7 @@ CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context,
SourceLocation EllipsisLoc)
: Initializee(TInfo), MemberOrEllipsisLocation(EllipsisLoc), Init(Init),
LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(IsVirtual),
- IsWritten(false), SourceOrderOrNumArrayIndices(0)
+ IsWritten(false), SourceOrder(0)
{
}
@@ -1725,7 +1745,7 @@ CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context,
SourceLocation R)
: Initializee(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init),
LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(false),
- IsWritten(false), SourceOrderOrNumArrayIndices(0)
+ IsWritten(false), SourceOrder(0)
{
}
@@ -1736,7 +1756,7 @@ CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context,
SourceLocation R)
: Initializee(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init),
LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(false),
- IsWritten(false), SourceOrderOrNumArrayIndices(0)
+ IsWritten(false), SourceOrder(0)
{
}
@@ -1746,38 +1766,10 @@ CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context,
SourceLocation R)
: Initializee(TInfo), MemberOrEllipsisLocation(), Init(Init),
LParenLoc(L), RParenLoc(R), IsDelegating(true), IsVirtual(false),
- IsWritten(false), SourceOrderOrNumArrayIndices(0)
+ IsWritten(false), SourceOrder(0)
{
}
-CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context,
- FieldDecl *Member,
- SourceLocation MemberLoc,
- SourceLocation L, Expr *Init,
- SourceLocation R,
- VarDecl **Indices,
- unsigned NumIndices)
- : Initializee(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init),
- LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(false),
- IsWritten(false), SourceOrderOrNumArrayIndices(NumIndices)
-{
- std::uninitialized_copy(Indices, Indices + NumIndices,
- getTrailingObjects<VarDecl *>());
-}
-
-CXXCtorInitializer *CXXCtorInitializer::Create(ASTContext &Context,
- FieldDecl *Member,
- SourceLocation MemberLoc,
- SourceLocation L, Expr *Init,
- SourceLocation R,
- VarDecl **Indices,
- unsigned NumIndices) {
- void *Mem = Context.Allocate(totalSizeToAlloc<VarDecl *>(NumIndices),
- llvm::alignOf<CXXCtorInitializer>());
- return new (Mem) CXXCtorInitializer(Context, Member, MemberLoc, L, Init, R,
- Indices, NumIndices);
-}
-
TypeLoc CXXCtorInitializer::getBaseClassLoc() const {
if (isBaseInitializer())
return Initializee.get<TypeSourceInfo*>()->getTypeLoc();
@@ -2253,15 +2245,37 @@ SourceRange UsingDecl::getSourceRange() const {
return SourceRange(Begin, getNameInfo().getEndLoc());
}
+void UsingPackDecl::anchor() { }
+
+UsingPackDecl *UsingPackDecl::Create(ASTContext &C, DeclContext *DC,
+ NamedDecl *InstantiatedFrom,
+ ArrayRef<NamedDecl *> UsingDecls) {
+ size_t Extra = additionalSizeToAlloc<NamedDecl *>(UsingDecls.size());
+ return new (C, DC, Extra) UsingPackDecl(DC, InstantiatedFrom, UsingDecls);
+}
+
+UsingPackDecl *UsingPackDecl::CreateDeserialized(ASTContext &C, unsigned ID,
+ unsigned NumExpansions) {
+ size_t Extra = additionalSizeToAlloc<NamedDecl *>(NumExpansions);
+ auto *Result = new (C, ID, Extra) UsingPackDecl(nullptr, nullptr, None);
+ Result->NumExpansions = NumExpansions;
+ auto *Trail = Result->getTrailingObjects<NamedDecl *>();
+ for (unsigned I = 0; I != NumExpansions; ++I)
+ new (Trail + I) NamedDecl*(nullptr);
+ return Result;
+}
+
void UnresolvedUsingValueDecl::anchor() { }
UnresolvedUsingValueDecl *
UnresolvedUsingValueDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation UsingLoc,
NestedNameSpecifierLoc QualifierLoc,
- const DeclarationNameInfo &NameInfo) {
+ const DeclarationNameInfo &NameInfo,
+ SourceLocation EllipsisLoc) {
return new (C, DC) UnresolvedUsingValueDecl(DC, C.DependentTy, UsingLoc,
- QualifierLoc, NameInfo);
+ QualifierLoc, NameInfo,
+ EllipsisLoc);
}
UnresolvedUsingValueDecl *
@@ -2269,7 +2283,8 @@ UnresolvedUsingValueDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
return new (C, ID) UnresolvedUsingValueDecl(nullptr, QualType(),
SourceLocation(),
NestedNameSpecifierLoc(),
- DeclarationNameInfo());
+ DeclarationNameInfo(),
+ SourceLocation());
}
SourceRange UnresolvedUsingValueDecl::getSourceRange() const {
@@ -2286,17 +2301,18 @@ UnresolvedUsingTypenameDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation TypenameLoc,
NestedNameSpecifierLoc QualifierLoc,
SourceLocation TargetNameLoc,
- DeclarationName TargetName) {
+ DeclarationName TargetName,
+ SourceLocation EllipsisLoc) {
return new (C, DC) UnresolvedUsingTypenameDecl(
DC, UsingLoc, TypenameLoc, QualifierLoc, TargetNameLoc,
- TargetName.getAsIdentifierInfo());
+ TargetName.getAsIdentifierInfo(), EllipsisLoc);
}
UnresolvedUsingTypenameDecl *
UnresolvedUsingTypenameDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
return new (C, ID) UnresolvedUsingTypenameDecl(
nullptr, SourceLocation(), SourceLocation(), NestedNameSpecifierLoc(),
- SourceLocation(), nullptr);
+ SourceLocation(), nullptr, SourceLocation());
}
void StaticAssertDecl::anchor() { }
@@ -2317,6 +2333,70 @@ StaticAssertDecl *StaticAssertDecl::CreateDeserialized(ASTContext &C,
nullptr, SourceLocation(), false);
}
+void BindingDecl::anchor() {}
+
+BindingDecl *BindingDecl::Create(ASTContext &C, DeclContext *DC,
+ SourceLocation IdLoc, IdentifierInfo *Id) {
+ return new (C, DC) BindingDecl(DC, IdLoc, Id);
+}
+
+BindingDecl *BindingDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
+ return new (C, ID) BindingDecl(nullptr, SourceLocation(), nullptr);
+}
+
+VarDecl *BindingDecl::getHoldingVar() const {
+ Expr *B = getBinding();
+ if (!B)
+ return nullptr;
+ auto *DRE = dyn_cast<DeclRefExpr>(B->IgnoreImplicit());
+ if (!DRE)
+ return nullptr;
+
+ auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
+ assert(VD->isImplicit() && "holding var for binding decl not implicit");
+ return VD;
+}
+
+void DecompositionDecl::anchor() {}
+
+DecompositionDecl *DecompositionDecl::Create(ASTContext &C, DeclContext *DC,
+ SourceLocation StartLoc,
+ SourceLocation LSquareLoc,
+ QualType T, TypeSourceInfo *TInfo,
+ StorageClass SC,
+ ArrayRef<BindingDecl *> Bindings) {
+ size_t Extra = additionalSizeToAlloc<BindingDecl *>(Bindings.size());
+ return new (C, DC, Extra)
+ DecompositionDecl(C, DC, StartLoc, LSquareLoc, T, TInfo, SC, Bindings);
+}
+
+DecompositionDecl *DecompositionDecl::CreateDeserialized(ASTContext &C,
+ unsigned ID,
+ unsigned NumBindings) {
+ size_t Extra = additionalSizeToAlloc<BindingDecl *>(NumBindings);
+ auto *Result = new (C, ID, Extra)
+ DecompositionDecl(C, nullptr, SourceLocation(), SourceLocation(),
+ QualType(), nullptr, StorageClass(), None);
+ // Set up and clean out the bindings array.
+ Result->NumBindings = NumBindings;
+ auto *Trail = Result->getTrailingObjects<BindingDecl *>();
+ for (unsigned I = 0; I != NumBindings; ++I)
+ new (Trail + I) BindingDecl*(nullptr);
+ return Result;
+}
+
+void DecompositionDecl::printName(llvm::raw_ostream &os) const {
+ os << '[';
+ bool Comma = false;
+ for (auto *B : bindings()) {
+ if (Comma)
+ os << ", ";
+ B->printName(os);
+ Comma = true;
+ }
+ os << ']';
+}
+
MSPropertyDecl *MSPropertyDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation L, DeclarationName N,
QualType T, TypeSourceInfo *TInfo,
diff --git a/lib/AST/DeclGroup.cpp b/lib/AST/DeclGroup.cpp
index f162e6d40c48..2f95e1f1c345 100644
--- a/lib/AST/DeclGroup.cpp
+++ b/lib/AST/DeclGroup.cpp
@@ -14,13 +14,12 @@
#include "clang/AST/DeclGroup.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
-#include "llvm/Support/Allocator.h"
using namespace clang;
DeclGroup* DeclGroup::Create(ASTContext &C, Decl **Decls, unsigned NumDecls) {
assert(NumDecls > 1 && "Invalid DeclGroup");
unsigned Size = totalSizeToAlloc<Decl *>(NumDecls);
- void* Mem = C.Allocate(Size, llvm::AlignOf<DeclGroup>::Alignment);
+ void *Mem = C.Allocate(Size, alignof(DeclGroup));
new (Mem) DeclGroup(NumDecls, Decls);
return static_cast<DeclGroup*>(Mem);
}
diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp
index d2701211beae..60d05f682e6e 100644
--- a/lib/AST/DeclObjC.cpp
+++ b/lib/AST/DeclObjC.cpp
@@ -800,8 +800,7 @@ void ObjCMethodDecl::setParamsAndSelLocs(ASTContext &C,
if (Params.empty() && SelLocs.empty())
return;
- static_assert(llvm::AlignOf<ParmVarDecl *>::Alignment >=
- llvm::AlignOf<SourceLocation>::Alignment,
+ static_assert(alignof(ParmVarDecl *) >= alignof(SourceLocation),
"Alignment not sufficient for SourceLocation");
unsigned Size = sizeof(ParmVarDecl *) * NumParams +
@@ -871,6 +870,12 @@ ObjCMethodDecl *ObjCMethodDecl::getNextRedeclarationImpl() {
}
}
+ // Ensure that the discovered method redeclaration has a valid declaration
+ // context. Used to prevent infinite loops when iterating redeclarations in
+ // a partially invalid AST.
+ if (Redecl && cast<Decl>(Redecl->getDeclContext())->isInvalidDecl())
+ Redecl = nullptr;
+
if (!Redecl && isRedeclaration()) {
// This is the last redeclaration, go back to the first method.
return cast<ObjCContainerDecl>(CtxD)->getMethod(getSelector(),
@@ -897,9 +902,13 @@ ObjCMethodDecl *ObjCMethodDecl::getCanonicalDecl() {
return MD;
}
- if (isRedeclaration())
- return cast<ObjCContainerDecl>(CtxD)->getMethod(getSelector(),
- isInstanceMethod());
+ if (isRedeclaration()) {
+ // It is possible that we have not done deserializing the ObjCMethod yet.
+ ObjCMethodDecl *MD =
+ cast<ObjCContainerDecl>(CtxD)->getMethod(getSelector(),
+ isInstanceMethod());
+ return MD ? MD : this;
+ }
return this;
}
@@ -1320,8 +1329,12 @@ ObjCTypeParamDecl *ObjCTypeParamDecl::Create(ASTContext &ctx, DeclContext *dc,
IdentifierInfo *name,
SourceLocation colonLoc,
TypeSourceInfo *boundInfo) {
- return new (ctx, dc) ObjCTypeParamDecl(ctx, dc, variance, varianceLoc, index,
- nameLoc, name, colonLoc, boundInfo);
+ auto *TPDecl =
+ new (ctx, dc) ObjCTypeParamDecl(ctx, dc, variance, varianceLoc, index,
+ nameLoc, name, colonLoc, boundInfo);
+ QualType TPType = ctx.getObjCTypeParamType(TPDecl, {});
+ TPDecl->setTypeForDecl(TPType.getTypePtr());
+ return TPDecl;
}
ObjCTypeParamDecl *ObjCTypeParamDecl::CreateDeserialized(ASTContext &ctx,
@@ -1366,7 +1379,7 @@ ObjCTypeParamList *ObjCTypeParamList::create(
SourceLocation rAngleLoc) {
void *mem =
ctx.Allocate(totalSizeToAlloc<ObjCTypeParamDecl *>(typeParams.size()),
- llvm::alignOf<ObjCTypeParamList>());
+ alignof(ObjCTypeParamList));
return new (mem) ObjCTypeParamList(lAngleLoc, typeParams, rAngleLoc);
}
diff --git a/lib/AST/DeclOpenMP.cpp b/lib/AST/DeclOpenMP.cpp
index 5b06ce0778a7..95e44acca032 100644
--- a/lib/AST/DeclOpenMP.cpp
+++ b/lib/AST/DeclOpenMP.cpp
@@ -90,13 +90,18 @@ OMPDeclareReductionDecl::getPrevDeclInScope() const {
void OMPCapturedExprDecl::anchor() {}
OMPCapturedExprDecl *OMPCapturedExprDecl::Create(ASTContext &C, DeclContext *DC,
- IdentifierInfo *Id,
- QualType T) {
- return new (C, DC) OMPCapturedExprDecl(C, DC, Id, T);
+ IdentifierInfo *Id, QualType T,
+ SourceLocation StartLoc) {
+ return new (C, DC) OMPCapturedExprDecl(C, DC, Id, T, StartLoc);
}
OMPCapturedExprDecl *OMPCapturedExprDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
- return new (C, ID) OMPCapturedExprDecl(C, nullptr, nullptr, QualType());
+ return new (C, ID)
+ OMPCapturedExprDecl(C, nullptr, nullptr, QualType(), SourceLocation());
}
+SourceRange OMPCapturedExprDecl::getSourceRange() const {
+ assert(hasInit());
+ return SourceRange(getInit()->getLocStart(), getInit()->getLocEnd());
+}
diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp
index 7e786990becb..b8ebe1c568c7 100644
--- a/lib/AST/DeclPrinter.cpp
+++ b/lib/AST/DeclPrinter.cpp
@@ -78,6 +78,10 @@ namespace {
void VisitTemplateDecl(const TemplateDecl *D);
void VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
void VisitClassTemplateDecl(ClassTemplateDecl *D);
+ void VisitClassTemplateSpecializationDecl(
+ ClassTemplateSpecializationDecl *D);
+ void VisitClassTemplatePartialSpecializationDecl(
+ ClassTemplatePartialSpecializationDecl *D);
void VisitObjCMethodDecl(ObjCMethodDecl *D);
void VisitObjCImplementationDecl(ObjCImplementationDecl *D);
void VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
@@ -95,8 +99,9 @@ namespace {
void VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D);
void VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D);
- void PrintTemplateParameters(const TemplateParameterList *Params,
- const TemplateArgumentList *Args = nullptr);
+ void printTemplateParameters(const TemplateParameterList *Params);
+ void printTemplateArguments(const TemplateArgumentList &Args,
+ const TemplateParameterList *Params = nullptr);
void prettyPrintAttributes(Decl *D);
void prettyPrintPragmas(Decl *D);
void printDeclType(QualType T, StringRef DeclName, bool Pack = false);
@@ -290,6 +295,13 @@ void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) {
if (D->isImplicit())
continue;
+ // Don't print implicit specializations, as they are printed when visiting
+ // corresponding templates.
+ if (auto FD = dyn_cast<FunctionDecl>(*D))
+ if (FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation &&
+ !isa<ClassTemplateSpecializationDecl>(DC))
+ continue;
+
// The next bits of code handles stuff like "struct {int x;} a,b"; we're
// forced to merge the declarations because there's no other way to
// refer to the struct in question. This limited merging is safe without
@@ -337,12 +349,19 @@ void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) {
const char *Terminator = nullptr;
if (isa<OMPThreadPrivateDecl>(*D) || isa<OMPDeclareReductionDecl>(*D))
Terminator = nullptr;
- else if (isa<FunctionDecl>(*D) &&
- cast<FunctionDecl>(*D)->isThisDeclarationADefinition())
+ else if (isa<ObjCMethodDecl>(*D) && cast<ObjCMethodDecl>(*D)->hasBody())
Terminator = nullptr;
- else if (isa<ObjCMethodDecl>(*D) && cast<ObjCMethodDecl>(*D)->getBody())
- Terminator = nullptr;
- else if (isa<NamespaceDecl>(*D) || isa<LinkageSpecDecl>(*D) ||
+ else if (auto FD = dyn_cast<FunctionDecl>(*D)) {
+ if (FD->isThisDeclarationADefinition())
+ Terminator = nullptr;
+ else
+ Terminator = ";";
+ } else if (auto TD = dyn_cast<FunctionTemplateDecl>(*D)) {
+ if (TD->getTemplatedDecl()->isThisDeclarationADefinition())
+ Terminator = nullptr;
+ else
+ Terminator = ";";
+ } else if (isa<NamespaceDecl>(*D) || isa<LinkageSpecDecl>(*D) ||
isa<ObjCImplementationDecl>(*D) ||
isa<ObjCInterfaceDecl>(*D) ||
isa<ObjCProtocolDecl>(*D) ||
@@ -359,7 +378,14 @@ void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) {
if (Terminator)
Out << Terminator;
- Out << "\n";
+ if (!Policy.TerseOutput &&
+ ((isa<FunctionDecl>(*D) &&
+ cast<FunctionDecl>(*D)->doesThisDeclarationHaveABody()) ||
+ (isa<FunctionTemplateDecl>(*D) &&
+ cast<FunctionTemplateDecl>(*D)->getTemplatedDecl()->doesThisDeclarationHaveABody())))
+ ; // StmtPrinter already added '\n' after CompoundStmt.
+ else
+ Out << "\n";
// Declare target attribute is special one, natural spelling for the pragma
// assumes "ending" construct so print it here.
@@ -408,7 +434,7 @@ void DeclPrinter::VisitEnumDecl(EnumDecl *D) {
}
Out << *D;
- if (D->isFixed())
+ if (D->isFixed() && D->getASTContext().getLangOpts().CPlusPlus11)
Out << " : " << D->getIntegerType().stream(Policy);
if (D->isCompleteDefinition()) {
@@ -449,6 +475,9 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
!D->isFunctionTemplateSpecialization())
prettyPrintPragmas(D);
+ if (D->isFunctionTemplateSpecialization())
+ Out << "template<> ";
+
CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D);
CXXConversionDecl *ConversionDecl = dyn_cast<CXXConversionDecl>(D);
if (!Policy.SuppressSpecifiers) {
@@ -473,6 +502,11 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
PrintingPolicy SubPolicy(Policy);
SubPolicy.SuppressSpecifiers = false;
std::string Proto = D->getNameInfo().getAsString();
+ if (const TemplateArgumentList *TArgs = D->getTemplateSpecializationArgs()) {
+ llvm::raw_string_ostream POut(Proto);
+ DeclPrinter TArgPrinter(POut, SubPolicy, Indentation);
+ TArgPrinter.printTemplateArguments(*TArgs);
+ }
QualType Ty = D->getType();
while (const ParenType *PT = dyn_cast<ParenType>(Ty)) {
@@ -636,25 +670,29 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
Out << " = delete";
else if (D->isExplicitlyDefaulted())
Out << " = default";
- else if (D->doesThisDeclarationHaveABody() && !Policy.TerseOutput) {
- if (!D->hasPrototype() && D->getNumParams()) {
- // This is a K&R function definition, so we need to print the
- // parameters.
- Out << '\n';
- DeclPrinter ParamPrinter(Out, SubPolicy, Indentation);
- Indentation += Policy.Indentation;
- for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) {
- Indent();
- ParamPrinter.VisitParmVarDecl(D->getParamDecl(i));
- Out << ";\n";
- }
- Indentation -= Policy.Indentation;
- } else
- Out << ' ';
+ else if (D->doesThisDeclarationHaveABody()) {
+ if (!Policy.TerseOutput) {
+ if (!D->hasPrototype() && D->getNumParams()) {
+ // This is a K&R function definition, so we need to print the
+ // parameters.
+ Out << '\n';
+ DeclPrinter ParamPrinter(Out, SubPolicy, Indentation);
+ Indentation += Policy.Indentation;
+ for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) {
+ Indent();
+ ParamPrinter.VisitParmVarDecl(D->getParamDecl(i));
+ Out << ";\n";
+ }
+ Indentation -= Policy.Indentation;
+ } else
+ Out << ' ';
- if (D->getBody())
- D->getBody()->printPretty(Out, nullptr, SubPolicy, Indentation);
- Out << '\n';
+ if (D->getBody())
+ D->getBody()->printPretty(Out, nullptr, SubPolicy, Indentation);
+ } else {
+ if (isa<CXXConstructorDecl>(*D))
+ Out << " {}";
+ }
}
}
@@ -662,7 +700,7 @@ void DeclPrinter::VisitFriendDecl(FriendDecl *D) {
if (TypeSourceInfo *TSI = D->getFriendType()) {
unsigned NumTPLists = D->getFriendTypeNumTemplateParameterLists();
for (unsigned i = 0; i < NumTPLists; ++i)
- PrintTemplateParameters(D->getFriendTypeTemplateParameterList(i));
+ printTemplateParameters(D->getFriendTypeTemplateParameterList(i));
Out << "friend ";
Out << " " << TSI->getType().getAsString(Policy);
}
@@ -839,9 +877,15 @@ void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) {
prettyPrintAttributes(D);
- if (D->getIdentifier())
+ if (D->getIdentifier()) {
Out << ' ' << *D;
+ if (auto S = dyn_cast<ClassTemplatePartialSpecializationDecl>(D))
+ printTemplateArguments(S->getTemplateArgs(), S->getTemplateParameters());
+ else if (auto S = dyn_cast<ClassTemplateSpecializationDecl>(D))
+ printTemplateArguments(S->getTemplateArgs());
+ }
+
if (D->isCompleteDefinition()) {
// Print the base classes
if (D->getNumBases()) {
@@ -868,9 +912,13 @@ void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) {
// Print the class definition
// FIXME: Doesn't print access specifiers, e.g., "public:"
- Out << " {\n";
- VisitDeclContext(D);
- Indent() << "}";
+ if (Policy.TerseOutput) {
+ Out << " {}";
+ } else {
+ Out << " {\n";
+ VisitDeclContext(D);
+ Indent() << "}";
+ }
}
}
@@ -893,10 +941,8 @@ void DeclPrinter::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
Visit(*D->decls_begin());
}
-void DeclPrinter::PrintTemplateParameters(const TemplateParameterList *Params,
- const TemplateArgumentList *Args) {
+void DeclPrinter::printTemplateParameters(const TemplateParameterList *Params) {
assert(Params);
- assert(!Args || Params->size() == Args->size());
Out << "template <";
@@ -905,8 +951,7 @@ void DeclPrinter::PrintTemplateParameters(const TemplateParameterList *Params,
Out << ", ";
const Decl *Param = Params->getParam(i);
- if (const TemplateTypeParmDecl *TTP =
- dyn_cast<TemplateTypeParmDecl>(Param)) {
+ if (auto TTP = dyn_cast<TemplateTypeParmDecl>(Param)) {
if (TTP->wasDeclaredWithTypename())
Out << "typename ";
@@ -918,30 +963,22 @@ void DeclPrinter::PrintTemplateParameters(const TemplateParameterList *Params,
Out << *TTP;
- if (Args) {
- Out << " = ";
- Args->get(i).print(Policy, Out);
- } else if (TTP->hasDefaultArgument()) {
+ if (TTP->hasDefaultArgument()) {
Out << " = ";
Out << TTP->getDefaultArgument().getAsString(Policy);
};
- } else if (const NonTypeTemplateParmDecl *NTTP =
- dyn_cast<NonTypeTemplateParmDecl>(Param)) {
+ } else if (auto NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
StringRef Name;
if (IdentifierInfo *II = NTTP->getIdentifier())
Name = II->getName();
printDeclType(NTTP->getType(), Name, NTTP->isParameterPack());
- if (Args) {
- Out << " = ";
- Args->get(i).print(Policy, Out);
- } else if (NTTP->hasDefaultArgument()) {
+ if (NTTP->hasDefaultArgument()) {
Out << " = ";
NTTP->getDefaultArgument()->printPretty(Out, nullptr, Policy,
Indentation);
}
- } else if (const TemplateTemplateParmDecl *TTPD =
- dyn_cast<TemplateTemplateParmDecl>(Param)) {
+ } else if (auto TTPD = dyn_cast<TemplateTemplateParmDecl>(Param)) {
VisitTemplateDecl(TTPD);
// FIXME: print the default argument, if present.
}
@@ -950,8 +987,46 @@ void DeclPrinter::PrintTemplateParameters(const TemplateParameterList *Params,
Out << "> ";
}
+void DeclPrinter::printTemplateArguments(const TemplateArgumentList &Args,
+ const TemplateParameterList *Params) {
+ Out << "<";
+ for (size_t I = 0, E = Args.size(); I < E; ++I) {
+ const TemplateArgument &A = Args[I];
+ if (I)
+ Out << ", ";
+ if (Params) {
+ if (A.getKind() == TemplateArgument::Type)
+ if (auto T = A.getAsType()->getAs<TemplateTypeParmType>()) {
+ auto P = cast<TemplateTypeParmDecl>(Params->getParam(T->getIndex()));
+ Out << *P;
+ continue;
+ }
+ if (A.getKind() == TemplateArgument::Template) {
+ if (auto T = A.getAsTemplate().getAsTemplateDecl())
+ if (auto TD = dyn_cast<TemplateTemplateParmDecl>(T)) {
+ auto P = cast<TemplateTemplateParmDecl>(
+ Params->getParam(TD->getIndex()));
+ Out << *P;
+ continue;
+ }
+ }
+ if (A.getKind() == TemplateArgument::Expression) {
+ if (auto E = dyn_cast<DeclRefExpr>(A.getAsExpr()))
+ if (auto N = dyn_cast<NonTypeTemplateParmDecl>(E->getDecl())) {
+ auto P = cast<NonTypeTemplateParmDecl>(
+ Params->getParam(N->getIndex()));
+ Out << *P;
+ continue;
+ }
+ }
+ }
+ A.print(Policy, Out);
+ }
+ Out << ">";
+}
+
void DeclPrinter::VisitTemplateDecl(const TemplateDecl *D) {
- PrintTemplateParameters(D->getTemplateParameters());
+ printTemplateParameters(D->getTemplateParameters());
if (const TemplateTemplateParmDecl *TTP =
dyn_cast<TemplateTemplateParmDecl>(D)) {
@@ -965,30 +1040,49 @@ void DeclPrinter::VisitTemplateDecl(const TemplateDecl *D) {
}
void DeclPrinter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
+ prettyPrintPragmas(D->getTemplatedDecl());
+ VisitRedeclarableTemplateDecl(D);
+
if (PrintInstantiation) {
- TemplateParameterList *Params = D->getTemplateParameters();
- for (auto *I : D->specializations()) {
- prettyPrintPragmas(I);
- PrintTemplateParameters(Params, I->getTemplateSpecializationArgs());
- Visit(I);
- }
+ FunctionDecl *PrevDecl = D->getTemplatedDecl();
+ const FunctionDecl *Def;
+ if (PrevDecl->isDefined(Def) && Def != PrevDecl)
+ return;
+ for (auto *I : D->specializations())
+ if (I->getTemplateSpecializationKind() == TSK_ImplicitInstantiation) {
+ if (!PrevDecl->isThisDeclarationADefinition())
+ Out << ";\n";
+ Indent();
+ prettyPrintPragmas(I);
+ Visit(I);
+ }
}
-
- prettyPrintPragmas(D->getTemplatedDecl());
- return VisitRedeclarableTemplateDecl(D);
}
void DeclPrinter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
+ VisitRedeclarableTemplateDecl(D);
+
if (PrintInstantiation) {
- TemplateParameterList *Params = D->getTemplateParameters();
- for (auto *I : D->specializations()) {
- PrintTemplateParameters(Params, &I->getTemplateArgs());
- Visit(I);
- Out << '\n';
- }
+ for (auto *I : D->specializations())
+ if (I->getSpecializationKind() == TSK_ImplicitInstantiation) {
+ if (D->isThisDeclarationADefinition())
+ Out << ";";
+ Out << "\n";
+ Visit(I);
+ }
}
+}
+
+void DeclPrinter::VisitClassTemplateSpecializationDecl(
+ ClassTemplateSpecializationDecl *D) {
+ Out << "template<> ";
+ VisitCXXRecordDecl(D);
+}
- return VisitRedeclarableTemplateDecl(D);
+void DeclPrinter::VisitClassTemplatePartialSpecializationDecl(
+ ClassTemplatePartialSpecializationDecl *D) {
+ printTemplateParameters(D->getTemplateParameters());
+ VisitCXXRecordDecl(D);
}
//----------------------------------------------------------------------------
@@ -1346,6 +1440,17 @@ void DeclPrinter::VisitUsingDecl(UsingDecl *D) {
if (D->hasTypename())
Out << "typename ";
D->getQualifier()->print(Out, Policy);
+
+ // Use the correct record name when the using declaration is used for
+ // inheriting constructors.
+ for (const auto *Shadow : D->shadows()) {
+ if (const auto *ConstructorShadow =
+ dyn_cast<ConstructorUsingShadowDecl>(Shadow)) {
+ assert(Shadow->getDeclContext() == ConstructorShadow->getDeclContext());
+ Out << *ConstructorShadow->getNominatedBaseClass();
+ return;
+ }
+ }
Out << *D;
}
diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp
index 37943cdd5b7b..8643cbfcd960 100644
--- a/lib/AST/DeclTemplate.cpp
+++ b/lib/AST/DeclTemplate.cpp
@@ -31,10 +31,11 @@ using namespace clang;
TemplateParameterList::TemplateParameterList(SourceLocation TemplateLoc,
SourceLocation LAngleLoc,
ArrayRef<NamedDecl *> Params,
- SourceLocation RAngleLoc)
+ SourceLocation RAngleLoc,
+ Expr *RequiresClause)
: TemplateLoc(TemplateLoc), LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc),
- NumParams(Params.size()), ContainsUnexpandedParameterPack(false) {
- assert(this->NumParams == NumParams && "Too many template parameters");
+ NumParams(Params.size()), ContainsUnexpandedParameterPack(false),
+ HasRequiresClause(static_cast<bool>(RequiresClause)) {
for (unsigned Idx = 0; Idx < NumParams; ++Idx) {
NamedDecl *P = Params[Idx];
begin()[Idx] = P;
@@ -52,15 +53,21 @@ TemplateParameterList::TemplateParameterList(SourceLocation TemplateLoc,
// template parameter list does too.
}
}
+ if (RequiresClause) {
+ *getTrailingObjects<Expr *>() = RequiresClause;
+ }
}
-TemplateParameterList *TemplateParameterList::Create(
- const ASTContext &C, SourceLocation TemplateLoc, SourceLocation LAngleLoc,
- ArrayRef<NamedDecl *> Params, SourceLocation RAngleLoc) {
- void *Mem = C.Allocate(totalSizeToAlloc<NamedDecl *>(Params.size()),
- llvm::alignOf<TemplateParameterList>());
+TemplateParameterList *
+TemplateParameterList::Create(const ASTContext &C, SourceLocation TemplateLoc,
+ SourceLocation LAngleLoc,
+ ArrayRef<NamedDecl *> Params,
+ SourceLocation RAngleLoc, Expr *RequiresClause) {
+ void *Mem = C.Allocate(totalSizeToAlloc<NamedDecl *, Expr *>(
+ Params.size(), RequiresClause ? 1u : 0u),
+ alignof(TemplateParameterList));
return new (Mem) TemplateParameterList(TemplateLoc, LAngleLoc, Params,
- RAngleLoc);
+ RAngleLoc, RequiresClause);
}
unsigned TemplateParameterList::getMinRequiredArguments() const {
@@ -197,44 +204,6 @@ void RedeclarableTemplateDecl::addSpecializationImpl(
SETraits::getDecl(Entry));
}
-/// \brief Generate the injected template arguments for the given template
-/// parameter list, e.g., for the injected-class-name of a class template.
-static void GenerateInjectedTemplateArgs(ASTContext &Context,
- TemplateParameterList *Params,
- TemplateArgument *Args) {
- for (NamedDecl *Param : *Params) {
- TemplateArgument Arg;
- if (auto *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) {
- QualType ArgType = Context.getTypeDeclType(TTP);
- if (TTP->isParameterPack())
- ArgType = Context.getPackExpansionType(ArgType, None);
-
- Arg = TemplateArgument(ArgType);
- } else if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
- Expr *E = new (Context) DeclRefExpr(NTTP, /*enclosing*/ false,
- NTTP->getType().getNonLValueExprType(Context),
- Expr::getValueKindForType(NTTP->getType()),
- NTTP->getLocation());
-
- if (NTTP->isParameterPack())
- E = new (Context) PackExpansionExpr(Context.DependentTy, E,
- NTTP->getLocation(), None);
- Arg = TemplateArgument(E);
- } else {
- auto *TTP = cast<TemplateTemplateParmDecl>(Param);
- if (TTP->isParameterPack())
- Arg = TemplateArgument(TemplateName(TTP), Optional<unsigned>());
- else
- Arg = TemplateArgument(TemplateName(TTP));
- }
-
- if (Param->isTemplateParameterPack())
- Arg = TemplateArgument::CreatePackCopy(Context, Arg);
-
- *Args++ = Arg;
- }
-}
-
//===----------------------------------------------------------------------===//
// FunctionTemplateDecl Implementation
//===----------------------------------------------------------------------===//
@@ -303,10 +272,13 @@ ArrayRef<TemplateArgument> FunctionTemplateDecl::getInjectedTemplateArgs() {
TemplateParameterList *Params = getTemplateParameters();
Common *CommonPtr = getCommonPtr();
if (!CommonPtr->InjectedArgs) {
- CommonPtr->InjectedArgs
- = new (getASTContext()) TemplateArgument[Params->size()];
- GenerateInjectedTemplateArgs(getASTContext(), Params,
- CommonPtr->InjectedArgs);
+ auto &Context = getASTContext();
+ SmallVector<TemplateArgument, 16> TemplateArgs;
+ Context.getInjectedTemplateArgs(Params, TemplateArgs);
+ CommonPtr->InjectedArgs =
+ new (Context) TemplateArgument[TemplateArgs.size()];
+ std::copy(TemplateArgs.begin(), TemplateArgs.end(),
+ CommonPtr->InjectedArgs);
}
return llvm::makeArrayRef(CommonPtr->InjectedArgs, Params->size());
@@ -457,8 +429,7 @@ ClassTemplateDecl::getInjectedClassNameSpecialization() {
ASTContext &Context = getASTContext();
TemplateParameterList *Params = getTemplateParameters();
SmallVector<TemplateArgument, 16> TemplateArgs;
- TemplateArgs.resize(Params->size());
- GenerateInjectedTemplateArgs(getASTContext(), Params, TemplateArgs.data());
+ Context.getInjectedTemplateArgs(Params, TemplateArgs);
CommonPtr->InjectedClassNameType
= Context.getTemplateSpecializationType(TemplateName(this),
TemplateArgs);
@@ -754,9 +725,16 @@ void ClassTemplateSpecializationDecl::getNameForDiagnostic(
raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const {
NamedDecl::getNameForDiagnostic(OS, Policy, Qualified);
- const TemplateArgumentList &TemplateArgs = getTemplateArgs();
- TemplateSpecializationType::PrintTemplateArgumentList(
- OS, TemplateArgs.asArray(), Policy);
+ auto *PS = dyn_cast<ClassTemplatePartialSpecializationDecl>(this);
+ if (const ASTTemplateArgumentListInfo *ArgsAsWritten =
+ PS ? PS->getTemplateArgsAsWritten() : nullptr) {
+ TemplateSpecializationType::PrintTemplateArgumentList(
+ OS, ArgsAsWritten->arguments(), Policy);
+ } else {
+ const TemplateArgumentList &TemplateArgs = getTemplateArgs();
+ TemplateSpecializationType::PrintTemplateArgumentList(
+ OS, TemplateArgs.asArray(), Policy);
+ }
}
ClassTemplateDecl *
@@ -1086,9 +1064,16 @@ void VarTemplateSpecializationDecl::getNameForDiagnostic(
raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const {
NamedDecl::getNameForDiagnostic(OS, Policy, Qualified);
- const TemplateArgumentList &TemplateArgs = getTemplateArgs();
- TemplateSpecializationType::PrintTemplateArgumentList(
- OS, TemplateArgs.asArray(), Policy);
+ auto *PS = dyn_cast<VarTemplatePartialSpecializationDecl>(this);
+ if (const ASTTemplateArgumentListInfo *ArgsAsWritten =
+ PS ? PS->getTemplateArgsAsWritten() : nullptr) {
+ TemplateSpecializationType::PrintTemplateArgumentList(
+ OS, ArgsAsWritten->arguments(), Policy);
+ } else {
+ const TemplateArgumentList &TemplateArgs = getTemplateArgs();
+ TemplateSpecializationType::PrintTemplateArgumentList(
+ OS, TemplateArgs.asArray(), Policy);
+ }
}
VarTemplateDecl *VarTemplateSpecializationDecl::getSpecializedTemplate() const {
@@ -1169,7 +1154,7 @@ createMakeIntegerSeqParameterList(const ASTContext &C, DeclContext *DC) {
// <typename T, T ...Ints>
NamedDecl *P[2] = {T, N};
auto *TPL = TemplateParameterList::Create(
- C, SourceLocation(), SourceLocation(), P, SourceLocation());
+ C, SourceLocation(), SourceLocation(), P, SourceLocation(), nullptr);
// template <typename T, ...Ints> class IntSeq
auto *TemplateTemplateParm = TemplateTemplateParmDecl::Create(
@@ -1194,7 +1179,7 @@ createMakeIntegerSeqParameterList(const ASTContext &C, DeclContext *DC) {
// template <template <typename T, T ...Ints> class IntSeq, typename T, T N>
return TemplateParameterList::Create(C, SourceLocation(), SourceLocation(),
- Params, SourceLocation());
+ Params, SourceLocation(), nullptr);
}
static TemplateParameterList *
@@ -1215,7 +1200,7 @@ createTypePackElementParameterList(const ASTContext &C, DeclContext *DC) {
NamedDecl *Params[] = {Index, Ts};
return TemplateParameterList::Create(C, SourceLocation(), SourceLocation(),
llvm::makeArrayRef(Params),
- SourceLocation());
+ SourceLocation(), nullptr);
}
static TemplateParameterList *createBuiltinTemplateParameterList(
diff --git a/lib/AST/DeclarationName.cpp b/lib/AST/DeclarationName.cpp
index 2a988e1d22d0..52791e51d2dc 100644
--- a/lib/AST/DeclarationName.cpp
+++ b/lib/AST/DeclarationName.cpp
@@ -11,14 +11,13 @@
// classes.
//
//===----------------------------------------------------------------------===//
+#include "clang/AST/DeclarationName.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclCXX.h"
-#include "clang/AST/DeclarationName.h"
#include "clang/AST/Type.h"
#include "clang/AST/TypeLoc.h"
#include "clang/AST/TypeOrdering.h"
#include "clang/Basic/IdentifierTable.h"
-#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
@@ -96,12 +95,18 @@ int DeclarationName::compare(DeclarationName LHS, DeclarationName RHS) {
case DeclarationName::ObjCMultiArgSelector: {
Selector LHSSelector = LHS.getObjCSelector();
Selector RHSSelector = RHS.getObjCSelector();
+ // getNumArgs for ZeroArgSelector returns 0, but we still need to compare.
+ if (LHS.getNameKind() == DeclarationName::ObjCZeroArgSelector &&
+ RHS.getNameKind() == DeclarationName::ObjCZeroArgSelector) {
+ return LHSSelector.getAsIdentifierInfo()->getName().compare(
+ RHSSelector.getAsIdentifierInfo()->getName());
+ }
unsigned LN = LHSSelector.getNumArgs(), RN = RHSSelector.getNumArgs();
for (unsigned I = 0, N = std::min(LN, RN); I != N; ++I) {
switch (LHSSelector.getNameForSlot(I).compare(
RHSSelector.getNameForSlot(I))) {
- case -1: return true;
- case 1: return false;
+ case -1: return -1;
+ case 1: return 1;
default: break;
}
}
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 091e8787d8b6..93f3ad5f2bdd 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -11,7 +11,6 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/AST/APValue.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
#include "clang/AST/DeclCXX.h"
@@ -36,9 +35,33 @@
#include <cstring>
using namespace clang;
-const CXXRecordDecl *Expr::getBestDynamicClassType() const {
- const Expr *E = ignoreParenBaseCasts();
+const Expr *Expr::getBestDynamicClassTypeExpr() const {
+ const Expr *E = this;
+ while (true) {
+ E = E->ignoreParenBaseCasts();
+
+ // Follow the RHS of a comma operator.
+ if (auto *BO = dyn_cast<BinaryOperator>(E)) {
+ if (BO->getOpcode() == BO_Comma) {
+ E = BO->getRHS();
+ continue;
+ }
+ }
+
+ // Step into initializer for materialized temporaries.
+ if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E)) {
+ E = MTE->GetTemporaryExpr();
+ continue;
+ }
+
+ break;
+ }
+
+ return E;
+}
+const CXXRecordDecl *Expr::getBestDynamicClassType() const {
+ const Expr *E = getBestDynamicClassTypeExpr();
QualType DerivedType = E->getType();
if (const PointerType *PTy = DerivedType->getAs<PointerType>())
DerivedType = PTy->getPointeeType();
@@ -403,7 +426,7 @@ DeclRefExpr *DeclRefExpr::Create(const ASTContext &Context,
HasTemplateKWAndArgsInfo ? 1 : 0,
TemplateArgs ? TemplateArgs->size() : 0);
- void *Mem = Context.Allocate(Size, llvm::alignOf<DeclRefExpr>());
+ void *Mem = Context.Allocate(Size, alignof(DeclRefExpr));
return new (Mem) DeclRefExpr(Context, QualifierLoc, TemplateKWLoc, D,
RefersToEnclosingVariableOrCapture,
NameInfo, FoundD, TemplateArgs, T, VK);
@@ -420,7 +443,7 @@ DeclRefExpr *DeclRefExpr::CreateEmpty(const ASTContext &Context,
ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(
HasQualifier ? 1 : 0, HasFoundDecl ? 1 : 0, HasTemplateKWAndArgsInfo,
NumTemplateArgs);
- void *Mem = Context.Allocate(Size, llvm::alignOf<DeclRefExpr>());
+ void *Mem = Context.Allocate(Size, alignof(DeclRefExpr));
return new (Mem) DeclRefExpr(EmptyShell());
}
@@ -495,20 +518,21 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) {
}
return "";
}
- if (auto *BD = dyn_cast<BlockDecl>(CurrentDecl)) {
- std::unique_ptr<MangleContext> MC;
- MC.reset(Context.createMangleContext());
- SmallString<256> Buffer;
- llvm::raw_svector_ostream Out(Buffer);
+ if (isa<BlockDecl>(CurrentDecl)) {
+ // For blocks we only emit something if it is enclosed in a function
+ // For top-level block we'd like to include the name of variable, but we
+ // don't have it at this point.
auto DC = CurrentDecl->getDeclContext();
if (DC->isFileContext())
- MC->mangleGlobalBlock(BD, /*ID*/ nullptr, Out);
- else if (const auto *CD = dyn_cast<CXXConstructorDecl>(DC))
- MC->mangleCtorBlock(CD, /*CT*/ Ctor_Complete, BD, Out);
- else if (const auto *DD = dyn_cast<CXXDestructorDecl>(DC))
- MC->mangleDtorBlock(DD, /*DT*/ Dtor_Complete, BD, Out);
- else
- MC->mangleBlock(DC, BD, Out);
+ return "";
+
+ SmallString<256> Buffer;
+ llvm::raw_svector_ostream Out(Buffer);
+ if (auto *DCBlock = dyn_cast<BlockDecl>(DC))
+ // For nested blocks, propagate up to the parent.
+ Out << ComputeName(IT, DCBlock);
+ else if (auto *DCDecl = dyn_cast<Decl>(DC))
+ Out << ComputeName(IT, DCDecl) << "_block_invoke";
return Out.str();
}
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CurrentDecl)) {
@@ -538,12 +562,14 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) {
FT = dyn_cast<FunctionProtoType>(AFT);
if (IT == FuncSig) {
+ assert(FT && "We must have a written prototype in this case.");
switch (FT->getCallConv()) {
case CC_C: POut << "__cdecl "; break;
case CC_X86StdCall: POut << "__stdcall "; break;
case CC_X86FastCall: POut << "__fastcall "; break;
case CC_X86ThisCall: POut << "__thiscall "; break;
case CC_X86VectorCall: POut << "__vectorcall "; break;
+ case CC_X86RegCall: POut << "__regcall "; break;
// Only bother printing the conventions that MSVC knows about.
default: break;
}
@@ -756,33 +782,33 @@ FloatingLiteral::Create(const ASTContext &C, EmptyShell Empty) {
const llvm::fltSemantics &FloatingLiteral::getSemantics() const {
switch(FloatingLiteralBits.Semantics) {
case IEEEhalf:
- return llvm::APFloat::IEEEhalf;
+ return llvm::APFloat::IEEEhalf();
case IEEEsingle:
- return llvm::APFloat::IEEEsingle;
+ return llvm::APFloat::IEEEsingle();
case IEEEdouble:
- return llvm::APFloat::IEEEdouble;
+ return llvm::APFloat::IEEEdouble();
case x87DoubleExtended:
- return llvm::APFloat::x87DoubleExtended;
+ return llvm::APFloat::x87DoubleExtended();
case IEEEquad:
- return llvm::APFloat::IEEEquad;
+ return llvm::APFloat::IEEEquad();
case PPCDoubleDouble:
- return llvm::APFloat::PPCDoubleDouble;
+ return llvm::APFloat::PPCDoubleDouble();
}
llvm_unreachable("Unrecognised floating semantics");
}
void FloatingLiteral::setSemantics(const llvm::fltSemantics &Sem) {
- if (&Sem == &llvm::APFloat::IEEEhalf)
+ if (&Sem == &llvm::APFloat::IEEEhalf())
FloatingLiteralBits.Semantics = IEEEhalf;
- else if (&Sem == &llvm::APFloat::IEEEsingle)
+ else if (&Sem == &llvm::APFloat::IEEEsingle())
FloatingLiteralBits.Semantics = IEEEsingle;
- else if (&Sem == &llvm::APFloat::IEEEdouble)
+ else if (&Sem == &llvm::APFloat::IEEEdouble())
FloatingLiteralBits.Semantics = IEEEdouble;
- else if (&Sem == &llvm::APFloat::x87DoubleExtended)
+ else if (&Sem == &llvm::APFloat::x87DoubleExtended())
FloatingLiteralBits.Semantics = x87DoubleExtended;
- else if (&Sem == &llvm::APFloat::IEEEquad)
+ else if (&Sem == &llvm::APFloat::IEEEquad())
FloatingLiteralBits.Semantics = IEEEquad;
- else if (&Sem == &llvm::APFloat::PPCDoubleDouble)
+ else if (&Sem == &llvm::APFloat::PPCDoubleDouble())
FloatingLiteralBits.Semantics = PPCDoubleDouble;
else
llvm_unreachable("Unknown floating semantics");
@@ -794,7 +820,7 @@ void FloatingLiteral::setSemantics(const llvm::fltSemantics &Sem) {
double FloatingLiteral::getValueAsApproximateDouble() const {
llvm::APFloat V = getValue();
bool ignored;
- V.convert(llvm::APFloat::IEEEdouble, llvm::APFloat::rmNearestTiesToEven,
+ V.convert(llvm::APFloat::IEEEdouble(), llvm::APFloat::rmNearestTiesToEven,
&ignored);
return V.convertToDouble();
}
@@ -832,9 +858,9 @@ StringLiteral *StringLiteral::Create(const ASTContext &C, StringRef Str,
// Allocate enough space for the StringLiteral plus an array of locations for
// any concatenated string tokens.
- void *Mem = C.Allocate(sizeof(StringLiteral)+
- sizeof(SourceLocation)*(NumStrs-1),
- llvm::alignOf<StringLiteral>());
+ void *Mem =
+ C.Allocate(sizeof(StringLiteral) + sizeof(SourceLocation) * (NumStrs - 1),
+ alignof(StringLiteral));
StringLiteral *SL = new (Mem) StringLiteral(Ty);
// OPTIMIZE: could allocate this appended to the StringLiteral.
@@ -850,9 +876,9 @@ StringLiteral *StringLiteral::Create(const ASTContext &C, StringRef Str,
StringLiteral *StringLiteral::CreateEmpty(const ASTContext &C,
unsigned NumStrs) {
- void *Mem = C.Allocate(sizeof(StringLiteral)+
- sizeof(SourceLocation)*(NumStrs-1),
- llvm::alignOf<StringLiteral>());
+ void *Mem =
+ C.Allocate(sizeof(StringLiteral) + sizeof(SourceLocation) * (NumStrs - 1),
+ alignof(StringLiteral));
StringLiteral *SL = new (Mem) StringLiteral(QualType());
SL->CharByteWidth = 0;
SL->Length = 0;
@@ -944,10 +970,13 @@ void StringLiteral::outputString(raw_ostream &OS) const {
// Handle some common non-printable cases to make dumps prettier.
case '\\': OS << "\\\\"; break;
case '"': OS << "\\\""; break;
- case '\n': OS << "\\n"; break;
- case '\t': OS << "\\t"; break;
case '\a': OS << "\\a"; break;
case '\b': OS << "\\b"; break;
+ case '\f': OS << "\\f"; break;
+ case '\n': OS << "\\n"; break;
+ case '\r': OS << "\\r"; break;
+ case '\t': OS << "\\t"; break;
+ case '\v': OS << "\\v"; break;
}
}
OS << '"';
@@ -1182,8 +1211,16 @@ void CallExpr::updateDependenciesFromArg(Expr *Arg) {
ExprBits.ContainsUnexpandedParameterPack = true;
}
+FunctionDecl *CallExpr::getDirectCallee() {
+ return dyn_cast_or_null<FunctionDecl>(getCalleeDecl());
+}
+
Decl *CallExpr::getCalleeDecl() {
- Expr *CEE = getCallee()->IgnoreParenImpCasts();
+ return getCallee()->getReferencedDeclOfCallee();
+}
+
+Decl *Expr::getReferencedDeclOfCallee() {
+ Expr *CEE = IgnoreParenImpCasts();
while (SubstNonTypeTemplateParmExpr *NTTP
= dyn_cast<SubstNonTypeTemplateParmExpr>(CEE)) {
@@ -1206,10 +1243,6 @@ Decl *CallExpr::getCalleeDecl() {
return nullptr;
}
-FunctionDecl *CallExpr::getDirectCallee() {
- return dyn_cast_or_null<FunctionDecl>(getCalleeDecl());
-}
-
/// setNumArgs - This changes the number of arguments present in this call.
/// Any orphaned expressions are deleted by this, and any new operands are set
/// to null.
@@ -1417,7 +1450,7 @@ MemberExpr *MemberExpr::Create(
HasTemplateKWAndArgsInfo ? 1 : 0,
targs ? targs->size() : 0);
- void *Mem = C.Allocate(Size, llvm::alignOf<MemberExpr>());
+ void *Mem = C.Allocate(Size, alignof(MemberExpr));
MemberExpr *E = new (Mem)
MemberExpr(base, isarrow, OperatorLoc, memberdecl, nameinfo, ty, vk, ok);
@@ -1570,6 +1603,8 @@ bool CastExpr::CastConsistency() const {
case CK_ARCReclaimReturnedObject:
case CK_ARCExtendBlockObject:
case CK_ZeroToOCLEvent:
+ case CK_ZeroToOCLQueue:
+ case CK_IntToOCLSampler:
assert(!getType()->isBooleanType() && "unheralded conversion to bool");
goto CheckNoBasePath;
@@ -1830,6 +1865,24 @@ bool InitListExpr::isStringLiteralInit() const {
return isa<StringLiteral>(Init) || isa<ObjCEncodeExpr>(Init);
}
+bool InitListExpr::isTransparent() const {
+ assert(isSemanticForm() && "syntactic form never semantically transparent");
+
+ // A glvalue InitListExpr is always just sugar.
+ if (isGLValue()) {
+ assert(getNumInits() == 1 && "multiple inits in glvalue init list");
+ return true;
+ }
+
+ // Otherwise, we're sugar if and only if we have exactly one initializer that
+ // is of the same type.
+ if (getNumInits() != 1 || !getInit(0))
+ return false;
+
+ return getType().getCanonicalType() ==
+ getInit(0)->getType().getCanonicalType();
+}
+
SourceLocation InitListExpr::getLocStart() const {
if (InitListExpr *SyntacticForm = getSyntacticForm())
return SyntacticForm->getLocStart();
@@ -2212,12 +2265,15 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc,
// effects (e.g. a placement new with an uninitialized POD).
case CXXDeleteExprClass:
return false;
+ case MaterializeTemporaryExprClass:
+ return cast<MaterializeTemporaryExpr>(this)->GetTemporaryExpr()
+ ->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx);
case CXXBindTemporaryExprClass:
- return (cast<CXXBindTemporaryExpr>(this)
- ->getSubExpr()->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx));
+ return cast<CXXBindTemporaryExpr>(this)->getSubExpr()
+ ->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx);
case ExprWithCleanupsClass:
- return (cast<ExprWithCleanups>(this)
- ->getSubExpr()->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx));
+ return cast<ExprWithCleanups>(this)->getSubExpr()
+ ->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx);
}
}
@@ -2748,7 +2804,8 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef,
CE->getCastKind() == CK_ToUnion ||
CE->getCastKind() == CK_ConstructorConversion ||
CE->getCastKind() == CK_NonAtomicToAtomic ||
- CE->getCastKind() == CK_AtomicToNonAtomic)
+ CE->getCastKind() == CK_AtomicToNonAtomic ||
+ CE->getCastKind() == CK_IntToOCLSampler)
return CE->getSubExpr()->isConstantInitializer(Ctx, false, Culprit);
break;
@@ -2843,6 +2900,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx,
case UnaryExprOrTypeTraitExprClass:
case AddrLabelExprClass:
case GNUNullExprClass:
+ case ArrayInitIndexExprClass:
case NoInitExprClass:
case CXXBoolLiteralExprClass:
case CXXNullPtrLiteralExprClass:
@@ -2919,6 +2977,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx,
case ExtVectorElementExprClass:
case DesignatedInitExprClass:
case DesignatedInitUpdateExprClass:
+ case ArrayInitLoopExprClass:
case ParenListExprClass:
case CXXPseudoDestructorExprClass:
case CXXStdInitializerListExprClass:
@@ -3307,11 +3366,16 @@ FieldDecl *Expr::getSourceBitField() {
if (Ivar->isBitField())
return Ivar;
- if (DeclRefExpr *DeclRef = dyn_cast<DeclRefExpr>(E))
+ if (DeclRefExpr *DeclRef = dyn_cast<DeclRefExpr>(E)) {
if (FieldDecl *Field = dyn_cast<FieldDecl>(DeclRef->getDecl()))
if (Field->isBitField())
return Field;
+ if (BindingDecl *BD = dyn_cast<BindingDecl>(DeclRef->getDecl()))
+ if (Expr *E = BD->getBinding())
+ return E->getSourceBitField();
+ }
+
if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(E)) {
if (BinOp->isAssignmentOp() && BinOp->getLHS())
return BinOp->getLHS()->getSourceBitField();
@@ -3328,6 +3392,7 @@ FieldDecl *Expr::getSourceBitField() {
}
bool Expr::refersToVectorElement() const {
+ // FIXME: Why do we not just look at the ObjectKind here?
const Expr *E = this->IgnoreParens();
while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
@@ -3344,6 +3409,11 @@ bool Expr::refersToVectorElement() const {
if (isa<ExtVectorElementExpr>(E))
return true;
+ if (auto *DRE = dyn_cast<DeclRefExpr>(E))
+ if (auto *BD = dyn_cast<BindingDecl>(DRE->getDecl()))
+ if (auto *E = BD->getBinding())
+ return E->refersToVectorElement();
+
return false;
}
@@ -3396,8 +3466,11 @@ bool ExtVectorElementExpr::containsDuplicateElements() const {
void ExtVectorElementExpr::getEncodedElementAccess(
SmallVectorImpl<uint32_t> &Elts) const {
StringRef Comp = Accessor->getName();
- if (Comp[0] == 's' || Comp[0] == 'S')
+ bool isNumericAccessor = false;
+ if (Comp[0] == 's' || Comp[0] == 'S') {
Comp = Comp.substr(1);
+ isNumericAccessor = true;
+ }
bool isHi = Comp == "hi";
bool isLo = Comp == "lo";
@@ -3416,7 +3489,7 @@ void ExtVectorElementExpr::getEncodedElementAccess(
else if (isOdd)
Index = 2 * i + 1;
else
- Index = ExtVectorType::getAccessorIdx(Comp[i]);
+ Index = ExtVectorType::getAccessorIdx(Comp[i], isNumericAccessor);
Elts.push_back(Index);
}
@@ -3589,7 +3662,7 @@ DesignatedInitExpr::Create(const ASTContext &C,
SourceLocation ColonOrEqualLoc,
bool UsesColonSyntax, Expr *Init) {
void *Mem = C.Allocate(totalSizeToAlloc<Stmt *>(IndexExprs.size() + 1),
- llvm::alignOf<DesignatedInitExpr>());
+ alignof(DesignatedInitExpr));
return new (Mem) DesignatedInitExpr(C, C.VoidTy, Designators,
ColonOrEqualLoc, UsesColonSyntax,
IndexExprs, Init);
@@ -3598,7 +3671,7 @@ DesignatedInitExpr::Create(const ASTContext &C,
DesignatedInitExpr *DesignatedInitExpr::CreateEmpty(const ASTContext &C,
unsigned NumIndexExprs) {
void *Mem = C.Allocate(totalSizeToAlloc<Stmt *>(NumIndexExprs + 1),
- llvm::alignOf<DesignatedInitExpr>());
+ alignof(DesignatedInitExpr));
return new (Mem) DesignatedInitExpr(NumIndexExprs + 1);
}
@@ -3738,7 +3811,7 @@ PseudoObjectExpr *PseudoObjectExpr::Create(const ASTContext &Context,
unsigned numSemanticExprs) {
void *buffer =
Context.Allocate(totalSizeToAlloc<Expr *>(1 + numSemanticExprs),
- llvm::alignOf<PseudoObjectExpr>());
+ alignof(PseudoObjectExpr));
return new(buffer) PseudoObjectExpr(sh, numSemanticExprs);
}
@@ -3766,7 +3839,7 @@ PseudoObjectExpr *PseudoObjectExpr::Create(const ASTContext &C, Expr *syntax,
}
void *buffer = C.Allocate(totalSizeToAlloc<Expr *>(semantics.size() + 1),
- llvm::alignOf<PseudoObjectExpr>());
+ alignof(PseudoObjectExpr));
return new(buffer) PseudoObjectExpr(type, VK, syntax, semantics,
resultIndex);
}
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index a13033d47467..ad510e0070e6 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -25,6 +25,22 @@ using namespace clang;
// Child Iterators for iterating over subexpressions/substatements
//===----------------------------------------------------------------------===//
+bool CXXOperatorCallExpr::isInfixBinaryOp() const {
+ // An infix binary operator is any operator with two arguments other than
+ // operator() and operator[]. Note that none of these operators can have
+ // default arguments, so it suffices to check the number of argument
+ // expressions.
+ if (getNumArgs() != 2)
+ return false;
+
+ switch (getOperator()) {
+ case OO_Call: case OO_Subscript:
+ return false;
+ default:
+ return true;
+ }
+}
+
bool CXXTypeidExpr::isPotentiallyEvaluated() const {
if (isTypeOperand())
return false;
@@ -62,7 +78,7 @@ SourceLocation CXXScalarValueInitExpr::getLocStart() const {
// CXXNewExpr
CXXNewExpr::CXXNewExpr(const ASTContext &C, bool globalNew,
FunctionDecl *operatorNew, FunctionDecl *operatorDelete,
- bool usualArrayDeleteWantsSize,
+ bool PassAlignment, bool usualArrayDeleteWantsSize,
ArrayRef<Expr*> placementArgs,
SourceRange typeIdParens, Expr *arraySize,
InitializationStyle initializationStyle,
@@ -76,7 +92,8 @@ CXXNewExpr::CXXNewExpr(const ASTContext &C, bool globalNew,
SubExprs(nullptr), OperatorNew(operatorNew), OperatorDelete(operatorDelete),
AllocatedTypeInfo(allocatedTypeInfo), TypeIdParens(typeIdParens),
Range(Range), DirectInitRange(directInitRange),
- GlobalNew(globalNew), UsualArrayDeleteWantsSize(usualArrayDeleteWantsSize) {
+ GlobalNew(globalNew), PassAlignment(PassAlignment),
+ UsualArrayDeleteWantsSize(usualArrayDeleteWantsSize) {
assert((initializer != nullptr || initializationStyle == NoInit) &&
"Only NoInit can have no initializer.");
StoredInitializationStyle = initializer ? initializationStyle + 1 : 0;
@@ -226,7 +243,7 @@ UnresolvedLookupExpr::Create(const ASTContext &C,
std::size_t Size =
totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(1,
num_args);
- void *Mem = C.Allocate(Size, llvm::alignOf<UnresolvedLookupExpr>());
+ void *Mem = C.Allocate(Size, alignof(UnresolvedLookupExpr));
return new (Mem) UnresolvedLookupExpr(C, NamingClass, QualifierLoc,
TemplateKWLoc, NameInfo,
ADL, /*Overload*/ true, Args,
@@ -241,7 +258,7 @@ UnresolvedLookupExpr::CreateEmpty(const ASTContext &C,
std::size_t Size =
totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(
HasTemplateKWAndArgsInfo, NumTemplateArgs);
- void *Mem = C.Allocate(Size, llvm::alignOf<UnresolvedLookupExpr>());
+ void *Mem = C.Allocate(Size, alignof(UnresolvedLookupExpr));
UnresolvedLookupExpr *E = new (Mem) UnresolvedLookupExpr(EmptyShell());
E->HasTemplateKWAndArgsInfo = HasTemplateKWAndArgsInfo;
return E;
@@ -284,9 +301,8 @@ OverloadExpr::OverloadExpr(StmtClass K, const ASTContext &C,
}
}
- Results = static_cast<DeclAccessPair *>(
- C.Allocate(sizeof(DeclAccessPair) * NumResults,
- llvm::alignOf<DeclAccessPair>()));
+ Results = static_cast<DeclAccessPair *>(C.Allocate(
+ sizeof(DeclAccessPair) * NumResults, alignof(DeclAccessPair)));
memcpy(Results, Begin.I, NumResults * sizeof(DeclAccessPair));
}
@@ -323,11 +339,11 @@ void OverloadExpr::initializeResults(const ASTContext &C,
assert(!Results && "Results already initialized!");
NumResults = End - Begin;
if (NumResults) {
- Results = static_cast<DeclAccessPair *>(
- C.Allocate(sizeof(DeclAccessPair) * NumResults,
-
- llvm::alignOf<DeclAccessPair>()));
- memcpy(Results, Begin.I, NumResults * sizeof(DeclAccessPair));
+ Results = static_cast<DeclAccessPair *>(
+ C.Allocate(sizeof(DeclAccessPair) * NumResults,
+
+ alignof(DeclAccessPair)));
+ memcpy(Results, Begin.I, NumResults * sizeof(DeclAccessPair));
}
}
@@ -853,8 +869,6 @@ LambdaExpr::LambdaExpr(QualType T, SourceRange IntroducerRange,
SourceLocation CaptureDefaultLoc,
ArrayRef<LambdaCapture> Captures, bool ExplicitParams,
bool ExplicitResultType, ArrayRef<Expr *> CaptureInits,
- ArrayRef<VarDecl *> ArrayIndexVars,
- ArrayRef<unsigned> ArrayIndexStarts,
SourceLocation ClosingBrace,
bool ContainsUnexpandedParameterPack)
: Expr(LambdaExprClass, T, VK_RValue, OK_Ordinary, T->isDependentType(),
@@ -891,17 +905,6 @@ LambdaExpr::LambdaExpr(QualType T, SourceRange IntroducerRange,
// Copy the body of the lambda.
*Stored++ = getCallOperator()->getBody();
-
- // Copy the array index variables, if any.
- HasArrayIndexVars = !ArrayIndexVars.empty();
- if (HasArrayIndexVars) {
- assert(ArrayIndexStarts.size() == NumCaptures);
- memcpy(getArrayIndexVars(), ArrayIndexVars.data(),
- sizeof(VarDecl *) * ArrayIndexVars.size());
- memcpy(getArrayIndexStarts(), ArrayIndexStarts.data(),
- sizeof(unsigned) * Captures.size());
- getArrayIndexStarts()[Captures.size()] = ArrayIndexVars.size();
- }
}
LambdaExpr *LambdaExpr::Create(
@@ -909,31 +912,24 @@ LambdaExpr *LambdaExpr::Create(
SourceRange IntroducerRange, LambdaCaptureDefault CaptureDefault,
SourceLocation CaptureDefaultLoc, ArrayRef<LambdaCapture> Captures,
bool ExplicitParams, bool ExplicitResultType, ArrayRef<Expr *> CaptureInits,
- ArrayRef<VarDecl *> ArrayIndexVars, ArrayRef<unsigned> ArrayIndexStarts,
SourceLocation ClosingBrace, bool ContainsUnexpandedParameterPack) {
// Determine the type of the expression (i.e., the type of the
// function object we're creating).
QualType T = Context.getTypeDeclType(Class);
- unsigned Size = totalSizeToAlloc<Stmt *, unsigned, VarDecl *>(
- Captures.size() + 1, ArrayIndexVars.empty() ? 0 : Captures.size() + 1,
- ArrayIndexVars.size());
+ unsigned Size = totalSizeToAlloc<Stmt *>(Captures.size() + 1);
void *Mem = Context.Allocate(Size);
- return new (Mem) LambdaExpr(T, IntroducerRange,
- CaptureDefault, CaptureDefaultLoc, Captures,
- ExplicitParams, ExplicitResultType,
- CaptureInits, ArrayIndexVars, ArrayIndexStarts,
- ClosingBrace, ContainsUnexpandedParameterPack);
+ return new (Mem)
+ LambdaExpr(T, IntroducerRange, CaptureDefault, CaptureDefaultLoc,
+ Captures, ExplicitParams, ExplicitResultType, CaptureInits,
+ ClosingBrace, ContainsUnexpandedParameterPack);
}
LambdaExpr *LambdaExpr::CreateDeserialized(const ASTContext &C,
- unsigned NumCaptures,
- unsigned NumArrayIndexVars) {
- unsigned Size = totalSizeToAlloc<Stmt *, unsigned, VarDecl *>(
- NumCaptures + 1, NumArrayIndexVars ? NumCaptures + 1 : 0,
- NumArrayIndexVars);
+ unsigned NumCaptures) {
+ unsigned Size = totalSizeToAlloc<Stmt *>(NumCaptures + 1);
void *Mem = C.Allocate(Size);
- return new (Mem) LambdaExpr(EmptyShell(), NumCaptures, NumArrayIndexVars > 0);
+ return new (Mem) LambdaExpr(EmptyShell(), NumCaptures);
}
bool LambdaExpr::isInitCapture(const LambdaCapture *C) const {
@@ -979,19 +975,6 @@ LambdaExpr::capture_range LambdaExpr::implicit_captures() const {
return capture_range(implicit_capture_begin(), implicit_capture_end());
}
-ArrayRef<VarDecl *>
-LambdaExpr::getCaptureInitIndexVars(const_capture_init_iterator Iter) const {
- assert(HasArrayIndexVars && "No array index-var data?");
-
- unsigned Index = Iter - capture_init_begin();
- assert(Index < getLambdaClass()->getLambdaData().NumCaptures &&
- "Capture index out-of-range");
- VarDecl *const *IndexVars = getArrayIndexVars();
- const unsigned *IndexStarts = getArrayIndexStarts();
- return llvm::makeArrayRef(IndexVars + IndexStarts[Index],
- IndexVars + IndexStarts[Index + 1]);
-}
-
CXXRecordDecl *LambdaExpr::getLambdaClass() const {
return getType()->getAsCXXRecordDecl();
}
@@ -1041,7 +1024,7 @@ ExprWithCleanups *ExprWithCleanups::Create(const ASTContext &C, Expr *subexpr,
bool CleanupsHaveSideEffects,
ArrayRef<CleanupObject> objects) {
void *buffer = C.Allocate(totalSizeToAlloc<CleanupObject>(objects.size()),
- llvm::alignOf<ExprWithCleanups>());
+ alignof(ExprWithCleanups));
return new (buffer)
ExprWithCleanups(subexpr, CleanupsHaveSideEffects, objects);
}
@@ -1055,7 +1038,7 @@ ExprWithCleanups *ExprWithCleanups::Create(const ASTContext &C,
EmptyShell empty,
unsigned numObjects) {
void *buffer = C.Allocate(totalSizeToAlloc<CleanupObject>(numObjects),
- llvm::alignOf<ExprWithCleanups>());
+ alignof(ExprWithCleanups));
return new (buffer) ExprWithCleanups(empty, numObjects);
}
@@ -1154,7 +1137,7 @@ CXXDependentScopeMemberExpr::Create(const ASTContext &C,
totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(
HasTemplateKWAndArgsInfo, NumTemplateArgs);
- void *Mem = C.Allocate(Size, llvm::alignOf<CXXDependentScopeMemberExpr>());
+ void *Mem = C.Allocate(Size, alignof(CXXDependentScopeMemberExpr));
return new (Mem) CXXDependentScopeMemberExpr(C, Base, BaseType,
IsArrow, OperatorLoc,
QualifierLoc,
@@ -1171,7 +1154,7 @@ CXXDependentScopeMemberExpr::CreateEmpty(const ASTContext &C,
std::size_t Size =
totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(
HasTemplateKWAndArgsInfo, NumTemplateArgs);
- void *Mem = C.Allocate(Size, llvm::alignOf<CXXDependentScopeMemberExpr>());
+ void *Mem = C.Allocate(Size, alignof(CXXDependentScopeMemberExpr));
CXXDependentScopeMemberExpr *E
= new (Mem) CXXDependentScopeMemberExpr(C, nullptr, QualType(),
0, SourceLocation(),
@@ -1255,7 +1238,7 @@ UnresolvedMemberExpr *UnresolvedMemberExpr::Create(
totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(
HasTemplateKWAndArgsInfo, TemplateArgs ? TemplateArgs->size() : 0);
- void *Mem = C.Allocate(Size, llvm::alignOf<UnresolvedMemberExpr>());
+ void *Mem = C.Allocate(Size, alignof(UnresolvedMemberExpr));
return new (Mem) UnresolvedMemberExpr(
C, HasUnresolvedUsing, Base, BaseType, IsArrow, OperatorLoc, QualifierLoc,
TemplateKWLoc, MemberNameInfo, TemplateArgs, Begin, End);
@@ -1270,7 +1253,7 @@ UnresolvedMemberExpr::CreateEmpty(const ASTContext &C,
totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(
HasTemplateKWAndArgsInfo, NumTemplateArgs);
- void *Mem = C.Allocate(Size, llvm::alignOf<UnresolvedMemberExpr>());
+ void *Mem = C.Allocate(Size, alignof(UnresolvedMemberExpr));
UnresolvedMemberExpr *E = new (Mem) UnresolvedMemberExpr(EmptyShell());
E->HasTemplateKWAndArgsInfo = HasTemplateKWAndArgsInfo;
return E;
diff --git a/lib/AST/ExprClassification.cpp b/lib/AST/ExprClassification.cpp
index 89cc9bc18ef0..adb74b80b198 100644
--- a/lib/AST/ExprClassification.cpp
+++ b/lib/AST/ExprClassification.cpp
@@ -141,10 +141,9 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
return Cl::CL_LValue;
// C99 6.5.2.5p5 says that compound literals are lvalues.
- // In C++, they're prvalue temporaries.
+ // In C++, they're prvalue temporaries, except for file-scope arrays.
case Expr::CompoundLiteralExprClass:
- return Ctx.getLangOpts().CPlusPlus ? ClassifyTemporary(E->getType())
- : Cl::CL_LValue;
+ return !E->isLValue() ? ClassifyTemporary(E->getType()) : Cl::CL_LValue;
// Expressions that are prvalues.
case Expr::CXXBoolLiteralExprClass:
@@ -186,6 +185,8 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
case Expr::ObjCIndirectCopyRestoreExprClass:
case Expr::AtomicExprClass:
case Expr::CXXFoldExprClass:
+ case Expr::ArrayInitLoopExprClass:
+ case Expr::ArrayInitIndexExprClass:
case Expr::NoInitExprClass:
case Expr::DesignatedInitUpdateExprClass:
case Expr::CoyieldExprClass:
@@ -196,11 +197,20 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
return ClassifyInternal(Ctx,
cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement());
- // C++ [expr.sub]p1: The result is an lvalue of type "T".
- // However, subscripting vector types is more like member access.
+ // C, C++98 [expr.sub]p1: The result is an lvalue of type "T".
+ // C++11 (DR1213): in the case of an array operand, the result is an lvalue
+ // if that operand is an lvalue and an xvalue otherwise.
+ // Subscripting vector types is more like member access.
case Expr::ArraySubscriptExprClass:
if (cast<ArraySubscriptExpr>(E)->getBase()->getType()->isVectorType())
return ClassifyInternal(Ctx, cast<ArraySubscriptExpr>(E)->getBase());
+ if (Lang.CPlusPlus11) {
+ // Step over the array-to-pointer decay if present, but not over the
+ // temporary materialization.
+ auto *Base = cast<ArraySubscriptExpr>(E)->getBase()->IgnoreImpCasts();
+ if (Base->getType()->isArrayType())
+ return ClassifyInternal(Ctx, Base);
+ }
return Cl::CL_LValue;
// C++ [expr.prim.general]p3: The result is an lvalue if the entity is a
@@ -429,6 +439,7 @@ static Cl::Kinds ClassifyDecl(ASTContext &Ctx, const Decl *D) {
else
islvalue = isa<VarDecl>(D) || isa<FieldDecl>(D) ||
isa<IndirectFieldDecl>(D) ||
+ isa<BindingDecl>(D) ||
(Ctx.getLangOpts().CPlusPlus &&
(isa<FunctionDecl>(D) || isa<MSPropertyDecl>(D) ||
isa<FunctionTemplateDecl>(D)));
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index df944e8f25f2..b3f8925b6464 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -36,6 +36,7 @@
#include "clang/AST/APValue.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTDiagnostic.h"
+#include "clang/AST/ASTLambda.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/Expr.h"
#include "clang/AST/RecordLayout.h"
@@ -43,7 +44,6 @@
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/TargetInfo.h"
-#include "llvm/ADT/SmallString.h"
#include "llvm/Support/raw_ostream.h"
#include <cstring>
#include <functional>
@@ -76,8 +76,8 @@ namespace {
const Expr *Inner = Temp->skipRValueSubobjectAdjustments(CommaLHSs,
Adjustments);
// Keep any cv-qualifiers from the reference if we generated a temporary
- // for it.
- if (Inner != Temp)
+ // for it directly. Otherwise use the type after adjustment.
+ if (!Adjustments.empty())
return Inner->getType();
}
@@ -109,19 +109,57 @@ namespace {
return getAsBaseOrMember(E).getInt();
}
+ /// Given a CallExpr, try to get the alloc_size attribute. May return null.
+ static const AllocSizeAttr *getAllocSizeAttr(const CallExpr *CE) {
+ const FunctionDecl *Callee = CE->getDirectCallee();
+ return Callee ? Callee->getAttr<AllocSizeAttr>() : nullptr;
+ }
+
+ /// Attempts to unwrap a CallExpr (with an alloc_size attribute) from an Expr.
+ /// This will look through a single cast.
+ ///
+ /// Returns null if we couldn't unwrap a function with alloc_size.
+ static const CallExpr *tryUnwrapAllocSizeCall(const Expr *E) {
+ if (!E->getType()->isPointerType())
+ return nullptr;
+
+ E = E->IgnoreParens();
+ // If we're doing a variable assignment from e.g. malloc(N), there will
+ // probably be a cast of some kind. Ignore it.
+ if (const auto *Cast = dyn_cast<CastExpr>(E))
+ E = Cast->getSubExpr()->IgnoreParens();
+
+ if (const auto *CE = dyn_cast<CallExpr>(E))
+ return getAllocSizeAttr(CE) ? CE : nullptr;
+ return nullptr;
+ }
+
+ /// Determines whether or not the given Base contains a call to a function
+ /// with the alloc_size attribute.
+ static bool isBaseAnAllocSizeCall(APValue::LValueBase Base) {
+ const auto *E = Base.dyn_cast<const Expr *>();
+ return E && E->getType()->isPointerType() && tryUnwrapAllocSizeCall(E);
+ }
+
+ /// Determines if an LValue with the given LValueBase will have an unsized
+ /// array in its designator.
/// Find the path length and type of the most-derived subobject in the given
/// path, and find the size of the containing array, if any.
- static
- unsigned findMostDerivedSubobject(ASTContext &Ctx, QualType Base,
- ArrayRef<APValue::LValuePathEntry> Path,
- uint64_t &ArraySize, QualType &Type,
- bool &IsArray) {
+ static unsigned
+ findMostDerivedSubobject(ASTContext &Ctx, APValue::LValueBase Base,
+ ArrayRef<APValue::LValuePathEntry> Path,
+ uint64_t &ArraySize, QualType &Type, bool &IsArray) {
+ // This only accepts LValueBases from APValues, and APValues don't support
+ // arrays that lack size info.
+ assert(!isBaseAnAllocSizeCall(Base) &&
+ "Unsized arrays shouldn't appear here");
unsigned MostDerivedLength = 0;
- Type = Base;
+ Type = getType(Base);
+
for (unsigned I = 0, N = Path.size(); I != N; ++I) {
if (Type->isArrayType()) {
const ConstantArrayType *CAT =
- cast<ConstantArrayType>(Ctx.getAsArrayType(Type));
+ cast<ConstantArrayType>(Ctx.getAsArrayType(Type));
Type = CAT->getElementType();
ArraySize = CAT->getSize().getZExtValue();
MostDerivedLength = I + 1;
@@ -162,17 +200,23 @@ namespace {
/// Is this a pointer one past the end of an object?
unsigned IsOnePastTheEnd : 1;
+ /// Indicator of whether the first entry is an unsized array.
+ unsigned FirstEntryIsAnUnsizedArray : 1;
+
/// Indicator of whether the most-derived object is an array element.
unsigned MostDerivedIsArrayElement : 1;
/// The length of the path to the most-derived object of which this is a
/// subobject.
- unsigned MostDerivedPathLength : 29;
+ unsigned MostDerivedPathLength : 28;
/// The size of the array of which the most-derived object is an element.
/// This will always be 0 if the most-derived object is not an array
/// element. 0 is not an indicator of whether or not the most-derived object
/// is an array, however, because 0-length arrays are allowed.
+ ///
+ /// If the current array is an unsized array, the value of this is
+ /// undefined.
uint64_t MostDerivedArraySize;
/// The type of the most derived object referred to by this address.
@@ -187,23 +231,24 @@ namespace {
explicit SubobjectDesignator(QualType T)
: Invalid(false), IsOnePastTheEnd(false),
- MostDerivedIsArrayElement(false), MostDerivedPathLength(0),
- MostDerivedArraySize(0), MostDerivedType(T) {}
+ FirstEntryIsAnUnsizedArray(false), MostDerivedIsArrayElement(false),
+ MostDerivedPathLength(0), MostDerivedArraySize(0),
+ MostDerivedType(T) {}
SubobjectDesignator(ASTContext &Ctx, const APValue &V)
: Invalid(!V.isLValue() || !V.hasLValuePath()), IsOnePastTheEnd(false),
- MostDerivedIsArrayElement(false), MostDerivedPathLength(0),
- MostDerivedArraySize(0) {
+ FirstEntryIsAnUnsizedArray(false), MostDerivedIsArrayElement(false),
+ MostDerivedPathLength(0), MostDerivedArraySize(0) {
+ assert(V.isLValue() && "Non-LValue used to make an LValue designator?");
if (!Invalid) {
IsOnePastTheEnd = V.isLValueOnePastTheEnd();
ArrayRef<PathEntry> VEntries = V.getLValuePath();
Entries.insert(Entries.end(), VEntries.begin(), VEntries.end());
if (V.getLValueBase()) {
bool IsArray = false;
- MostDerivedPathLength =
- findMostDerivedSubobject(Ctx, getType(V.getLValueBase()),
- V.getLValuePath(), MostDerivedArraySize,
- MostDerivedType, IsArray);
+ MostDerivedPathLength = findMostDerivedSubobject(
+ Ctx, V.getLValueBase(), V.getLValuePath(), MostDerivedArraySize,
+ MostDerivedType, IsArray);
MostDerivedIsArrayElement = IsArray;
}
}
@@ -214,12 +259,26 @@ namespace {
Entries.clear();
}
+ /// Determine whether the most derived subobject is an array without a
+ /// known bound.
+ bool isMostDerivedAnUnsizedArray() const {
+ assert(!Invalid && "Calling this makes no sense on invalid designators");
+ return Entries.size() == 1 && FirstEntryIsAnUnsizedArray;
+ }
+
+ /// Determine what the most derived array's size is. Results in an assertion
+ /// failure if the most derived array lacks a size.
+ uint64_t getMostDerivedArraySize() const {
+ assert(!isMostDerivedAnUnsizedArray() && "Unsized array has no size");
+ return MostDerivedArraySize;
+ }
+
/// Determine whether this is a one-past-the-end pointer.
bool isOnePastTheEnd() const {
assert(!Invalid);
if (IsOnePastTheEnd)
return true;
- if (MostDerivedIsArrayElement &&
+ if (!isMostDerivedAnUnsizedArray() && MostDerivedIsArrayElement &&
Entries[MostDerivedPathLength - 1].ArrayIndex == MostDerivedArraySize)
return true;
return false;
@@ -247,6 +306,21 @@ namespace {
MostDerivedArraySize = CAT->getSize().getZExtValue();
MostDerivedPathLength = Entries.size();
}
+ /// Update this designator to refer to the first element within the array of
+ /// elements of type T. This is an array of unknown size.
+ void addUnsizedArrayUnchecked(QualType ElemTy) {
+ PathEntry Entry;
+ Entry.ArrayIndex = 0;
+ Entries.push_back(Entry);
+
+ MostDerivedType = ElemTy;
+ MostDerivedIsArrayElement = true;
+ // The value in MostDerivedArraySize is undefined in this case. So, set it
+ // to an arbitrary value that's likely to loudly break things if it's
+ // used.
+ MostDerivedArraySize = std::numeric_limits<uint64_t>::max() / 2;
+ MostDerivedPathLength = Entries.size();
+ }
/// Update this designator to refer to the given base or member of this
/// object.
void addDeclUnchecked(const Decl *D, bool Virtual = false) {
@@ -280,10 +354,16 @@ namespace {
/// Add N to the address of this subobject.
void adjustIndex(EvalInfo &Info, const Expr *E, uint64_t N) {
if (Invalid) return;
+ if (isMostDerivedAnUnsizedArray()) {
+ // Can't verify -- trust that the user is doing the right thing (or if
+ // not, trust that the caller will catch the bad behavior).
+ Entries.back().ArrayIndex += N;
+ return;
+ }
if (MostDerivedPathLength == Entries.size() &&
MostDerivedIsArrayElement) {
Entries.back().ArrayIndex += N;
- if (Entries.back().ArrayIndex > MostDerivedArraySize) {
+ if (Entries.back().ArrayIndex > getMostDerivedArraySize()) {
diagnosePointerArithmetic(Info, E, Entries.back().ArrayIndex);
setInvalid();
}
@@ -310,15 +390,9 @@ namespace {
/// Parent - The caller of this stack frame.
CallStackFrame *Caller;
- /// CallLoc - The location of the call expression for this call.
- SourceLocation CallLoc;
-
/// Callee - The function which was called.
const FunctionDecl *Callee;
- /// Index - The call index of this call.
- unsigned Index;
-
/// This - The binding for the this pointer in this call, if any.
const LValue *This;
@@ -333,6 +407,12 @@ namespace {
/// Temporaries - Temporary lvalues materialized within this stack frame.
MapTy Temporaries;
+ /// CallLoc - The location of the call expression for this call.
+ SourceLocation CallLoc;
+
+ /// Index - The call index of this call.
+ unsigned Index;
+
CallStackFrame(EvalInfo &Info, SourceLocation CallLoc,
const FunctionDecl *Callee, const LValue *This,
APValue *Arguments);
@@ -433,7 +513,7 @@ namespace {
/// rules. For example, the RHS of (0 && foo()) is not evaluated. We can
/// evaluate the expression regardless of what the RHS is, but C only allows
/// certain things in certain situations.
- struct EvalInfo {
+ struct LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) EvalInfo {
ASTContext &Ctx;
/// EvalStatus - Contains information about the evaluation.
@@ -469,6 +549,10 @@ namespace {
/// declaration whose initializer is being evaluated, if any.
APValue *EvaluatingDeclValue;
+ /// The current array initialization index, if we're performing array
+ /// initialization.
+ uint64_t ArrayInitIndex = -1;
+
/// HasActiveDiagnostic - Was the previous diagnostic stored? If so, further
/// notes attached to it will also be stored, otherwise they will not be.
bool HasActiveDiagnostic;
@@ -520,9 +604,15 @@ namespace {
/// gets a chance to look at it.
EM_PotentialConstantExpressionUnevaluated,
- /// Evaluate as a constant expression. Continue evaluating if we find a
- /// MemberExpr with a base that can't be evaluated.
- EM_DesignatorFold,
+ /// Evaluate as a constant expression. Continue evaluating if either:
+ /// - We find a MemberExpr with a base that can't be evaluated.
+ /// - We find a variable initialized with a call to a function that has
+ /// the alloc_size attribute on it.
+ /// In either case, the LValue returned shall have an invalid base; in the
+ /// former, the base will be the invalid MemberExpr, in the latter, the
+ /// base will be either the alloc_size CallExpr or a CastExpr wrapping
+ /// said CallExpr.
+ EM_OffsetFold,
} EvalMode;
/// Are we checking whether the expression is a potential constant
@@ -624,7 +714,7 @@ namespace {
case EM_PotentialConstantExpression:
case EM_ConstantExpressionUnevaluated:
case EM_PotentialConstantExpressionUnevaluated:
- case EM_DesignatorFold:
+ case EM_OffsetFold:
HasActiveDiagnostic = false;
return OptionalDiagnostic();
}
@@ -716,7 +806,7 @@ namespace {
case EM_ConstantExpression:
case EM_ConstantExpressionUnevaluated:
case EM_ConstantFold:
- case EM_DesignatorFold:
+ case EM_OffsetFold:
return false;
}
llvm_unreachable("Missed EvalMode case");
@@ -735,7 +825,7 @@ namespace {
case EM_EvaluateForOverflow:
case EM_IgnoreSideEffects:
case EM_ConstantFold:
- case EM_DesignatorFold:
+ case EM_OffsetFold:
return true;
case EM_PotentialConstantExpression:
@@ -771,7 +861,7 @@ namespace {
case EM_ConstantExpressionUnevaluated:
case EM_ConstantFold:
case EM_IgnoreSideEffects:
- case EM_DesignatorFold:
+ case EM_OffsetFold:
return false;
}
llvm_unreachable("Missed EvalMode case");
@@ -787,7 +877,7 @@ namespace {
/// (Foo(), 1) // use noteSideEffect
/// (Foo() || true) // use noteSideEffect
/// Foo() + 1 // use noteFailure
- LLVM_ATTRIBUTE_UNUSED_RESULT bool noteFailure() {
+ LLVM_NODISCARD bool noteFailure() {
// Failure when evaluating some expression often means there is some
// subexpression whose evaluation was skipped. Therefore, (because we
// don't track whether we skipped an expression when unwinding after an
@@ -801,8 +891,22 @@ namespace {
}
bool allowInvalidBaseExpr() const {
- return EvalMode == EM_DesignatorFold;
+ return EvalMode == EM_OffsetFold;
}
+
+ class ArrayInitLoopIndex {
+ EvalInfo &Info;
+ uint64_t OuterIndex;
+
+ public:
+ ArrayInitLoopIndex(EvalInfo &Info)
+ : Info(Info), OuterIndex(Info.ArrayInitIndex) {
+ Info.ArrayInitIndex = 0;
+ }
+ ~ArrayInitLoopIndex() { Info.ArrayInitIndex = OuterIndex; }
+
+ operator uint64_t&() { return Info.ArrayInitIndex; }
+ };
};
/// Object used to treat all foldable expressions as constant expressions.
@@ -838,11 +942,10 @@ namespace {
struct FoldOffsetRAII {
EvalInfo &Info;
EvalInfo::EvaluationMode OldMode;
- explicit FoldOffsetRAII(EvalInfo &Info, bool Subobject)
+ explicit FoldOffsetRAII(EvalInfo &Info)
: Info(Info), OldMode(Info.EvalMode) {
if (!Info.checkingPotentialConstantExpression())
- Info.EvalMode = Subobject ? EvalInfo::EM_DesignatorFold
- : EvalInfo::EM_ConstantFold;
+ Info.EvalMode = EvalInfo::EM_OffsetFold;
}
~FoldOffsetRAII() { Info.EvalMode = OldMode; }
@@ -948,10 +1051,12 @@ bool SubobjectDesignator::checkSubobject(EvalInfo &Info, const Expr *E,
void SubobjectDesignator::diagnosePointerArithmetic(EvalInfo &Info,
const Expr *E, uint64_t N) {
+ // If we're complaining, we must be able to statically determine the size of
+ // the most derived array.
if (MostDerivedPathLength == Entries.size() && MostDerivedIsArrayElement)
Info.CCEDiag(E, diag::note_constexpr_array_index)
<< static_cast<int>(N) << /*array*/ 0
- << static_cast<unsigned>(MostDerivedArraySize);
+ << static_cast<unsigned>(getMostDerivedArraySize());
else
Info.CCEDiag(E, diag::note_constexpr_array_index)
<< static_cast<int>(N) << /*non-array*/ 1;
@@ -961,8 +1066,8 @@ void SubobjectDesignator::diagnosePointerArithmetic(EvalInfo &Info,
CallStackFrame::CallStackFrame(EvalInfo &Info, SourceLocation CallLoc,
const FunctionDecl *Callee, const LValue *This,
APValue *Arguments)
- : Info(Info), Caller(Info.CurrentCall), CallLoc(CallLoc), Callee(Callee),
- Index(Info.NextCallIndex++), This(This), Arguments(Arguments) {
+ : Info(Info), Caller(Info.CurrentCall), Callee(Callee), This(This),
+ Arguments(Arguments), CallLoc(CallLoc), Index(Info.NextCallIndex++) {
Info.CurrentCall = this;
++Info.CallStackDepth;
}
@@ -1032,7 +1137,7 @@ namespace {
APSInt IntReal, IntImag;
APFloat FloatReal, FloatImag;
- ComplexValue() : FloatReal(APFloat::Bogus), FloatImag(APFloat::Bogus) {}
+ ComplexValue() : FloatReal(APFloat::Bogus()), FloatImag(APFloat::Bogus()) {}
void makeComplexFloat() { IsInt = false; }
bool isComplexFloat() const { return !IsInt; }
@@ -1070,6 +1175,7 @@ namespace {
unsigned InvalidBase : 1;
unsigned CallIndex : 31;
SubobjectDesignator Designator;
+ bool IsNullPtr;
const APValue::LValueBase getLValueBase() const { return Base; }
CharUnits &getLValueOffset() { return Offset; }
@@ -1077,29 +1183,47 @@ namespace {
unsigned getLValueCallIndex() const { return CallIndex; }
SubobjectDesignator &getLValueDesignator() { return Designator; }
const SubobjectDesignator &getLValueDesignator() const { return Designator;}
+ bool isNullPointer() const { return IsNullPtr;}
void moveInto(APValue &V) const {
if (Designator.Invalid)
- V = APValue(Base, Offset, APValue::NoLValuePath(), CallIndex);
- else
+ V = APValue(Base, Offset, APValue::NoLValuePath(), CallIndex,
+ IsNullPtr);
+ else {
+ assert(!InvalidBase && "APValues can't handle invalid LValue bases");
+ assert(!Designator.FirstEntryIsAnUnsizedArray &&
+ "Unsized array with a valid base?");
V = APValue(Base, Offset, Designator.Entries,
- Designator.IsOnePastTheEnd, CallIndex);
+ Designator.IsOnePastTheEnd, CallIndex, IsNullPtr);
+ }
}
void setFrom(ASTContext &Ctx, const APValue &V) {
- assert(V.isLValue());
+ assert(V.isLValue() && "Setting LValue from a non-LValue?");
Base = V.getLValueBase();
Offset = V.getLValueOffset();
InvalidBase = false;
CallIndex = V.getLValueCallIndex();
Designator = SubobjectDesignator(Ctx, V);
+ IsNullPtr = V.isNullPointer();
}
- void set(APValue::LValueBase B, unsigned I = 0, bool BInvalid = false) {
+ void set(APValue::LValueBase B, unsigned I = 0, bool BInvalid = false,
+ bool IsNullPtr_ = false, uint64_t Offset_ = 0) {
+#ifndef NDEBUG
+ // We only allow a few types of invalid bases. Enforce that here.
+ if (BInvalid) {
+ const auto *E = B.get<const Expr *>();
+ assert((isa<MemberExpr>(E) || tryUnwrapAllocSizeCall(E)) &&
+ "Unexpected type of invalid base");
+ }
+#endif
+
Base = B;
- Offset = CharUnits::Zero();
+ Offset = CharUnits::fromQuantity(Offset_);
InvalidBase = BInvalid;
CallIndex = I;
Designator = SubobjectDesignator(getType(B));
+ IsNullPtr = IsNullPtr_;
}
void setInvalid(APValue::LValueBase B, unsigned I = 0) {
@@ -1112,7 +1236,7 @@ namespace {
CheckSubobjectKind CSK) {
if (Designator.Invalid)
return false;
- if (!Base) {
+ if (IsNullPtr) {
Info.CCEDiag(E, diag::note_constexpr_null_subobject)
<< CSK;
Designator.setInvalid();
@@ -1133,6 +1257,13 @@ namespace {
if (checkSubobject(Info, E, isa<FieldDecl>(D) ? CSK_Field : CSK_Base))
Designator.addDeclUnchecked(D, Virtual);
}
+ void addUnsizedArray(EvalInfo &Info, QualType ElemTy) {
+ assert(Designator.Entries.empty() && getType(Base)->isPointerType());
+ assert(isBaseAnAllocSizeCall(Base) &&
+ "Only alloc_size bases can have unsized arrays");
+ Designator.FirstEntryIsAnUnsizedArray = true;
+ Designator.addUnsizedArrayUnchecked(ElemTy);
+ }
void addArray(EvalInfo &Info, const Expr *E, const ConstantArrayType *CAT) {
if (checkSubobject(Info, E, CSK_ArrayToPointer))
Designator.addArrayUnchecked(CAT);
@@ -1141,9 +1272,22 @@ namespace {
if (checkSubobject(Info, E, Imag ? CSK_Imag : CSK_Real))
Designator.addComplexUnchecked(EltTy, Imag);
}
- void adjustIndex(EvalInfo &Info, const Expr *E, uint64_t N) {
- if (N && checkNullPointer(Info, E, CSK_ArrayIndex))
- Designator.adjustIndex(Info, E, N);
+ void clearIsNullPointer() {
+ IsNullPtr = false;
+ }
+ void adjustOffsetAndIndex(EvalInfo &Info, const Expr *E, uint64_t Index,
+ CharUnits ElementSize) {
+ // Compute the new offset in the appropriate width.
+ Offset += Index * ElementSize;
+ if (Index && checkNullPointer(Info, E, CSK_ArrayIndex))
+ Designator.adjustIndex(Info, E, Index);
+ if (Index)
+ clearIsNullPointer();
+ }
+ void adjustOffset(CharUnits N) {
+ Offset += N;
+ if (N.getQuantity())
+ clearIsNullPointer();
}
};
@@ -2018,7 +2162,7 @@ static bool HandleLValueMember(EvalInfo &Info, const Expr *E, LValue &LVal,
}
unsigned I = FD->getFieldIndex();
- LVal.Offset += Info.Ctx.toCharUnitsFromBits(RL->getFieldOffset(I));
+ LVal.adjustOffset(Info.Ctx.toCharUnitsFromBits(RL->getFieldOffset(I)));
LVal.addDecl(Info, E, FD);
return true;
}
@@ -2072,9 +2216,7 @@ static bool HandleLValueArrayAdjustment(EvalInfo &Info, const Expr *E,
if (!HandleSizeof(Info, E->getExprLoc(), EltTy, SizeOfPointee))
return false;
- // Compute the new offset in the appropriate width.
- LVal.Offset += Adjustment * SizeOfPointee;
- LVal.adjustIndex(Info, E, Adjustment);
+ LVal.adjustOffsetAndIndex(Info, E, Adjustment, SizeOfPointee);
return true;
}
@@ -2125,7 +2267,22 @@ static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E,
// If this is a local variable, dig out its value.
if (Frame) {
Result = Frame->getTemporary(VD);
- assert(Result && "missing value for local variable");
+ if (!Result) {
+ // Assume variables referenced within a lambda's call operator that were
+ // not declared within the call operator are captures and during checking
+ // of a potential constant expression, assume they are unknown constant
+ // expressions.
+ assert(isLambdaCallOperator(Frame->Callee) &&
+ (VD->getDeclContext() != Frame->Callee || VD->isInitCapture()) &&
+ "missing value for local variable");
+ if (Info.checkingPotentialConstantExpression())
+ return false;
+ // FIXME: implement capture evaluation during constant expr evaluation.
+ Info.FFDiag(E->getLocStart(),
+ diag::note_unimplemented_constexpr_lambda_feature_ast)
+ << "captures not currently allowed";
+ return false;
+ }
return true;
}
@@ -2771,6 +2928,9 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
} else {
Info.CCEDiag(E);
}
+ } else if (BaseType.isConstQualified() && VD->hasDefinition(Info.Ctx)) {
+ Info.CCEDiag(E, diag::note_constexpr_ltor_non_constexpr) << VD;
+ // Keep evaluating to see what we can do.
} else {
// FIXME: Allow folding of values of any literal type in all languages.
if (Info.checkingPotentialConstantExpression() &&
@@ -2892,7 +3052,6 @@ static bool handleLValueToRValueConversion(EvalInfo &Info, const Expr *Conv,
// In C99, a CompoundLiteralExpr is an lvalue, and we defer evaluating the
// initializer until now for such expressions. Such an expression can't be
// an ICE in C, so this only matters for fold.
- assert(!Info.getLangOpts().CPlusPlus && "lvalue compound literal in c++?");
if (Type.isVolatileQualified()) {
Info.FFDiag(Conv);
return false;
@@ -3385,38 +3544,51 @@ enum EvalStmtResult {
};
}
-static bool EvaluateDecl(EvalInfo &Info, const Decl *D) {
- if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
- // We don't need to evaluate the initializer for a static local.
- if (!VD->hasLocalStorage())
- return true;
+static bool EvaluateVarDecl(EvalInfo &Info, const VarDecl *VD) {
+ // We don't need to evaluate the initializer for a static local.
+ if (!VD->hasLocalStorage())
+ return true;
- LValue Result;
- Result.set(VD, Info.CurrentCall->Index);
- APValue &Val = Info.CurrentCall->createTemporary(VD, true);
+ LValue Result;
+ Result.set(VD, Info.CurrentCall->Index);
+ APValue &Val = Info.CurrentCall->createTemporary(VD, true);
- const Expr *InitE = VD->getInit();
- if (!InitE) {
- Info.FFDiag(D->getLocStart(), diag::note_constexpr_uninitialized)
- << false << VD->getType();
- Val = APValue();
- return false;
- }
+ const Expr *InitE = VD->getInit();
+ if (!InitE) {
+ Info.FFDiag(VD->getLocStart(), diag::note_constexpr_uninitialized)
+ << false << VD->getType();
+ Val = APValue();
+ return false;
+ }
- if (InitE->isValueDependent())
- return false;
+ if (InitE->isValueDependent())
+ return false;
- if (!EvaluateInPlace(Val, Info, Result, InitE)) {
- // Wipe out any partially-computed value, to allow tracking that this
- // evaluation failed.
- Val = APValue();
- return false;
- }
+ if (!EvaluateInPlace(Val, Info, Result, InitE)) {
+ // Wipe out any partially-computed value, to allow tracking that this
+ // evaluation failed.
+ Val = APValue();
+ return false;
}
return true;
}
+static bool EvaluateDecl(EvalInfo &Info, const Decl *D) {
+ bool OK = true;
+
+ if (const VarDecl *VD = dyn_cast<VarDecl>(D))
+ OK &= EvaluateVarDecl(Info, VD);
+
+ if (const DecompositionDecl *DD = dyn_cast<DecompositionDecl>(D))
+ for (auto *BD : DD->bindings())
+ if (auto *VD = BD->getHoldingVar())
+ OK &= EvaluateDecl(Info, VD);
+
+ return OK;
+}
+
+
/// Evaluate a condition (either a variable declaration or an expression).
static bool EvaluateCond(EvalInfo &Info, const VarDecl *CondDecl,
const Expr *Cond, bool &Result) {
@@ -4389,8 +4561,11 @@ public:
}
// Don't call function pointers which have been cast to some other type.
- if (!Info.Ctx.hasSameType(CalleeType->getPointeeType(), FD->getType()))
+ // Per DR (no number yet), the caller and callee can differ in noexcept.
+ if (!Info.Ctx.hasSameFunctionTypeIgnoringExceptionSpec(
+ CalleeType->getPointeeType(), FD->getType())) {
return Error(E);
+ }
} else
return Error(E);
@@ -4683,7 +4858,7 @@ public:
// * VarDecl
// * FunctionDecl
// - Literals
-// * CompoundLiteralExpr in C
+// * CompoundLiteralExpr in C (and in global scope in C++)
// * StringLiteral
// * CXXTypeidExpr
// * PredefinedExpr
@@ -4770,13 +4945,26 @@ bool LValueExprEvaluator::VisitDeclRefExpr(const DeclRefExpr *E) {
return Success(FD);
if (const VarDecl *VD = dyn_cast<VarDecl>(E->getDecl()))
return VisitVarDecl(E, VD);
+ if (const BindingDecl *BD = dyn_cast<BindingDecl>(E->getDecl()))
+ return Visit(BD->getBinding());
return Error(E);
}
+
bool LValueExprEvaluator::VisitVarDecl(const Expr *E, const VarDecl *VD) {
CallStackFrame *Frame = nullptr;
- if (VD->hasLocalStorage() && Info.CurrentCall->Index > 1)
- Frame = Info.CurrentCall;
+ if (VD->hasLocalStorage() && Info.CurrentCall->Index > 1) {
+ // Only if a local variable was declared in the function currently being
+ // evaluated, do we expect to be able to find its value in the current
+ // frame. (Otherwise it was likely declared in an enclosing context and
+ // could either have a valid evaluatable value (for e.g. a constexpr
+ // variable) or be ill-formed (and trigger an appropriate evaluation
+ // diagnostic)).
+ if (Info.CurrentCall->Callee &&
+ Info.CurrentCall->Callee->Equals(VD->getDeclContext())) {
+ Frame = Info.CurrentCall;
+ }
+ }
if (!VD->getType()->isReferenceType()) {
if (Frame) {
@@ -4865,7 +5053,8 @@ bool LValueExprEvaluator::VisitMaterializeTemporaryExpr(
bool
LValueExprEvaluator::VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) {
- assert(!Info.getLangOpts().CPlusPlus && "lvalue compound literal in c++?");
+ assert((!Info.getLangOpts().CPlusPlus || E->isFileScope()) &&
+ "lvalue compound literal in c++?");
// Defer visiting the literal until the lvalue-to-rvalue conversion. We can
// only see this when folding in C, so there's no standard to follow here.
return Success(E);
@@ -5000,6 +5189,105 @@ bool LValueExprEvaluator::VisitBinAssign(const BinaryOperator *E) {
// Pointer Evaluation
//===----------------------------------------------------------------------===//
+/// \brief Attempts to compute the number of bytes available at the pointer
+/// returned by a function with the alloc_size attribute. Returns true if we
+/// were successful. Places an unsigned number into `Result`.
+///
+/// This expects the given CallExpr to be a call to a function with an
+/// alloc_size attribute.
+static bool getBytesReturnedByAllocSizeCall(const ASTContext &Ctx,
+ const CallExpr *Call,
+ llvm::APInt &Result) {
+ const AllocSizeAttr *AllocSize = getAllocSizeAttr(Call);
+
+ // alloc_size args are 1-indexed, 0 means not present.
+ assert(AllocSize && AllocSize->getElemSizeParam() != 0);
+ unsigned SizeArgNo = AllocSize->getElemSizeParam() - 1;
+ unsigned BitsInSizeT = Ctx.getTypeSize(Ctx.getSizeType());
+ if (Call->getNumArgs() <= SizeArgNo)
+ return false;
+
+ auto EvaluateAsSizeT = [&](const Expr *E, APSInt &Into) {
+ if (!E->EvaluateAsInt(Into, Ctx, Expr::SE_AllowSideEffects))
+ return false;
+ if (Into.isNegative() || !Into.isIntN(BitsInSizeT))
+ return false;
+ Into = Into.zextOrSelf(BitsInSizeT);
+ return true;
+ };
+
+ APSInt SizeOfElem;
+ if (!EvaluateAsSizeT(Call->getArg(SizeArgNo), SizeOfElem))
+ return false;
+
+ if (!AllocSize->getNumElemsParam()) {
+ Result = std::move(SizeOfElem);
+ return true;
+ }
+
+ APSInt NumberOfElems;
+ // Argument numbers start at 1
+ unsigned NumArgNo = AllocSize->getNumElemsParam() - 1;
+ if (!EvaluateAsSizeT(Call->getArg(NumArgNo), NumberOfElems))
+ return false;
+
+ bool Overflow;
+ llvm::APInt BytesAvailable = SizeOfElem.umul_ov(NumberOfElems, Overflow);
+ if (Overflow)
+ return false;
+
+ Result = std::move(BytesAvailable);
+ return true;
+}
+
+/// \brief Convenience function. LVal's base must be a call to an alloc_size
+/// function.
+static bool getBytesReturnedByAllocSizeCall(const ASTContext &Ctx,
+ const LValue &LVal,
+ llvm::APInt &Result) {
+ assert(isBaseAnAllocSizeCall(LVal.getLValueBase()) &&
+ "Can't get the size of a non alloc_size function");
+ const auto *Base = LVal.getLValueBase().get<const Expr *>();
+ const CallExpr *CE = tryUnwrapAllocSizeCall(Base);
+ return getBytesReturnedByAllocSizeCall(Ctx, CE, Result);
+}
+
+/// \brief Attempts to evaluate the given LValueBase as the result of a call to
+/// a function with the alloc_size attribute. If it was possible to do so, this
+/// function will return true, make Result's Base point to said function call,
+/// and mark Result's Base as invalid.
+static bool evaluateLValueAsAllocSize(EvalInfo &Info, APValue::LValueBase Base,
+ LValue &Result) {
+ if (!Info.allowInvalidBaseExpr() || Base.isNull())
+ return false;
+
+ // Because we do no form of static analysis, we only support const variables.
+ //
+ // Additionally, we can't support parameters, nor can we support static
+ // variables (in the latter case, use-before-assign isn't UB; in the former,
+ // we have no clue what they'll be assigned to).
+ const auto *VD =
+ dyn_cast_or_null<VarDecl>(Base.dyn_cast<const ValueDecl *>());
+ if (!VD || !VD->isLocalVarDecl() || !VD->getType().isConstQualified())
+ return false;
+
+ const Expr *Init = VD->getAnyInitializer();
+ if (!Init)
+ return false;
+
+ const Expr *E = Init->IgnoreParens();
+ if (!tryUnwrapAllocSizeCall(E))
+ return false;
+
+ // Store E instead of E unwrapped so that the type of the LValue's base is
+ // what the user wanted.
+ Result.setInvalid(E);
+
+ QualType Pointee = E->getType()->castAs<PointerType>()->getPointeeType();
+ Result.addUnsizedArray(Info, Pointee);
+ return true;
+}
+
namespace {
class PointerExprEvaluator
: public ExprEvaluatorBase<PointerExprEvaluator> {
@@ -5009,6 +5297,8 @@ class PointerExprEvaluator
Result.set(E);
return true;
}
+
+ bool visitNonBuiltinCallExpr(const CallExpr *E);
public:
PointerExprEvaluator(EvalInfo &info, LValue &Result)
@@ -5019,7 +5309,9 @@ public:
return true;
}
bool ZeroInitialization(const Expr *E) {
- return Success((Expr*)nullptr);
+ auto Offset = Info.Ctx.getTargetNullPointerValue(E->getType());
+ Result.set((Expr*)nullptr, 0, false, true, Offset);
+ return true;
}
bool VisitBinaryOperator(const BinaryOperator *E);
@@ -5032,6 +5324,7 @@ public:
bool VisitAddrLabelExpr(const AddrLabelExpr *E)
{ return Success(E); }
bool VisitCallExpr(const CallExpr *E);
+ bool VisitBuiltinCallExpr(const CallExpr *E, unsigned BuiltinOp);
bool VisitBlockExpr(const BlockExpr *E) {
if (!E->getBlockDecl()->hasCaptures())
return Success(E);
@@ -5117,6 +5410,8 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) {
else
CCEDiag(E, diag::note_constexpr_invalid_cast) << 2;
}
+ if (E->getCastKind() == CK_AddressSpaceConversion && Result.IsNullPtr)
+ ZeroInitialization(E);
return true;
case CK_DerivedToBase:
@@ -5158,6 +5453,7 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) {
Result.Offset = CharUnits::fromQuantity(N);
Result.CallIndex = 0;
Result.Designator.setInvalid();
+ Result.IsNullPtr = false;
return true;
} else {
// Cast is of an lvalue, no need to change value.
@@ -5185,6 +5481,19 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) {
case CK_FunctionToPointerDecay:
return EvaluateLValue(SubExpr, Result, Info);
+
+ case CK_LValueToRValue: {
+ LValue LVal;
+ if (!EvaluateLValue(E->getSubExpr(), LVal, Info))
+ return false;
+
+ APValue RVal;
+ // Note, we use the subexpression's type in order to retain cv-qualifiers.
+ if (!handleLValueToRValueConversion(Info, E, E->getSubExpr()->getType(),
+ LVal, RVal))
+ return evaluateLValueAsAllocSize(Info, LVal.Base, Result);
+ return Success(RVal, E);
+ }
}
return ExprEvaluatorBaseTy::VisitCastExpr(E);
@@ -5222,11 +5531,33 @@ static CharUnits GetAlignOfExpr(EvalInfo &Info, const Expr *E) {
return GetAlignOfType(Info, E->getType());
}
+// To be clear: this happily visits unsupported builtins. Better name welcomed.
+bool PointerExprEvaluator::visitNonBuiltinCallExpr(const CallExpr *E) {
+ if (ExprEvaluatorBaseTy::VisitCallExpr(E))
+ return true;
+
+ if (!(Info.allowInvalidBaseExpr() && getAllocSizeAttr(E)))
+ return false;
+
+ Result.setInvalid(E);
+ QualType PointeeTy = E->getType()->castAs<PointerType>()->getPointeeType();
+ Result.addUnsizedArray(Info, PointeeTy);
+ return true;
+}
+
bool PointerExprEvaluator::VisitCallExpr(const CallExpr *E) {
if (IsStringLiteralCall(E))
return Success(E);
- switch (E->getBuiltinCallee()) {
+ if (unsigned BuiltinOp = E->getBuiltinCallee())
+ return VisitBuiltinCallExpr(E, BuiltinOp);
+
+ return visitNonBuiltinCallExpr(E);
+}
+
+bool PointerExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
+ unsigned BuiltinOp) {
+ switch (BuiltinOp) {
case Builtin::BI__builtin_addressof:
return EvaluateLValue(E->getArg(0), Result, Info);
case Builtin::BI__builtin_assume_aligned: {
@@ -5264,8 +5595,8 @@ bool PointerExprEvaluator::VisitCallExpr(const CallExpr *E) {
if (BaseAlignment < Align) {
Result.Designator.setInvalid();
- // FIXME: Quantities here cast to integers because the plural modifier
- // does not work on APSInts yet.
+ // FIXME: Quantities here cast to integers because the plural modifier
+ // does not work on APSInts yet.
CCEDiag(E->getArg(0),
diag::note_constexpr_baa_insufficient_alignment) << 0
<< (int) BaseAlignment.getQuantity()
@@ -5294,8 +5625,93 @@ bool PointerExprEvaluator::VisitCallExpr(const CallExpr *E) {
return true;
}
+
+ case Builtin::BIstrchr:
+ case Builtin::BIwcschr:
+ case Builtin::BImemchr:
+ case Builtin::BIwmemchr:
+ if (Info.getLangOpts().CPlusPlus11)
+ Info.CCEDiag(E, diag::note_constexpr_invalid_function)
+ << /*isConstexpr*/0 << /*isConstructor*/0
+ << (std::string("'") + Info.Ctx.BuiltinInfo.getName(BuiltinOp) + "'");
+ else
+ Info.CCEDiag(E, diag::note_invalid_subexpr_in_const_expr);
+ // Fall through.
+ case Builtin::BI__builtin_strchr:
+ case Builtin::BI__builtin_wcschr:
+ case Builtin::BI__builtin_memchr:
+ case Builtin::BI__builtin_wmemchr: {
+ if (!Visit(E->getArg(0)))
+ return false;
+ APSInt Desired;
+ if (!EvaluateInteger(E->getArg(1), Desired, Info))
+ return false;
+ uint64_t MaxLength = uint64_t(-1);
+ if (BuiltinOp != Builtin::BIstrchr &&
+ BuiltinOp != Builtin::BIwcschr &&
+ BuiltinOp != Builtin::BI__builtin_strchr &&
+ BuiltinOp != Builtin::BI__builtin_wcschr) {
+ APSInt N;
+ if (!EvaluateInteger(E->getArg(2), N, Info))
+ return false;
+ MaxLength = N.getExtValue();
+ }
+
+ QualType CharTy = E->getArg(0)->getType()->getPointeeType();
+
+ // Figure out what value we're actually looking for (after converting to
+ // the corresponding unsigned type if necessary).
+ uint64_t DesiredVal;
+ bool StopAtNull = false;
+ switch (BuiltinOp) {
+ case Builtin::BIstrchr:
+ case Builtin::BI__builtin_strchr:
+ // strchr compares directly to the passed integer, and therefore
+ // always fails if given an int that is not a char.
+ if (!APSInt::isSameValue(HandleIntToIntCast(Info, E, CharTy,
+ E->getArg(1)->getType(),
+ Desired),
+ Desired))
+ return ZeroInitialization(E);
+ StopAtNull = true;
+ // Fall through.
+ case Builtin::BImemchr:
+ case Builtin::BI__builtin_memchr:
+ // memchr compares by converting both sides to unsigned char. That's also
+ // correct for strchr if we get this far (to cope with plain char being
+ // unsigned in the strchr case).
+ DesiredVal = Desired.trunc(Info.Ctx.getCharWidth()).getZExtValue();
+ break;
+
+ case Builtin::BIwcschr:
+ case Builtin::BI__builtin_wcschr:
+ StopAtNull = true;
+ // Fall through.
+ case Builtin::BIwmemchr:
+ case Builtin::BI__builtin_wmemchr:
+ // wcschr and wmemchr are given a wchar_t to look for. Just use it.
+ DesiredVal = Desired.getZExtValue();
+ break;
+ }
+
+ for (; MaxLength; --MaxLength) {
+ APValue Char;
+ if (!handleLValueToRValueConversion(Info, E, CharTy, Result, Char) ||
+ !Char.isInt())
+ return false;
+ if (Char.getInt().getZExtValue() == DesiredVal)
+ return true;
+ if (StopAtNull && !Char.getInt())
+ break;
+ if (!HandleLValueArrayAdjustment(Info, E, Result, CharTy, 1))
+ return false;
+ }
+ // Not found: return nullptr.
+ return ZeroInitialization(E);
+ }
+
default:
- return ExprEvaluatorBaseTy::VisitCallExpr(E);
+ return visitNonBuiltinCallExpr(E);
}
}
@@ -5535,6 +5951,9 @@ bool RecordExprEvaluator::VisitCastExpr(const CastExpr *E) {
}
bool RecordExprEvaluator::VisitInitListExpr(const InitListExpr *E) {
+ if (E->isTransparent())
+ return Visit(E->getInit(0));
+
const RecordDecl *RD = E->getType()->castAs<RecordType>()->getDecl();
if (RD->isInvalidDecl()) return false;
const ASTRecordLayout &Layout = Info.Ctx.getASTRecordLayout(RD);
@@ -5890,7 +6309,7 @@ bool VectorExprEvaluator::VisitCastExpr(const CastExpr *E) {
if (EltTy->isRealFloatingType()) {
const llvm::fltSemantics &Sem = Info.Ctx.getFloatTypeSemantics(EltTy);
unsigned FloatEltSize = EltSize;
- if (&Sem == &APFloat::x87DoubleExtended)
+ if (&Sem == &APFloat::x87DoubleExtended())
FloatEltSize = 80;
for (unsigned i = 0; i < NElts; i++) {
llvm::APInt Elt;
@@ -6030,6 +6449,7 @@ namespace {
return handleCallExpr(E, Result, &This);
}
bool VisitInitListExpr(const InitListExpr *E);
+ bool VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E);
bool VisitCXXConstructExpr(const CXXConstructExpr *E);
bool VisitCXXConstructExpr(const CXXConstructExpr *E,
const LValue &Subobject,
@@ -6112,6 +6532,35 @@ bool ArrayExprEvaluator::VisitInitListExpr(const InitListExpr *E) {
FillerExpr) && Success;
}
+bool ArrayExprEvaluator::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E) {
+ if (E->getCommonExpr() &&
+ !Evaluate(Info.CurrentCall->createTemporary(E->getCommonExpr(), false),
+ Info, E->getCommonExpr()->getSourceExpr()))
+ return false;
+
+ auto *CAT = cast<ConstantArrayType>(E->getType()->castAsArrayTypeUnsafe());
+
+ uint64_t Elements = CAT->getSize().getZExtValue();
+ Result = APValue(APValue::UninitArray(), Elements, Elements);
+
+ LValue Subobject = This;
+ Subobject.addArray(Info, E, CAT);
+
+ bool Success = true;
+ for (EvalInfo::ArrayInitLoopIndex Index(Info); Index != Elements; ++Index) {
+ if (!EvaluateInPlace(Result.getArrayInitializedElt(Index),
+ Info, Subobject, E->getSubExpr()) ||
+ !HandleLValueArrayAdjustment(Info, E, Subobject,
+ CAT->getElementType(), 1)) {
+ if (!Info.noteFailure())
+ return false;
+ Success = false;
+ }
+ }
+
+ return Success;
+}
+
bool ArrayExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E) {
return VisitCXXConstructExpr(E, This, &Result, E->getType());
}
@@ -6252,6 +6701,7 @@ public:
}
bool VisitCallExpr(const CallExpr *E);
+ bool VisitBuiltinCallExpr(const CallExpr *E, unsigned BuiltinOp);
bool VisitBinaryOperator(const BinaryOperator *E);
bool VisitOffsetOfExpr(const OffsetOfExpr *E);
bool VisitUnaryOperator(const UnaryOperator *E);
@@ -6266,6 +6716,16 @@ public:
bool VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *E) {
return Success(E->getValue(), E);
}
+
+ bool VisitArrayInitIndexExpr(const ArrayInitIndexExpr *E) {
+ if (Info.ArrayInitIndex == uint64_t(-1)) {
+ // We were asked to evaluate this subexpression independent of the
+ // enclosing ArrayInitLoopExpr. We can't do that.
+ Info.FFDiag(E);
+ return false;
+ }
+ return Success(Info.ArrayInitIndex, E);
+ }
// Note, GNU defines __null as an integer, not a pointer.
bool VisitGNUNullExpr(const GNUNullExpr *E) {
@@ -6290,8 +6750,6 @@ public:
bool VisitCXXNoexceptExpr(const CXXNoexceptExpr *E);
bool VisitSizeOfPackExpr(const SizeOfPackExpr *E);
-private:
- bool TryEvaluateBuiltinObjectSize(const CallExpr *E, unsigned Type);
// FIXME: Missing: array subscript of vector, member of vector
};
} // end anonymous namespace
@@ -6563,7 +7021,7 @@ static QualType getObjectType(APValue::LValueBase B) {
}
/// A more selective version of E->IgnoreParenCasts for
-/// TryEvaluateBuiltinObjectSize. This ignores some casts/parens that serve only
+/// tryEvaluateBuiltinObjectSize. This ignores some casts/parens that serve only
/// to change the type of E.
/// Ex. For E = `(short*)((char*)(&foo))`, returns `&foo`
///
@@ -6630,82 +7088,191 @@ static bool isDesignatorAtObjectEnd(const ASTContext &Ctx, const LValue &LVal) {
}
}
+ unsigned I = 0;
QualType BaseType = getType(Base);
- for (int I = 0, E = LVal.Designator.Entries.size(); I != E; ++I) {
+ if (LVal.Designator.FirstEntryIsAnUnsizedArray) {
+ assert(isBaseAnAllocSizeCall(Base) &&
+ "Unsized array in non-alloc_size call?");
+ // If this is an alloc_size base, we should ignore the initial array index
+ ++I;
+ BaseType = BaseType->castAs<PointerType>()->getPointeeType();
+ }
+
+ for (unsigned E = LVal.Designator.Entries.size(); I != E; ++I) {
+ const auto &Entry = LVal.Designator.Entries[I];
if (BaseType->isArrayType()) {
// Because __builtin_object_size treats arrays as objects, we can ignore
// the index iff this is the last array in the Designator.
if (I + 1 == E)
return true;
- auto *CAT = cast<ConstantArrayType>(Ctx.getAsArrayType(BaseType));
- uint64_t Index = LVal.Designator.Entries[I].ArrayIndex;
+ const auto *CAT = cast<ConstantArrayType>(Ctx.getAsArrayType(BaseType));
+ uint64_t Index = Entry.ArrayIndex;
if (Index + 1 != CAT->getSize())
return false;
BaseType = CAT->getElementType();
} else if (BaseType->isAnyComplexType()) {
- auto *CT = BaseType->castAs<ComplexType>();
- uint64_t Index = LVal.Designator.Entries[I].ArrayIndex;
+ const auto *CT = BaseType->castAs<ComplexType>();
+ uint64_t Index = Entry.ArrayIndex;
if (Index != 1)
return false;
BaseType = CT->getElementType();
- } else if (auto *FD = getAsField(LVal.Designator.Entries[I])) {
+ } else if (auto *FD = getAsField(Entry)) {
bool Invalid;
if (!IsLastOrInvalidFieldDecl(FD, Invalid))
return Invalid;
BaseType = FD->getType();
} else {
- assert(getAsBaseClass(LVal.Designator.Entries[I]) != nullptr &&
- "Expecting cast to a base class");
+ assert(getAsBaseClass(Entry) && "Expecting cast to a base class");
return false;
}
}
return true;
}
-/// Tests to see if the LValue has a designator (that isn't necessarily valid).
+/// Tests to see if the LValue has a user-specified designator (that isn't
+/// necessarily valid). Note that this always returns 'true' if the LValue has
+/// an unsized array as its first designator entry, because there's currently no
+/// way to tell if the user typed *foo or foo[0].
static bool refersToCompleteObject(const LValue &LVal) {
- if (LVal.Designator.Invalid || !LVal.Designator.Entries.empty())
+ if (LVal.Designator.Invalid)
return false;
+ if (!LVal.Designator.Entries.empty())
+ return LVal.Designator.isMostDerivedAnUnsizedArray();
+
if (!LVal.InvalidBase)
return true;
- auto *E = LVal.Base.dyn_cast<const Expr *>();
- (void)E;
- assert(E != nullptr && isa<MemberExpr>(E));
- return false;
+ // If `E` is a MemberExpr, then the first part of the designator is hiding in
+ // the LValueBase.
+ const auto *E = LVal.Base.dyn_cast<const Expr *>();
+ return !E || !isa<MemberExpr>(E);
+}
+
+/// Attempts to detect a user writing into a piece of memory that's impossible
+/// to figure out the size of by just using types.
+static bool isUserWritingOffTheEnd(const ASTContext &Ctx, const LValue &LVal) {
+ const SubobjectDesignator &Designator = LVal.Designator;
+ // Notes:
+ // - Users can only write off of the end when we have an invalid base. Invalid
+ // bases imply we don't know where the memory came from.
+ // - We used to be a bit more aggressive here; we'd only be conservative if
+ // the array at the end was flexible, or if it had 0 or 1 elements. This
+ // broke some common standard library extensions (PR30346), but was
+ // otherwise seemingly fine. It may be useful to reintroduce this behavior
+ // with some sort of whitelist. OTOH, it seems that GCC is always
+ // conservative with the last element in structs (if it's an array), so our
+ // current behavior is more compatible than a whitelisting approach would
+ // be.
+ return LVal.InvalidBase &&
+ Designator.Entries.size() == Designator.MostDerivedPathLength &&
+ Designator.MostDerivedIsArrayElement &&
+ isDesignatorAtObjectEnd(Ctx, LVal);
+}
+
+/// Converts the given APInt to CharUnits, assuming the APInt is unsigned.
+/// Fails if the conversion would cause loss of precision.
+static bool convertUnsignedAPIntToCharUnits(const llvm::APInt &Int,
+ CharUnits &Result) {
+ auto CharUnitsMax = std::numeric_limits<CharUnits::QuantityType>::max();
+ if (Int.ugt(CharUnitsMax))
+ return false;
+ Result = CharUnits::fromQuantity(Int.getZExtValue());
+ return true;
}
-/// Tries to evaluate the __builtin_object_size for @p E. If successful, returns
-/// true and stores the result in @p Size.
+/// Helper for tryEvaluateBuiltinObjectSize -- Given an LValue, this will
+/// determine how many bytes exist from the beginning of the object to either
+/// the end of the current subobject, or the end of the object itself, depending
+/// on what the LValue looks like + the value of Type.
///
-/// If @p WasError is non-null, this will report whether the failure to evaluate
-/// is to be treated as an Error in IntExprEvaluator.
-static bool tryEvaluateBuiltinObjectSize(const Expr *E, unsigned Type,
- EvalInfo &Info, uint64_t &Size,
- bool *WasError = nullptr) {
- if (WasError != nullptr)
- *WasError = false;
-
- auto Error = [&](const Expr *E) {
- if (WasError != nullptr)
- *WasError = true;
+/// If this returns false, the value of Result is undefined.
+static bool determineEndOffset(EvalInfo &Info, SourceLocation ExprLoc,
+ unsigned Type, const LValue &LVal,
+ CharUnits &EndOffset) {
+ bool DetermineForCompleteObject = refersToCompleteObject(LVal);
+
+ // We want to evaluate the size of the entire object. This is a valid fallback
+ // for when Type=1 and the designator is invalid, because we're asked for an
+ // upper-bound.
+ if (!(Type & 1) || LVal.Designator.Invalid || DetermineForCompleteObject) {
+ // Type=3 wants a lower bound, so we can't fall back to this.
+ if (Type == 3 && !DetermineForCompleteObject)
+ return false;
+
+ llvm::APInt APEndOffset;
+ if (isBaseAnAllocSizeCall(LVal.getLValueBase()) &&
+ getBytesReturnedByAllocSizeCall(Info.Ctx, LVal, APEndOffset))
+ return convertUnsignedAPIntToCharUnits(APEndOffset, EndOffset);
+
+ if (LVal.InvalidBase)
+ return false;
+
+ QualType BaseTy = getObjectType(LVal.getLValueBase());
+ return !BaseTy.isNull() && HandleSizeof(Info, ExprLoc, BaseTy, EndOffset);
+ }
+
+ // We want to evaluate the size of a subobject.
+ const SubobjectDesignator &Designator = LVal.Designator;
+
+ // The following is a moderately common idiom in C:
+ //
+ // struct Foo { int a; char c[1]; };
+ // struct Foo *F = (struct Foo *)malloc(sizeof(struct Foo) + strlen(Bar));
+ // strcpy(&F->c[0], Bar);
+ //
+ // In order to not break too much legacy code, we need to support it.
+ if (isUserWritingOffTheEnd(Info.Ctx, LVal)) {
+ // If we can resolve this to an alloc_size call, we can hand that back,
+ // because we know for certain how many bytes there are to write to.
+ llvm::APInt APEndOffset;
+ if (isBaseAnAllocSizeCall(LVal.getLValueBase()) &&
+ getBytesReturnedByAllocSizeCall(Info.Ctx, LVal, APEndOffset))
+ return convertUnsignedAPIntToCharUnits(APEndOffset, EndOffset);
+
+ // If we cannot determine the size of the initial allocation, then we can't
+ // given an accurate upper-bound. However, we are still able to give
+ // conservative lower-bounds for Type=3.
+ if (Type == 1)
+ return false;
+ }
+
+ CharUnits BytesPerElem;
+ if (!HandleSizeof(Info, ExprLoc, Designator.MostDerivedType, BytesPerElem))
return false;
- };
- auto Success = [&](uint64_t S, const Expr *E) {
- Size = S;
- return true;
- };
+ // According to the GCC documentation, we want the size of the subobject
+ // denoted by the pointer. But that's not quite right -- what we actually
+ // want is the size of the immediately-enclosing array, if there is one.
+ int64_t ElemsRemaining;
+ if (Designator.MostDerivedIsArrayElement &&
+ Designator.Entries.size() == Designator.MostDerivedPathLength) {
+ uint64_t ArraySize = Designator.getMostDerivedArraySize();
+ uint64_t ArrayIndex = Designator.Entries.back().ArrayIndex;
+ ElemsRemaining = ArraySize <= ArrayIndex ? 0 : ArraySize - ArrayIndex;
+ } else {
+ ElemsRemaining = Designator.isOnePastTheEnd() ? 0 : 1;
+ }
+ EndOffset = LVal.getLValueOffset() + BytesPerElem * ElemsRemaining;
+ return true;
+}
+
+/// \brief Tries to evaluate the __builtin_object_size for @p E. If successful,
+/// returns true and stores the result in @p Size.
+///
+/// If @p WasError is non-null, this will report whether the failure to evaluate
+/// is to be treated as an Error in IntExprEvaluator.
+static bool tryEvaluateBuiltinObjectSize(const Expr *E, unsigned Type,
+ EvalInfo &Info, uint64_t &Size) {
// Determine the denoted object.
- LValue Base;
+ LValue LVal;
{
// The operand of __builtin_object_size is never evaluated for side-effects.
// If there are any, but we can determine the pointed-to object anyway, then
// ignore the side-effects.
SpeculativeEvaluationRAII SpeculativeEval(Info);
- FoldOffsetRAII Fold(Info, Type & 1);
+ FoldOffsetRAII Fold(Info);
if (E->isGLValue()) {
// It's possible for us to be given GLValues if we're called via
@@ -6713,118 +7280,40 @@ static bool tryEvaluateBuiltinObjectSize(const Expr *E, unsigned Type,
APValue RVal;
if (!EvaluateAsRValue(Info, E, RVal))
return false;
- Base.setFrom(Info.Ctx, RVal);
- } else if (!EvaluatePointer(ignorePointerCastsAndParens(E), Base, Info))
+ LVal.setFrom(Info.Ctx, RVal);
+ } else if (!EvaluatePointer(ignorePointerCastsAndParens(E), LVal, Info))
return false;
}
- CharUnits BaseOffset = Base.getLValueOffset();
// If we point to before the start of the object, there are no accessible
// bytes.
- if (BaseOffset.isNegative())
- return Success(0, E);
-
- // In the case where we're not dealing with a subobject, we discard the
- // subobject bit.
- bool SubobjectOnly = (Type & 1) != 0 && !refersToCompleteObject(Base);
-
- // If Type & 1 is 0, we need to be able to statically guarantee that the bytes
- // exist. If we can't verify the base, then we can't do that.
- //
- // As a special case, we produce a valid object size for an unknown object
- // with a known designator if Type & 1 is 1. For instance:
- //
- // extern struct X { char buff[32]; int a, b, c; } *p;
- // int a = __builtin_object_size(p->buff + 4, 3); // returns 28
- // int b = __builtin_object_size(p->buff + 4, 2); // returns 0, not 40
- //
- // This matches GCC's behavior.
- if (Base.InvalidBase && !SubobjectOnly)
- return Error(E);
-
- // If we're not examining only the subobject, then we reset to a complete
- // object designator
- //
- // If Type is 1 and we've lost track of the subobject, just find the complete
- // object instead. (If Type is 3, that's not correct behavior and we should
- // return 0 instead.)
- LValue End = Base;
- if (!SubobjectOnly || (End.Designator.Invalid && Type == 1)) {
- QualType T = getObjectType(End.getLValueBase());
- if (T.isNull())
- End.Designator.setInvalid();
- else {
- End.Designator = SubobjectDesignator(T);
- End.Offset = CharUnits::Zero();
- }
+ if (LVal.getLValueOffset().isNegative()) {
+ Size = 0;
+ return true;
}
- // If it is not possible to determine which objects ptr points to at compile
- // time, __builtin_object_size should return (size_t) -1 for type 0 or 1
- // and (size_t) 0 for type 2 or 3.
- if (End.Designator.Invalid)
- return false;
-
- // According to the GCC documentation, we want the size of the subobject
- // denoted by the pointer. But that's not quite right -- what we actually
- // want is the size of the immediately-enclosing array, if there is one.
- int64_t AmountToAdd = 1;
- if (End.Designator.MostDerivedIsArrayElement &&
- End.Designator.Entries.size() == End.Designator.MostDerivedPathLength) {
- // We got a pointer to an array. Step to its end.
- AmountToAdd = End.Designator.MostDerivedArraySize -
- End.Designator.Entries.back().ArrayIndex;
- } else if (End.Designator.isOnePastTheEnd()) {
- // We're already pointing at the end of the object.
- AmountToAdd = 0;
- }
-
- QualType PointeeType = End.Designator.MostDerivedType;
- assert(!PointeeType.isNull());
- if (PointeeType->isIncompleteType() || PointeeType->isFunctionType())
- return Error(E);
-
- if (!HandleLValueArrayAdjustment(Info, E, End, End.Designator.MostDerivedType,
- AmountToAdd))
- return false;
-
- auto EndOffset = End.getLValueOffset();
-
- // The following is a moderately common idiom in C:
- //
- // struct Foo { int a; char c[1]; };
- // struct Foo *F = (struct Foo *)malloc(sizeof(struct Foo) + strlen(Bar));
- // strcpy(&F->c[0], Bar);
- //
- // So, if we see that we're examining a 1-length (or 0-length) array at the
- // end of a struct with an unknown base, we give up instead of breaking code
- // that behaves this way. Note that we only do this when Type=1, because
- // Type=3 is a lower bound, so answering conservatively is fine.
- if (End.InvalidBase && SubobjectOnly && Type == 1 &&
- End.Designator.Entries.size() == End.Designator.MostDerivedPathLength &&
- End.Designator.MostDerivedIsArrayElement &&
- End.Designator.MostDerivedArraySize < 2 &&
- isDesignatorAtObjectEnd(Info.Ctx, End))
+ CharUnits EndOffset;
+ if (!determineEndOffset(Info, E->getExprLoc(), Type, LVal, EndOffset))
return false;
- if (BaseOffset > EndOffset)
- return Success(0, E);
-
- return Success((EndOffset - BaseOffset).getQuantity(), E);
+ // If we've fallen outside of the end offset, just pretend there's nothing to
+ // write to/read from.
+ if (EndOffset <= LVal.getLValueOffset())
+ Size = 0;
+ else
+ Size = (EndOffset - LVal.getLValueOffset()).getQuantity();
+ return true;
}
-bool IntExprEvaluator::TryEvaluateBuiltinObjectSize(const CallExpr *E,
- unsigned Type) {
- uint64_t Size;
- bool WasError;
- if (::tryEvaluateBuiltinObjectSize(E->getArg(0), Type, Info, Size, &WasError))
- return Success(Size, E);
- if (WasError)
- return Error(E);
- return false;
+bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) {
+ if (unsigned BuiltinOp = E->getBuiltinCallee())
+ return VisitBuiltinCallExpr(E, BuiltinOp);
+
+ return ExprEvaluatorBaseTy::VisitCallExpr(E);
}
-bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) {
+bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
+ unsigned BuiltinOp) {
switch (unsigned BuiltinOp = E->getBuiltinCallee()) {
default:
return ExprEvaluatorBaseTy::VisitCallExpr(E);
@@ -6835,8 +7324,9 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) {
E->getArg(1)->EvaluateKnownConstInt(Info.Ctx).getZExtValue();
assert(Type <= 3 && "unexpected type");
- if (TryEvaluateBuiltinObjectSize(E, Type))
- return true;
+ uint64_t Size;
+ if (tryEvaluateBuiltinObjectSize(E->getArg(0), Type, Info, Size))
+ return Success(Size, E);
if (E->getArg(0)->HasSideEffects(Info.Ctx))
return Success((Type & 2) ? 0 : -1, E);
@@ -6849,7 +7339,7 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) {
case EvalInfo::EM_ConstantFold:
case EvalInfo::EM_EvaluateForOverflow:
case EvalInfo::EM_IgnoreSideEffects:
- case EvalInfo::EM_DesignatorFold:
+ case EvalInfo::EM_OffsetFold:
// Leave it to IR generation.
return Error(E);
case EvalInfo::EM_ConstantExpressionUnevaluated:
@@ -6857,6 +7347,8 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) {
// Reduce it to a constant now.
return Success((Type & 2) ? 0 : -1, E);
}
+
+ llvm_unreachable("unexpected EvalMode");
}
case Builtin::BI__builtin_bswap16:
@@ -6990,20 +7482,25 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) {
}
case Builtin::BIstrlen:
+ case Builtin::BIwcslen:
// A call to strlen is not a constant expression.
if (Info.getLangOpts().CPlusPlus11)
Info.CCEDiag(E, diag::note_constexpr_invalid_function)
- << /*isConstexpr*/0 << /*isConstructor*/0 << "'strlen'";
+ << /*isConstexpr*/0 << /*isConstructor*/0
+ << (std::string("'") + Info.Ctx.BuiltinInfo.getName(BuiltinOp) + "'");
else
Info.CCEDiag(E, diag::note_invalid_subexpr_in_const_expr);
// Fall through.
- case Builtin::BI__builtin_strlen: {
+ case Builtin::BI__builtin_strlen:
+ case Builtin::BI__builtin_wcslen: {
// As an extension, we support __builtin_strlen() as a constant expression,
// and support folding strlen() to a constant.
LValue String;
if (!EvaluatePointer(E->getArg(0), String, Info))
return false;
+ QualType CharTy = E->getArg(0)->getType()->getPointeeType();
+
// Fast path: if it's a string literal, search the string value.
if (const StringLiteral *S = dyn_cast_or_null<StringLiteral>(
String.getLValueBase().dyn_cast<const Expr *>())) {
@@ -7012,7 +7509,9 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) {
StringRef Str = S->getBytes();
int64_t Off = String.Offset.getQuantity();
if (Off >= 0 && (uint64_t)Off <= (uint64_t)Str.size() &&
- S->getCharByteWidth() == 1) {
+ S->getCharByteWidth() == 1 &&
+ // FIXME: Add fast-path for wchar_t too.
+ Info.Ctx.hasSameUnqualifiedType(CharTy, Info.Ctx.CharTy)) {
Str = Str.substr(Off);
StringRef::size_type Pos = Str.find(0);
@@ -7026,7 +7525,6 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) {
}
// Slow path: scan the bytes of the string looking for the terminating 0.
- QualType CharTy = E->getArg(0)->getType()->getPointeeType();
for (uint64_t Strlen = 0; /**/; ++Strlen) {
APValue Char;
if (!handleLValueToRValueConversion(Info, E, CharTy, String, Char) ||
@@ -7039,6 +7537,66 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) {
}
}
+ case Builtin::BIstrcmp:
+ case Builtin::BIwcscmp:
+ case Builtin::BIstrncmp:
+ case Builtin::BIwcsncmp:
+ case Builtin::BImemcmp:
+ case Builtin::BIwmemcmp:
+ // A call to strlen is not a constant expression.
+ if (Info.getLangOpts().CPlusPlus11)
+ Info.CCEDiag(E, diag::note_constexpr_invalid_function)
+ << /*isConstexpr*/0 << /*isConstructor*/0
+ << (std::string("'") + Info.Ctx.BuiltinInfo.getName(BuiltinOp) + "'");
+ else
+ Info.CCEDiag(E, diag::note_invalid_subexpr_in_const_expr);
+ // Fall through.
+ case Builtin::BI__builtin_strcmp:
+ case Builtin::BI__builtin_wcscmp:
+ case Builtin::BI__builtin_strncmp:
+ case Builtin::BI__builtin_wcsncmp:
+ case Builtin::BI__builtin_memcmp:
+ case Builtin::BI__builtin_wmemcmp: {
+ LValue String1, String2;
+ if (!EvaluatePointer(E->getArg(0), String1, Info) ||
+ !EvaluatePointer(E->getArg(1), String2, Info))
+ return false;
+
+ QualType CharTy = E->getArg(0)->getType()->getPointeeType();
+
+ uint64_t MaxLength = uint64_t(-1);
+ if (BuiltinOp != Builtin::BIstrcmp &&
+ BuiltinOp != Builtin::BIwcscmp &&
+ BuiltinOp != Builtin::BI__builtin_strcmp &&
+ BuiltinOp != Builtin::BI__builtin_wcscmp) {
+ APSInt N;
+ if (!EvaluateInteger(E->getArg(2), N, Info))
+ return false;
+ MaxLength = N.getExtValue();
+ }
+ bool StopAtNull = (BuiltinOp != Builtin::BImemcmp &&
+ BuiltinOp != Builtin::BIwmemcmp &&
+ BuiltinOp != Builtin::BI__builtin_memcmp &&
+ BuiltinOp != Builtin::BI__builtin_wmemcmp);
+ for (; MaxLength; --MaxLength) {
+ APValue Char1, Char2;
+ if (!handleLValueToRValueConversion(Info, E, CharTy, String1, Char1) ||
+ !handleLValueToRValueConversion(Info, E, CharTy, String2, Char2) ||
+ !Char1.isInt() || !Char2.isInt())
+ return false;
+ if (Char1.getInt() != Char2.getInt())
+ return Success(Char1.getInt() < Char2.getInt() ? -1 : 1, E);
+ if (StopAtNull && !Char1.getInt())
+ return Success(0, E);
+ assert(!(StopAtNull && !Char2.getInt()));
+ if (!HandleLValueArrayAdjustment(Info, E, String1, CharTy, 1) ||
+ !HandleLValueArrayAdjustment(Info, E, String2, CharTy, 1))
+ return false;
+ }
+ // We hit the strncmp / memcmp limit.
+ return Success(0, E);
+ }
+
case Builtin::BI__atomic_always_lock_free:
case Builtin::BI__atomic_is_lock_free:
case Builtin::BI__c11_atomic_is_lock_free: {
@@ -7160,9 +7718,7 @@ class DataRecursiveIntBinOpEvaluator {
enum { AnyExprKind, BinOpKind, BinOpVisitedLHSKind } Kind;
Job() = default;
- Job(Job &&J)
- : E(J.E), LHSResult(J.LHSResult), Kind(J.Kind),
- SpecEvalRAII(std::move(J.SpecEvalRAII)) {}
+ Job(Job &&) = default;
void startSpeculativeEval(EvalInfo &Info) {
SpecEvalRAII = SpeculativeEvaluationRAII(Info);
@@ -8037,8 +8593,10 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) {
case CK_IntegralComplexToFloatingComplex:
case CK_BuiltinFnToFnPtr:
case CK_ZeroToOCLEvent:
+ case CK_ZeroToOCLQueue:
case CK_NonAtomicToAtomic:
case CK_AddressSpaceConversion:
+ case CK_IntToOCLSampler:
llvm_unreachable("invalid cast kind for integral value");
case CK_BitCast:
@@ -8113,8 +8671,13 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) {
return true;
}
- APSInt AsInt = Info.Ctx.MakeIntValue(LV.getLValueOffset().getQuantity(),
- SrcType);
+ uint64_t V;
+ if (LV.isNullPointer())
+ V = Info.Ctx.getTargetNullPointerValue(SrcType);
+ else
+ V = LV.getLValueOffset().getQuantity();
+
+ APSInt AsInt = Info.Ctx.MakeIntValue(V, SrcType);
return Success(HandleIntToIntCast(Info, E, DestType, SrcType, AsInt), E);
}
@@ -8528,8 +9091,10 @@ bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) {
case CK_CopyAndAutoreleaseBlockObject:
case CK_BuiltinFnToFnPtr:
case CK_ZeroToOCLEvent:
+ case CK_ZeroToOCLQueue:
case CK_NonAtomicToAtomic:
case CK_AddressSpaceConversion:
+ case CK_IntToOCLSampler:
llvm_unreachable("invalid cast kind for complex value");
case CK_LValueToRValue:
@@ -9341,6 +9906,8 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
case Expr::CompoundLiteralExprClass:
case Expr::ExtVectorElementExprClass:
case Expr::DesignatedInitExprClass:
+ case Expr::ArrayInitLoopExprClass:
+ case Expr::ArrayInitIndexExprClass:
case Expr::NoInitExprClass:
case Expr::DesignatedInitUpdateExprClass:
case Expr::ImplicitValueInitExprClass:
@@ -9877,5 +10444,5 @@ bool Expr::tryEvaluateObjectSize(uint64_t &Result, ASTContext &Ctx,
Expr::EvalStatus Status;
EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantFold);
- return ::tryEvaluateBuiltinObjectSize(this, Type, Info, Result);
+ return tryEvaluateBuiltinObjectSize(this, Type, Info, Result);
}
diff --git a/lib/AST/ExprObjC.cpp b/lib/AST/ExprObjC.cpp
index 0936a81a597a..31c1b3f15621 100644
--- a/lib/AST/ExprObjC.cpp
+++ b/lib/AST/ExprObjC.cpp
@@ -278,7 +278,7 @@ ObjCMessageExpr *ObjCMessageExpr::alloc(const ASTContext &C, unsigned NumArgs,
unsigned NumStoredSelLocs) {
return (ObjCMessageExpr *)C.Allocate(
totalSizeToAlloc<void *, SourceLocation>(NumArgs + 1, NumStoredSelLocs),
- llvm::AlignOf<ObjCMessageExpr>::Alignment);
+ alignof(ObjCMessageExpr));
}
void ObjCMessageExpr::getSelectorLocs(
diff --git a/lib/AST/ItaniumCXXABI.cpp b/lib/AST/ItaniumCXXABI.cpp
index 8a2cc0fbee42..692a455eafc0 100644
--- a/lib/AST/ItaniumCXXABI.cpp
+++ b/lib/AST/ItaniumCXXABI.cpp
@@ -63,9 +63,10 @@ public:
CallOperator->getType()->getAs<FunctionProtoType>();
ASTContext &Context = CallOperator->getASTContext();
+ FunctionProtoType::ExtProtoInfo EPI;
+ EPI.Variadic = Proto->isVariadic();
QualType Key =
- Context.getFunctionType(Context.VoidTy, Proto->getParamTypes(),
- FunctionProtoType::ExtProtoInfo());
+ Context.getFunctionType(Context.VoidTy, Proto->getParamTypes(), EPI);
Key = Context.getCanonicalType(Key);
return ++ManglingNumbers[Key->castAs<FunctionProtoType>()];
}
@@ -141,14 +142,6 @@ public:
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;
- }
-
void addTypedefNameForUnnamedTagDecl(TagDecl *TD,
TypedefNameDecl *DD) override {}
@@ -163,8 +156,9 @@ public:
return nullptr;
}
- MangleNumberingContext *createMangleNumberingContext() const override {
- return new ItaniumNumberingContext();
+ std::unique_ptr<MangleNumberingContext>
+ createMangleNumberingContext() const override {
+ return llvm::make_unique<ItaniumNumberingContext>();
}
};
}
diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp
index 694fde317542..ab3e49d903cf 100644
--- a/lib/AST/ItaniumMangle.cpp
+++ b/lib/AST/ItaniumMangle.cpp
@@ -405,12 +405,14 @@ public:
CXXNameMangler(CXXNameMangler &Outer, raw_ostream &Out_)
: Context(Outer.Context), Out(Out_), NullOut(false),
Structor(Outer.Structor), StructorType(Outer.StructorType),
- SeqID(Outer.SeqID), AbiTagsRoot(AbiTags) {}
+ SeqID(Outer.SeqID), FunctionTypeDepth(Outer.FunctionTypeDepth),
+ AbiTagsRoot(AbiTags), Substitutions(Outer.Substitutions) {}
CXXNameMangler(CXXNameMangler &Outer, llvm::raw_null_ostream &Out_)
: Context(Outer.Context), Out(Out_), NullOut(true),
Structor(Outer.Structor), StructorType(Outer.StructorType),
- SeqID(Outer.SeqID), AbiTagsRoot(AbiTags) {}
+ SeqID(Outer.SeqID), FunctionTypeDepth(Outer.FunctionTypeDepth),
+ AbiTagsRoot(AbiTags), Substitutions(Outer.Substitutions) {}
#if MANGLE_CHECKER
~CXXNameMangler() {
@@ -458,11 +460,15 @@ private:
void addSubstitution(QualType T);
void addSubstitution(TemplateName Template);
void addSubstitution(uintptr_t Ptr);
+ // Destructive copy substitutions from other mangler.
+ void extendSubstitutions(CXXNameMangler* Other);
void mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,
bool recursive = false);
void mangleUnresolvedName(NestedNameSpecifier *qualifier,
DeclarationName name,
+ const TemplateArgumentLoc *TemplateArgs,
+ unsigned NumTemplateArgs,
unsigned KnownArity = UnknownArity);
void mangleFunctionEncodingBareType(const FunctionDecl *FD);
@@ -487,6 +493,7 @@ private:
void mangleUnscopedTemplateName(TemplateName,
const AbiTagList *AdditionalAbiTags);
void mangleSourceName(const IdentifierInfo *II);
+ void mangleRegCallName(const IdentifierInfo *II);
void mangleSourceNameWithAbiTags(
const NamedDecl *ND, const AbiTagList *AdditionalAbiTags = nullptr);
void mangleLocalName(const Decl *D,
@@ -537,6 +544,8 @@ private:
NestedNameSpecifier *qualifier,
NamedDecl *firstQualifierLookup,
DeclarationName name,
+ const TemplateArgumentLoc *TemplateArgs,
+ unsigned NumTemplateArgs,
unsigned knownArity);
void mangleCastExpression(const Expr *E, StringRef CastEncoding);
void mangleInitListElements(const InitListExpr *InitList);
@@ -593,7 +602,7 @@ bool ItaniumMangleContextImpl::shouldMangleCXXName(const NamedDecl *D) {
return false;
const VarDecl *VD = dyn_cast<VarDecl>(D);
- if (VD) {
+ if (VD && !isa<DecompositionDecl>(D)) {
// C variables are not mangled.
if (VD->isExternC())
return false;
@@ -685,6 +694,10 @@ void CXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) {
// Output name with implicit tags and function encoding from temporary buffer.
mangleNameWithAbiTags(FD, &AdditionalAbiTags);
Out << FunctionEncodingStream.str().substr(EncodingPositionStart);
+
+ // Function encoding could create new substitutions so we have to add
+ // temp mangled substitutions to main mangler.
+ extendSubstitutions(&FunctionEncodingMangler);
}
void CXXNameMangler::mangleFunctionEncodingBareType(const FunctionDecl *FD) {
@@ -1151,9 +1164,10 @@ 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,
- DeclarationName name,
- unsigned knownArity) {
+void CXXNameMangler::mangleUnresolvedName(
+ NestedNameSpecifier *qualifier, DeclarationName name,
+ const TemplateArgumentLoc *TemplateArgs, unsigned NumTemplateArgs,
+ unsigned knownArity) {
if (qualifier) mangleUnresolvedPrefix(qualifier);
switch (name.getNameKind()) {
// <base-unresolved-name> ::= <simple-id>
@@ -1181,6 +1195,11 @@ void CXXNameMangler::mangleUnresolvedName(NestedNameSpecifier *qualifier,
case DeclarationName::ObjCZeroArgSelector:
llvm_unreachable("Can't mangle Objective-C selector names here!");
}
+
+ // The <simple-id> and on <operator-name> productions end in an optional
+ // <template-args>.
+ if (TemplateArgs)
+ mangleTemplateArgs(TemplateArgs, NumTemplateArgs);
}
void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
@@ -1193,7 +1212,26 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
// ::= <source-name>
switch (Name.getNameKind()) {
case DeclarationName::Identifier: {
- if (const IdentifierInfo *II = Name.getAsIdentifierInfo()) {
+ const IdentifierInfo *II = Name.getAsIdentifierInfo();
+
+ // We mangle decomposition declarations as the names of their bindings.
+ if (auto *DD = dyn_cast<DecompositionDecl>(ND)) {
+ // FIXME: Non-standard mangling for decomposition declarations:
+ //
+ // <unqualified-name> ::= DC <source-name>* E
+ //
+ // These can never be referenced across translation units, so we do
+ // not need a cross-vendor mangling for anything other than demanglers.
+ // Proposed on cxx-abi-dev on 2016-08-12
+ Out << "DC";
+ for (auto *BD : DD->bindings())
+ mangleSourceName(BD->getDeclName().getAsIdentifierInfo());
+ Out << 'E';
+ writeAbiTags(ND, AdditionalAbiTags);
+ break;
+ }
+
+ if (II) {
// We must avoid conflicts between internally- and externally-
// linked variable and function declaration names in the same TU:
// void test() { extern void foo(); }
@@ -1204,7 +1242,15 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
getEffectiveDeclContext(ND)->isFileContext())
Out << 'L';
- mangleSourceName(II);
+ auto *FD = dyn_cast<FunctionDecl>(ND);
+ bool IsRegCall = FD &&
+ FD->getType()->castAs<FunctionType>()->getCallConv() ==
+ clang::CC_X86RegCall;
+ if (IsRegCall)
+ mangleRegCallName(II);
+ else
+ mangleSourceName(II);
+
writeAbiTags(ND, AdditionalAbiTags);
break;
}
@@ -1378,6 +1424,14 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
}
}
+void CXXNameMangler::mangleRegCallName(const IdentifierInfo *II) {
+ // <source-name> ::= <positive length number> __regcall3__ <identifier>
+ // <number> ::= [n] <non-negative decimal integer>
+ // <identifier> ::= <unqualified source code identifier>
+ Out << II->getLength() + sizeof("__regcall3__") - 1 << "__regcall3__"
+ << II->getName();
+}
+
void CXXNameMangler::mangleSourceName(const IdentifierInfo *II) {
// <source-name> ::= <positive length number> <identifier>
// <number> ::= [n] <non-negative decimal integer>
@@ -1471,7 +1525,7 @@ void CXXNameMangler::mangleLocalName(const Decl *D,
// numbering will be local to the particular argument in which it appears
// -- other default arguments do not affect its encoding.
const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD);
- if (CXXRD->isLambda()) {
+ if (CXXRD && CXXRD->isLambda()) {
if (const ParmVarDecl *Parm
= dyn_cast_or_null<ParmVarDecl>(CXXRD->getLambdaContextDecl())) {
if (const FunctionDecl *Func
@@ -1820,6 +1874,7 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty,
case Type::ObjCObject:
case Type::ObjCInterface:
case Type::ObjCObjectPointer:
+ case Type::ObjCTypeParam:
case Type::Atomic:
case Type::Pipe:
llvm_unreachable("type is illegal as a nested name specifier");
@@ -2207,6 +2262,22 @@ void CXXNameMangler::mangleType(QualType T) {
// they aren't written.
// - Conversions on non-type template arguments need to be expressed, since
// they can affect the mangling of sizeof/alignof.
+ //
+ // FIXME: This is wrong when mapping to the canonical type for a dependent
+ // type discards instantiation-dependent portions of the type, such as for:
+ //
+ // template<typename T, int N> void f(T (&)[sizeof(N)]);
+ // template<typename T> void f(T() throw(typename T::type)); (pre-C++17)
+ //
+ // It's also wrong in the opposite direction when instantiation-dependent,
+ // canonically-equivalent types differ in some irrelevant portion of inner
+ // type sugar. In such cases, we fail to form correct substitutions, eg:
+ //
+ // template<int N> void f(A<sizeof(N)> *, A<sizeof(N)> (*));
+ //
+ // We should instead canonicalize the non-instantiation-dependent parts,
+ // regardless of whether the type as a whole is dependent or instantiation
+ // dependent.
if (!T->isInstantiationDependentType() || T->isDependentType())
T = T.getCanonicalType();
else {
@@ -2443,6 +2514,7 @@ StringRef CXXNameMangler::getCallingConvQualifierName(CallingConv CC) {
case CC_X86Pascal:
case CC_X86_64Win64:
case CC_X86_64SysV:
+ case CC_X86RegCall:
case CC_AAPCS:
case CC_AAPCS_VFP:
case CC_IntelOclBicc:
@@ -2509,6 +2581,24 @@ void CXXNameMangler::mangleType(const FunctionProtoType *T) {
// e.g. "const" in "int (A::*)() const".
mangleQualifiers(Qualifiers::fromCVRMask(T->getTypeQuals()));
+ // Mangle instantiation-dependent exception-specification, if present,
+ // per cxx-abi-dev proposal on 2016-10-11.
+ if (T->hasInstantiationDependentExceptionSpec()) {
+ if (T->getExceptionSpecType() == EST_ComputedNoexcept) {
+ Out << "DO";
+ mangleExpression(T->getNoexceptExpr());
+ Out << "E";
+ } else {
+ assert(T->getExceptionSpecType() == EST_Dynamic);
+ Out << "Dw";
+ for (auto ExceptTy : T->exceptions())
+ mangleType(ExceptTy);
+ Out << "E";
+ }
+ } else if (T->isNothrow(getASTContext())) {
+ Out << "Do";
+ }
+
Out << 'F';
// FIXME: We don't have enough information in the AST to produce the 'Y'
@@ -3115,12 +3205,14 @@ void CXXNameMangler::mangleMemberExpr(const Expr *base,
NestedNameSpecifier *qualifier,
NamedDecl *firstQualifierLookup,
DeclarationName member,
+ const TemplateArgumentLoc *TemplateArgs,
+ unsigned NumTemplateArgs,
unsigned arity) {
// <expression> ::= dt <expression> <unresolved-name>
// ::= pt <expression> <unresolved-name>
if (base)
mangleMemberExprBase(base, isArrow);
- mangleUnresolvedName(qualifier, member, arity);
+ mangleUnresolvedName(qualifier, member, TemplateArgs, NumTemplateArgs, arity);
}
/// Look at the callee of the given call expression and determine if
@@ -3209,6 +3301,8 @@ recurse:
case Expr::AddrLabelExprClass:
case Expr::DesignatedInitUpdateExprClass:
case Expr::ImplicitValueInitExprClass:
+ case Expr::ArrayInitLoopExprClass:
+ case Expr::ArrayInitIndexExprClass:
case Expr::NoInitExprClass:
case Expr::ParenListExprClass:
case Expr::LambdaExprClass:
@@ -3418,7 +3512,9 @@ recurse:
const MemberExpr *ME = cast<MemberExpr>(E);
mangleMemberExpr(ME->getBase(), ME->isArrow(),
ME->getQualifier(), nullptr,
- ME->getMemberDecl()->getDeclName(), Arity);
+ ME->getMemberDecl()->getDeclName(),
+ ME->getTemplateArgs(), ME->getNumTemplateArgs(),
+ Arity);
break;
}
@@ -3426,9 +3522,9 @@ recurse:
const UnresolvedMemberExpr *ME = cast<UnresolvedMemberExpr>(E);
mangleMemberExpr(ME->isImplicitAccess() ? nullptr : ME->getBase(),
ME->isArrow(), ME->getQualifier(), nullptr,
- ME->getMemberName(), Arity);
- if (ME->hasExplicitTemplateArgs())
- mangleTemplateArgs(ME->getTemplateArgs(), ME->getNumTemplateArgs());
+ ME->getMemberName(),
+ ME->getTemplateArgs(), ME->getNumTemplateArgs(),
+ Arity);
break;
}
@@ -3438,21 +3534,17 @@ recurse:
mangleMemberExpr(ME->isImplicitAccess() ? nullptr : ME->getBase(),
ME->isArrow(), ME->getQualifier(),
ME->getFirstQualifierFoundInScope(),
- ME->getMember(), Arity);
- if (ME->hasExplicitTemplateArgs())
- mangleTemplateArgs(ME->getTemplateArgs(), ME->getNumTemplateArgs());
+ ME->getMember(),
+ ME->getTemplateArgs(), ME->getNumTemplateArgs(),
+ Arity);
break;
}
case Expr::UnresolvedLookupExprClass: {
const UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(E);
- mangleUnresolvedName(ULE->getQualifier(), ULE->getName(), Arity);
-
- // All the <unresolved-name> productions end in a
- // base-unresolved-name, where <template-args> are just tacked
- // onto the end.
- if (ULE->hasExplicitTemplateArgs())
- mangleTemplateArgs(ULE->getTemplateArgs(), ULE->getNumTemplateArgs());
+ mangleUnresolvedName(ULE->getQualifier(), ULE->getName(),
+ ULE->getTemplateArgs(), ULE->getNumTemplateArgs(),
+ Arity);
break;
}
@@ -3707,7 +3799,10 @@ recurse:
case Expr::CXXOperatorCallExprClass: {
const CXXOperatorCallExpr *CE = cast<CXXOperatorCallExpr>(E);
unsigned NumArgs = CE->getNumArgs();
- mangleOperatorName(CE->getOperator(), /*Arity=*/NumArgs);
+ // A CXXOperatorCallExpr for OO_Arrow models only semantics, not syntax
+ // (the enclosing MemberExpr covers the syntactic portion).
+ if (CE->getOperator() != OO_Arrow)
+ mangleOperatorName(CE->getOperator(), /*Arity=*/NumArgs);
// Mangle the arguments.
for (unsigned i = 0; i != NumArgs; ++i)
mangleExpression(CE->getArg(i));
@@ -3768,13 +3863,9 @@ recurse:
case Expr::DependentScopeDeclRefExprClass: {
const DependentScopeDeclRefExpr *DRE = cast<DependentScopeDeclRefExpr>(E);
- mangleUnresolvedName(DRE->getQualifier(), DRE->getDeclName(), Arity);
-
- // All the <unresolved-name> productions end in a
- // base-unresolved-name, where <template-args> are just tacked
- // onto the end.
- if (DRE->hasExplicitTemplateArgs())
- mangleTemplateArgs(DRE->getTemplateArgs(), DRE->getNumTemplateArgs());
+ mangleUnresolvedName(DRE->getQualifier(), DRE->getDeclName(),
+ DRE->getTemplateArgs(), DRE->getNumTemplateArgs(),
+ Arity);
break;
}
@@ -4406,6 +4497,14 @@ void CXXNameMangler::addSubstitution(uintptr_t Ptr) {
Substitutions[Ptr] = SeqID++;
}
+void CXXNameMangler::extendSubstitutions(CXXNameMangler* Other) {
+ assert(Other->SeqID >= SeqID && "Must be superset of substitutions!");
+ if (Other->SeqID > SeqID) {
+ Substitutions.swap(Other->Substitutions);
+ SeqID = Other->SeqID;
+ }
+}
+
CXXNameMangler::AbiTagList
CXXNameMangler::makeFunctionReturnTypeTags(const FunctionDecl *FD) {
// When derived abi tags are disabled there is no need to make any list.
diff --git a/lib/AST/Mangle.cpp b/lib/AST/Mangle.cpp
index ee241732e8ad..05dd886adcef 100644
--- a/lib/AST/Mangle.cpp
+++ b/lib/AST/Mangle.cpp
@@ -52,6 +52,7 @@ void MangleContext::anchor() { }
enum CCMangling {
CCM_Other,
CCM_Fast,
+ CCM_RegCall,
CCM_Vector,
CCM_Std
};
@@ -152,6 +153,8 @@ void MangleContext::mangleName(const NamedDecl *D, raw_ostream &Out) {
Out << '_';
else if (CC == CCM_Fast)
Out << '@';
+ else if (CC == CCM_RegCall)
+ Out << "__regcall3__";
if (!MCXX)
Out << D->getIdentifier()->getName();
diff --git a/lib/AST/MicrosoftCXXABI.cpp b/lib/AST/MicrosoftCXXABI.cpp
index 3ae04538d626..73324e40f3b1 100644
--- a/lib/AST/MicrosoftCXXABI.cpp
+++ b/lib/AST/MicrosoftCXXABI.cpp
@@ -67,8 +67,6 @@ public:
class MicrosoftCXXABI : public CXXABI {
ASTContext &Context;
llvm::SmallDenseMap<CXXRecordDecl *, CXXConstructorDecl *> RecordToCopyCtor;
- llvm::SmallDenseMap<std::pair<const CXXConstructorDecl *, unsigned>, Expr *>
- CtorToDefaultArgExpr;
llvm::SmallDenseMap<TagDecl *, DeclaratorDecl *>
UnnamedTagDeclToDeclaratorDecl;
@@ -92,16 +90,6 @@ public:
llvm_unreachable("unapplicable to the MS ABI");
}
- 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];
@@ -143,8 +131,9 @@ public:
const_cast<TagDecl *>(TD->getCanonicalDecl()));
}
- MangleNumberingContext *createMangleNumberingContext() const override {
- return new MicrosoftNumberingContext();
+ std::unique_ptr<MangleNumberingContext>
+ createMangleNumberingContext() const override {
+ return llvm::make_unique<MicrosoftNumberingContext>();
}
};
}
diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp
index 351997e02a9d..911b8b471a05 100644
--- a/lib/AST/MicrosoftMangle.cpp
+++ b/lib/AST/MicrosoftMangle.cpp
@@ -66,6 +66,16 @@ struct msvc_hashing_ostream : public llvm::raw_svector_ostream {
}
};
+static const DeclContext *
+getLambdaDefaultArgumentDeclContext(const Decl *D) {
+ if (const auto *RD = dyn_cast<CXXRecordDecl>(D))
+ if (RD->isLambda())
+ if (const auto *Parm =
+ dyn_cast_or_null<ParmVarDecl>(RD->getLambdaContextDecl()))
+ return Parm->getDeclContext();
+ return nullptr;
+}
+
/// \brief Retrieve the declaration context that should be used when mangling
/// the given declaration.
static const DeclContext *getEffectiveDeclContext(const Decl *D) {
@@ -75,12 +85,8 @@ static const DeclContext *getEffectiveDeclContext(const Decl *D) {
// not the case: the lambda closure type ends up living in the context
// where the function itself resides, because the function declaration itself
// had not yet been created. Fix the context here.
- if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
- if (RD->isLambda())
- if (ParmVarDecl *ContextParam =
- dyn_cast_or_null<ParmVarDecl>(RD->getLambdaContextDecl()))
- return ContextParam->getDeclContext();
- }
+ if (const auto *LDADC = getLambdaDefaultArgumentDeclContext(D))
+ return LDADC;
// Perform the same check for block literals.
if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) {
@@ -112,14 +118,6 @@ static const FunctionDecl *getStructor(const NamedDecl *ND) {
return FD;
}
-static bool isLambda(const NamedDecl *ND) {
- const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(ND);
- if (!Record)
- return false;
-
- return Record->isLambda();
-}
-
/// MicrosoftMangleContextImpl - Overrides the default MangleContext for the
/// Microsoft Visual C++ ABI.
class MicrosoftMangleContextImpl : public MicrosoftMangleContext {
@@ -200,9 +198,11 @@ public:
// Lambda closure types are already numbered, give out a phony number so
// that they demangle nicely.
- if (isLambda(ND)) {
- disc = 1;
- return true;
+ if (const auto *RD = dyn_cast<CXXRecordDecl>(ND)) {
+ if (RD->isLambda()) {
+ disc = 1;
+ return true;
+ }
}
// Use the canonical number for externally visible decls.
@@ -394,7 +394,8 @@ bool MicrosoftMangleContextImpl::shouldMangleCXXName(const NamedDecl *D) {
if (!getASTContext().getLangOpts().CPlusPlus)
return false;
- if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ const VarDecl *VD = dyn_cast<VarDecl>(D);
+ if (VD && !isa<DecompositionDecl>(D)) {
// C variables are not mangled.
if (VD->isExternC())
return false;
@@ -780,6 +781,21 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
}
}
+ if (const DecompositionDecl *DD = dyn_cast<DecompositionDecl>(ND)) {
+ // FIXME: Invented mangling for decomposition declarations:
+ // [X,Y,Z]
+ // where X,Y,Z are the names of the bindings.
+ llvm::SmallString<128> Name("[");
+ for (auto *BD : DD->bindings()) {
+ if (Name.size() > 1)
+ Name += ',';
+ Name += BD->getDeclName().getAsIdentifierInfo()->getName();
+ }
+ Name += ']';
+ mangleSourceName(Name);
+ break;
+ }
+
if (const VarDecl *VD = dyn_cast<VarDecl>(ND)) {
// We must have an anonymous union or struct declaration.
const CXXRecordDecl *RD = VD->getType()->getAsCXXRecordDecl();
@@ -808,9 +824,24 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(TD)) {
if (Record->isLambda()) {
llvm::SmallString<10> Name("<lambda_");
+
+ Decl *LambdaContextDecl = Record->getLambdaContextDecl();
+ unsigned LambdaManglingNumber = Record->getLambdaManglingNumber();
unsigned LambdaId;
- if (Record->getLambdaManglingNumber())
- LambdaId = Record->getLambdaManglingNumber();
+ const ParmVarDecl *Parm =
+ dyn_cast_or_null<ParmVarDecl>(LambdaContextDecl);
+ const FunctionDecl *Func =
+ Parm ? dyn_cast<FunctionDecl>(Parm->getDeclContext()) : nullptr;
+
+ if (Func) {
+ unsigned DefaultArgNo =
+ Func->getNumParams() - Parm->getFunctionScopeIndex();
+ Name += llvm::utostr(DefaultArgNo);
+ Name += "_";
+ }
+
+ if (LambdaManglingNumber)
+ LambdaId = LambdaManglingNumber;
else
LambdaId = Context.getLambdaId(Record);
@@ -818,25 +849,42 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
Name += ">";
mangleSourceName(Name);
+
+ // If the context of a closure type is an initializer for a class
+ // member (static or nonstatic), it is encoded in a qualified name.
+ if (LambdaManglingNumber && LambdaContextDecl) {
+ if ((isa<VarDecl>(LambdaContextDecl) ||
+ isa<FieldDecl>(LambdaContextDecl)) &&
+ LambdaContextDecl->getDeclContext()->isRecord()) {
+ mangleUnqualifiedName(cast<NamedDecl>(LambdaContextDecl));
+ }
+ }
break;
}
}
- llvm::SmallString<64> Name("<unnamed-type-");
+ llvm::SmallString<64> Name;
if (DeclaratorDecl *DD =
Context.getASTContext().getDeclaratorForUnnamedTagDecl(TD)) {
// Anonymous types without a name for linkage purposes have their
// declarator mangled in if they have one.
+ Name += "<unnamed-type-";
Name += DD->getName();
} else if (TypedefNameDecl *TND =
Context.getASTContext().getTypedefNameForUnnamedTagDecl(
TD)) {
// Anonymous types without a name for linkage purposes have their
// associate typedef mangled in if they have one.
+ Name += "<unnamed-type-";
Name += TND->getName();
+ } else if (auto *ED = dyn_cast<EnumDecl>(TD)) {
+ auto EnumeratorI = ED->enumerator_begin();
+ assert(EnumeratorI != ED->enumerator_end());
+ Name += "<unnamed-enum-";
+ Name += EnumeratorI->getName();
} else {
// Otherwise, number the types using a $S prefix.
- Name += "$S";
+ Name += "<unnamed-type-$S";
Name += llvm::utostr(Context.getAnonymousStructId(TD) + 1);
}
Name += ">";
@@ -921,7 +969,6 @@ void MicrosoftCXXNameMangler::mangleNestedName(const NamedDecl *ND) {
// for how this should be done.
Out << "__block_invoke" << Context.getBlockId(BD, false);
Out << '@';
- continue;
} else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(DC)) {
mangleObjCMethodName(Method);
} else if (isa<NamedDecl>(DC)) {
@@ -929,8 +976,15 @@ void MicrosoftCXXNameMangler::mangleNestedName(const NamedDecl *ND) {
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
mangle(FD, "?");
break;
- } else
+ } else {
mangleUnqualifiedName(ND);
+ // Lambdas in default arguments conceptually belong to the function the
+ // parameter corresponds to.
+ if (const auto *LDADC = getLambdaDefaultArgumentDeclContext(ND)) {
+ DC = LDADC;
+ continue;
+ }
+ }
}
DC = DC->getParent();
}
@@ -1073,6 +1127,8 @@ void MicrosoftCXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO,
case OO_Array_New: Out << "?_U"; break;
// <operator-name> ::= ?_V # delete[]
case OO_Array_Delete: Out << "?_V"; break;
+ // <operator-name> ::= ?__L # co_await
+ case OO_Coawait: Out << "?__L"; break;
case OO_Conditional: {
DiagnosticsEngine &Diags = Context.getDiags();
@@ -1082,14 +1138,6 @@ void MicrosoftCXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO,
break;
}
- case OO_Coawait: {
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this operator co_await yet");
- Diags.Report(Loc, DiagID);
- break;
- }
-
case OO_None:
case NUM_OVERLOADED_OPERATORS:
llvm_unreachable("Not an overloaded operator");
@@ -1993,6 +2041,7 @@ void MicrosoftCXXNameMangler::mangleCallingConvention(CallingConv CC) {
// ::= I # __fastcall
// ::= J # __export __fastcall
// ::= Q # __vectorcall
+ // ::= w # __regcall
// The 'export' calling conventions are from a bygone era
// (*cough*Win16*cough*) when functions were declared for export with
// that keyword. (It didn't actually export them, it just made them so
@@ -2010,6 +2059,7 @@ void MicrosoftCXXNameMangler::mangleCallingConvention(CallingConv CC) {
case CC_X86StdCall: Out << 'G'; break;
case CC_X86FastCall: Out << 'I'; break;
case CC_X86VectorCall: Out << 'Q'; break;
+ case CC_X86RegCall: Out << 'w'; break;
}
}
void MicrosoftCXXNameMangler::mangleCallingConvention(const FunctionType *T) {
diff --git a/lib/AST/NestedNameSpecifier.cpp b/lib/AST/NestedNameSpecifier.cpp
index 82809d7ea7b5..514c7c9f5b33 100644
--- a/lib/AST/NestedNameSpecifier.cpp
+++ b/lib/AST/NestedNameSpecifier.cpp
@@ -34,8 +34,8 @@ NestedNameSpecifier::FindOrInsert(const ASTContext &Context,
NestedNameSpecifier *NNS
= Context.NestedNameSpecifiers.FindNodeOrInsertPos(ID, InsertPos);
if (!NNS) {
- NNS = new (Context, llvm::alignOf<NestedNameSpecifier>())
- NestedNameSpecifier(Mockup);
+ NNS =
+ new (Context, alignof(NestedNameSpecifier)) NestedNameSpecifier(Mockup);
Context.NestedNameSpecifiers.InsertNode(NNS, InsertPos);
}
@@ -113,8 +113,7 @@ NestedNameSpecifier *
NestedNameSpecifier::GlobalSpecifier(const ASTContext &Context) {
if (!Context.GlobalNestedNameSpecifier)
Context.GlobalNestedNameSpecifier =
- new (Context, llvm::alignOf<NestedNameSpecifier>())
- NestedNameSpecifier();
+ new (Context, alignof(NestedNameSpecifier)) NestedNameSpecifier();
return Context.GlobalNestedNameSpecifier;
}
@@ -155,7 +154,7 @@ NestedNameSpecifier::SpecifierKind NestedNameSpecifier::getKind() const {
/// \brief Retrieve the namespace stored in this nested name specifier.
NamespaceDecl *NestedNameSpecifier::getAsNamespace() const {
- if (Prefix.getInt() == StoredDecl)
+ if (Prefix.getInt() == StoredDecl)
return dyn_cast<NamespaceDecl>(static_cast<NamedDecl *>(Specifier));
return nullptr;
@@ -163,7 +162,7 @@ NamespaceDecl *NestedNameSpecifier::getAsNamespace() const {
/// \brief Retrieve the namespace alias stored in this nested name specifier.
NamespaceAliasDecl *NestedNameSpecifier::getAsNamespaceAlias() const {
- if (Prefix.getInt() == StoredDecl)
+ if (Prefix.getInt() == StoredDecl)
return dyn_cast<NamespaceAliasDecl>(static_cast<NamedDecl *>(Specifier));
return nullptr;
@@ -687,7 +686,7 @@ NestedNameSpecifierLocBuilder::getWithLocInContext(ASTContext &Context) const {
// FIXME: After copying the source-location information, should we free
// our (temporary) buffer and adopt the ASTContext-allocated memory?
// Doing so would optimize repeated calls to getWithLocInContext().
- void *Mem = Context.Allocate(BufferSize, llvm::alignOf<void *>());
+ void *Mem = Context.Allocate(BufferSize, alignof(void *));
memcpy(Mem, Buffer, BufferSize);
return NestedNameSpecifierLoc(Representation, Mem);
}
diff --git a/lib/AST/OpenMPClause.cpp b/lib/AST/OpenMPClause.cpp
index d04ba727bb05..a28b9f3b6d64 100644
--- a/lib/AST/OpenMPClause.cpp
+++ b/lib/AST/OpenMPClause.cpp
@@ -732,38 +732,113 @@ OMPFromClause *OMPFromClause::CreateEmpty(const ASTContext &C, unsigned NumVars,
NumComponentLists, NumComponents);
}
-OMPUseDevicePtrClause *OMPUseDevicePtrClause::Create(const ASTContext &C,
- SourceLocation StartLoc,
- SourceLocation LParenLoc,
- SourceLocation EndLoc,
- ArrayRef<Expr *> VL) {
- void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(VL.size()));
- OMPUseDevicePtrClause *Clause =
- new (Mem) OMPUseDevicePtrClause(StartLoc, LParenLoc, EndLoc, VL.size());
- Clause->setVarRefs(VL);
+void OMPUseDevicePtrClause::setPrivateCopies(ArrayRef<Expr *> VL) {
+ assert(VL.size() == varlist_size() &&
+ "Number of private copies is not the same as the preallocated buffer");
+ std::copy(VL.begin(), VL.end(), varlist_end());
+}
+
+void OMPUseDevicePtrClause::setInits(ArrayRef<Expr *> VL) {
+ assert(VL.size() == varlist_size() &&
+ "Number of inits is not the same as the preallocated buffer");
+ std::copy(VL.begin(), VL.end(), getPrivateCopies().end());
+}
+
+OMPUseDevicePtrClause *OMPUseDevicePtrClause::Create(
+ const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc, ArrayRef<Expr *> Vars, ArrayRef<Expr *> PrivateVars,
+ ArrayRef<Expr *> Inits, ArrayRef<ValueDecl *> Declarations,
+ MappableExprComponentListsRef ComponentLists) {
+ unsigned NumVars = Vars.size();
+ unsigned NumUniqueDeclarations =
+ getUniqueDeclarationsTotalNumber(Declarations);
+ unsigned NumComponentLists = ComponentLists.size();
+ unsigned NumComponents = getComponentsTotalNumber(ComponentLists);
+
+ // We need to allocate:
+ // 3 x NumVars x Expr* - we have an original list expression for each clause
+ // list entry and an equal number of private copies and inits.
+ // NumUniqueDeclarations x ValueDecl* - unique base declarations associated
+ // with each component list.
+ // (NumUniqueDeclarations + NumComponentLists) x unsigned - we specify the
+ // number of lists for each unique declaration and the size of each component
+ // list.
+ // NumComponents x MappableComponent - the total of all the components in all
+ // the lists.
+ void *Mem = C.Allocate(
+ totalSizeToAlloc<Expr *, ValueDecl *, unsigned,
+ OMPClauseMappableExprCommon::MappableComponent>(
+ 3 * NumVars, NumUniqueDeclarations,
+ NumUniqueDeclarations + NumComponentLists, NumComponents));
+
+ OMPUseDevicePtrClause *Clause = new (Mem) OMPUseDevicePtrClause(
+ StartLoc, LParenLoc, EndLoc, NumVars, NumUniqueDeclarations,
+ NumComponentLists, NumComponents);
+
+ Clause->setVarRefs(Vars);
+ Clause->setPrivateCopies(PrivateVars);
+ Clause->setInits(Inits);
+ Clause->setClauseInfo(Declarations, ComponentLists);
return Clause;
}
-OMPUseDevicePtrClause *OMPUseDevicePtrClause::CreateEmpty(const ASTContext &C,
- unsigned N) {
- void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(N));
- return new (Mem) OMPUseDevicePtrClause(N);
+OMPUseDevicePtrClause *OMPUseDevicePtrClause::CreateEmpty(
+ const ASTContext &C, unsigned NumVars, unsigned NumUniqueDeclarations,
+ unsigned NumComponentLists, unsigned NumComponents) {
+ void *Mem = C.Allocate(
+ totalSizeToAlloc<Expr *, ValueDecl *, unsigned,
+ OMPClauseMappableExprCommon::MappableComponent>(
+ 3 * NumVars, NumUniqueDeclarations,
+ NumUniqueDeclarations + NumComponentLists, NumComponents));
+ return new (Mem) OMPUseDevicePtrClause(NumVars, NumUniqueDeclarations,
+ NumComponentLists, NumComponents);
}
-OMPIsDevicePtrClause *OMPIsDevicePtrClause::Create(const ASTContext &C,
- SourceLocation StartLoc,
- SourceLocation LParenLoc,
- SourceLocation EndLoc,
- ArrayRef<Expr *> VL) {
- void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(VL.size()));
- OMPIsDevicePtrClause *Clause =
- new (Mem) OMPIsDevicePtrClause(StartLoc, LParenLoc, EndLoc, VL.size());
- Clause->setVarRefs(VL);
+OMPIsDevicePtrClause *
+OMPIsDevicePtrClause::Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation EndLoc,
+ ArrayRef<Expr *> Vars,
+ ArrayRef<ValueDecl *> Declarations,
+ MappableExprComponentListsRef ComponentLists) {
+ unsigned NumVars = Vars.size();
+ unsigned NumUniqueDeclarations =
+ getUniqueDeclarationsTotalNumber(Declarations);
+ unsigned NumComponentLists = ComponentLists.size();
+ unsigned NumComponents = getComponentsTotalNumber(ComponentLists);
+
+ // We need to allocate:
+ // NumVars x Expr* - we have an original list expression for each clause list
+ // entry.
+ // NumUniqueDeclarations x ValueDecl* - unique base declarations associated
+ // with each component list.
+ // (NumUniqueDeclarations + NumComponentLists) x unsigned - we specify the
+ // number of lists for each unique declaration and the size of each component
+ // list.
+ // NumComponents x MappableComponent - the total of all the components in all
+ // the lists.
+ void *Mem = C.Allocate(
+ totalSizeToAlloc<Expr *, ValueDecl *, unsigned,
+ OMPClauseMappableExprCommon::MappableComponent>(
+ NumVars, NumUniqueDeclarations,
+ NumUniqueDeclarations + NumComponentLists, NumComponents));
+
+ OMPIsDevicePtrClause *Clause = new (Mem) OMPIsDevicePtrClause(
+ StartLoc, LParenLoc, EndLoc, NumVars, NumUniqueDeclarations,
+ NumComponentLists, NumComponents);
+
+ Clause->setVarRefs(Vars);
+ Clause->setClauseInfo(Declarations, ComponentLists);
return Clause;
}
-OMPIsDevicePtrClause *OMPIsDevicePtrClause::CreateEmpty(const ASTContext &C,
- unsigned N) {
- void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(N));
- return new (Mem) OMPIsDevicePtrClause(N);
+OMPIsDevicePtrClause *OMPIsDevicePtrClause::CreateEmpty(
+ const ASTContext &C, unsigned NumVars, unsigned NumUniqueDeclarations,
+ unsigned NumComponentLists, unsigned NumComponents) {
+ void *Mem = C.Allocate(
+ totalSizeToAlloc<Expr *, ValueDecl *, unsigned,
+ OMPClauseMappableExprCommon::MappableComponent>(
+ NumVars, NumUniqueDeclarations,
+ NumUniqueDeclarations + NumComponentLists, NumComponents));
+ return new (Mem) OMPIsDevicePtrClause(NumVars, NumUniqueDeclarations,
+ NumComponentLists, NumComponents);
}
diff --git a/lib/AST/RawCommentList.cpp b/lib/AST/RawCommentList.cpp
index 8317f76b8569..881a7d9c61be 100644
--- a/lib/AST/RawCommentList.cpp
+++ b/lib/AST/RawCommentList.cpp
@@ -175,8 +175,8 @@ StringRef RawComment::getRawTextSlow(const SourceManager &SourceMgr) const {
}
const char *RawComment::extractBriefText(const ASTContext &Context) const {
- // Make sure that RawText is valid.
- getRawText(Context.getSourceManager());
+ // Lazily initialize RawText using the accessor before using it.
+ (void)getRawText(Context.getSourceManager());
// Since we will be copying the resulting text, all allocations made during
// parsing are garbage after resulting string is formed. Thus we can use
@@ -202,8 +202,8 @@ const char *RawComment::extractBriefText(const ASTContext &Context) const {
comments::FullComment *RawComment::parse(const ASTContext &Context,
const Preprocessor *PP,
const Decl *D) const {
- // Make sure that RawText is valid.
- getRawText(Context.getSourceManager());
+ // Lazily initialize RawText using the accessor before using it.
+ (void)getRawText(Context.getSourceManager());
comments::Lexer L(Context.getAllocator(), Context.getDiagnostics(),
Context.getCommentCommandTraits(),
@@ -334,4 +334,3 @@ void RawCommentList::addDeserializedComments(ArrayRef<RawComment *> Deserialized
BeforeThanCompare<RawComment>(SourceMgr));
std::swap(Comments, MergedComments);
}
-
diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp
index 75c076399511..697cdc3fb360 100644
--- a/lib/AST/Stmt.cpp
+++ b/lib/AST/Stmt.cpp
@@ -315,7 +315,7 @@ AttributedStmt *AttributedStmt::Create(const ASTContext &C, SourceLocation Loc,
Stmt *SubStmt) {
assert(!Attrs.empty() && "Attrs should not be empty");
void *Mem = C.Allocate(sizeof(AttributedStmt) + sizeof(Attr *) * Attrs.size(),
- llvm::alignOf<AttributedStmt>());
+ alignof(AttributedStmt));
return new (Mem) AttributedStmt(Loc, Attrs, SubStmt);
}
@@ -323,7 +323,7 @@ AttributedStmt *AttributedStmt::CreateEmpty(const ASTContext &C,
unsigned NumAttrs) {
assert(NumAttrs > 0 && "NumAttrs should be greater than zero");
void *Mem = C.Allocate(sizeof(AttributedStmt) + sizeof(Attr *) * NumAttrs,
- llvm::alignOf<AttributedStmt>());
+ alignof(AttributedStmt));
return new (Mem) AttributedStmt(EmptyShell(), NumAttrs);
}
@@ -533,15 +533,17 @@ unsigned GCCAsmStmt::AnalyzeAsmString(SmallVectorImpl<AsmStringPiece>&Pieces,
DiagOffs = CurPtr-StrStart-1;
return diag::err_asm_invalid_escape;
}
-
+ // Handle escaped char and continue looping over the asm string.
char EscapedChar = *CurPtr++;
- if (EscapedChar == '%') { // %% -> %
- // Escaped percentage sign.
- CurStringPiece += '%';
+ switch (EscapedChar) {
+ default:
+ break;
+ case '%': // %% -> %
+ case '{': // %{ -> {
+ case '}': // %} -> }
+ CurStringPiece += EscapedChar;
continue;
- }
-
- if (EscapedChar == '=') { // %= -> Generate an unique ID.
+ case '=': // %= -> Generate a unique ID.
CurStringPiece += "${:uid}";
continue;
}
@@ -794,6 +796,10 @@ void IfStmt::setConditionVariable(const ASTContext &C, VarDecl *V) {
VarRange.getEnd());
}
+bool IfStmt::isObjCAvailabilityCheck() const {
+ return isa<ObjCAvailabilityCheckExpr>(SubExprs[COND]);
+}
+
ForStmt::ForStmt(const ASTContext &C, Stmt *Init, Expr *Cond, VarDecl *condVar,
Expr *Inc, Stmt *Body, SourceLocation FL, SourceLocation LP,
SourceLocation RP)
@@ -998,7 +1004,7 @@ CapturedStmt::Capture *CapturedStmt::getStoredCaptures() const {
unsigned Size = sizeof(CapturedStmt) + sizeof(Stmt *) * (NumCaptures + 1);
// Offset of the first Capture object.
- unsigned FirstCaptureOffset = llvm::alignTo(Size, llvm::alignOf<Capture>());
+ unsigned FirstCaptureOffset = llvm::alignTo(Size, alignof(Capture));
return reinterpret_cast<Capture *>(
reinterpret_cast<char *>(const_cast<CapturedStmt *>(this))
@@ -1055,7 +1061,7 @@ CapturedStmt *CapturedStmt::Create(const ASTContext &Context, Stmt *S,
unsigned Size = sizeof(CapturedStmt) + sizeof(Stmt *) * (Captures.size() + 1);
if (!Captures.empty()) {
// Realign for the following Capture array.
- Size = llvm::alignTo(Size, llvm::alignOf<Capture>());
+ Size = llvm::alignTo(Size, alignof(Capture));
Size += sizeof(Capture) * Captures.size();
}
@@ -1068,7 +1074,7 @@ CapturedStmt *CapturedStmt::CreateDeserialized(const ASTContext &Context,
unsigned Size = sizeof(CapturedStmt) + sizeof(Stmt *) * (NumCaptures + 1);
if (NumCaptures > 0) {
// Realign for the following Capture array.
- Size = llvm::alignTo(Size, llvm::alignOf<Capture>());
+ Size = llvm::alignTo(Size, alignof(Capture));
Size += sizeof(Capture) * NumCaptures;
}
diff --git a/lib/AST/StmtCXX.cpp b/lib/AST/StmtCXX.cpp
index 4692db84b505..4a04fc211262 100644
--- a/lib/AST/StmtCXX.cpp
+++ b/lib/AST/StmtCXX.cpp
@@ -28,7 +28,7 @@ CXXTryStmt *CXXTryStmt::Create(const ASTContext &C, SourceLocation tryLoc,
std::size_t Size = sizeof(CXXTryStmt);
Size += ((handlers.size() + 1) * sizeof(Stmt *));
- void *Mem = C.Allocate(Size, llvm::alignOf<CXXTryStmt>());
+ void *Mem = C.Allocate(Size, alignof(CXXTryStmt));
return new (Mem) CXXTryStmt(tryLoc, tryBlock, handlers);
}
@@ -37,7 +37,7 @@ CXXTryStmt *CXXTryStmt::Create(const ASTContext &C, EmptyShell Empty,
std::size_t Size = sizeof(CXXTryStmt);
Size += ((numHandlers + 1) * sizeof(Stmt *));
- void *Mem = C.Allocate(Size, llvm::alignOf<CXXTryStmt>());
+ void *Mem = C.Allocate(Size, alignof(CXXTryStmt));
return new (Mem) CXXTryStmt(Empty, numHandlers);
}
diff --git a/lib/AST/StmtObjC.cpp b/lib/AST/StmtObjC.cpp
index a77550c7605d..eea03f64c2fe 100644
--- a/lib/AST/StmtObjC.cpp
+++ b/lib/AST/StmtObjC.cpp
@@ -50,7 +50,7 @@ ObjCAtTryStmt *ObjCAtTryStmt::Create(const ASTContext &Context,
unsigned Size =
sizeof(ObjCAtTryStmt) +
(1 + NumCatchStmts + (atFinallyStmt != nullptr)) * sizeof(Stmt *);
- void *Mem = Context.Allocate(Size, llvm::alignOf<ObjCAtTryStmt>());
+ void *Mem = Context.Allocate(Size, alignof(ObjCAtTryStmt));
return new (Mem) ObjCAtTryStmt(atTryLoc, atTryStmt, CatchStmts, NumCatchStmts,
atFinallyStmt);
}
@@ -60,7 +60,7 @@ ObjCAtTryStmt *ObjCAtTryStmt::CreateEmpty(const ASTContext &Context,
bool HasFinally) {
unsigned Size =
sizeof(ObjCAtTryStmt) + (1 + NumCatchStmts + HasFinally) * sizeof(Stmt *);
- void *Mem = Context.Allocate(Size, llvm::alignOf<ObjCAtTryStmt>());
+ void *Mem = Context.Allocate(Size, alignof(ObjCAtTryStmt));
return new (Mem) ObjCAtTryStmt(EmptyShell(), NumCatchStmts, HasFinally);
}
diff --git a/lib/AST/StmtOpenMP.cpp b/lib/AST/StmtOpenMP.cpp
index f1ddedb2b0f2..0a90740162b9 100644
--- a/lib/AST/StmtOpenMP.cpp
+++ b/lib/AST/StmtOpenMP.cpp
@@ -58,7 +58,7 @@ OMPParallelDirective *OMPParallelDirective::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, bool HasCancel) {
unsigned Size =
- llvm::alignTo(sizeof(OMPParallelDirective), llvm::alignOf<OMPClause *>());
+ llvm::alignTo(sizeof(OMPParallelDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
OMPParallelDirective *Dir =
@@ -73,7 +73,7 @@ OMPParallelDirective *OMPParallelDirective::CreateEmpty(const ASTContext &C,
unsigned NumClauses,
EmptyShell) {
unsigned Size =
- llvm::alignTo(sizeof(OMPParallelDirective), llvm::alignOf<OMPClause *>());
+ llvm::alignTo(sizeof(OMPParallelDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *));
return new (Mem) OMPParallelDirective(NumClauses);
@@ -84,8 +84,7 @@ OMPSimdDirective::Create(const ASTContext &C, SourceLocation StartLoc,
SourceLocation EndLoc, unsigned CollapsedNum,
ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
const HelperExprs &Exprs) {
- unsigned Size =
- llvm::alignTo(sizeof(OMPSimdDirective), llvm::alignOf<OMPClause *>());
+ unsigned Size = llvm::alignTo(sizeof(OMPSimdDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_simd));
@@ -113,8 +112,7 @@ OMPSimdDirective *OMPSimdDirective::CreateEmpty(const ASTContext &C,
unsigned NumClauses,
unsigned CollapsedNum,
EmptyShell) {
- unsigned Size =
- llvm::alignTo(sizeof(OMPSimdDirective), llvm::alignOf<OMPClause *>());
+ unsigned Size = llvm::alignTo(sizeof(OMPSimdDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(OMPClause *) * NumClauses +
sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_simd));
@@ -126,8 +124,7 @@ OMPForDirective::Create(const ASTContext &C, SourceLocation StartLoc,
SourceLocation EndLoc, unsigned CollapsedNum,
ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
const HelperExprs &Exprs, bool HasCancel) {
- unsigned Size =
- llvm::alignTo(sizeof(OMPForDirective), llvm::alignOf<OMPClause *>());
+ unsigned Size = llvm::alignTo(sizeof(OMPForDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_for));
@@ -166,8 +163,7 @@ OMPForDirective *OMPForDirective::CreateEmpty(const ASTContext &C,
unsigned NumClauses,
unsigned CollapsedNum,
EmptyShell) {
- unsigned Size =
- llvm::alignTo(sizeof(OMPForDirective), llvm::alignOf<OMPClause *>());
+ unsigned Size = llvm::alignTo(sizeof(OMPForDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(OMPClause *) * NumClauses +
sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_for));
@@ -180,7 +176,7 @@ OMPForSimdDirective::Create(const ASTContext &C, SourceLocation StartLoc,
ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
const HelperExprs &Exprs) {
unsigned Size =
- llvm::alignTo(sizeof(OMPForSimdDirective), llvm::alignOf<OMPClause *>());
+ llvm::alignTo(sizeof(OMPForSimdDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_for_simd));
@@ -219,7 +215,7 @@ OMPForSimdDirective *OMPForSimdDirective::CreateEmpty(const ASTContext &C,
unsigned CollapsedNum,
EmptyShell) {
unsigned Size =
- llvm::alignTo(sizeof(OMPForSimdDirective), llvm::alignOf<OMPClause *>());
+ llvm::alignTo(sizeof(OMPForSimdDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(OMPClause *) * NumClauses +
sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_for_simd));
@@ -230,7 +226,7 @@ OMPSectionsDirective *OMPSectionsDirective::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, bool HasCancel) {
unsigned Size =
- llvm::alignTo(sizeof(OMPSectionsDirective), llvm::alignOf<OMPClause *>());
+ llvm::alignTo(sizeof(OMPSectionsDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
OMPSectionsDirective *Dir =
@@ -245,7 +241,7 @@ OMPSectionsDirective *OMPSectionsDirective::CreateEmpty(const ASTContext &C,
unsigned NumClauses,
EmptyShell) {
unsigned Size =
- llvm::alignTo(sizeof(OMPSectionsDirective), llvm::alignOf<OMPClause *>());
+ llvm::alignTo(sizeof(OMPSectionsDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *));
return new (Mem) OMPSectionsDirective(NumClauses);
@@ -256,8 +252,7 @@ OMPSectionDirective *OMPSectionDirective::Create(const ASTContext &C,
SourceLocation EndLoc,
Stmt *AssociatedStmt,
bool HasCancel) {
- unsigned Size =
- llvm::alignTo(sizeof(OMPSectionDirective), llvm::alignOf<Stmt *>());
+ unsigned Size = llvm::alignTo(sizeof(OMPSectionDirective), alignof(Stmt *));
void *Mem = C.Allocate(Size + sizeof(Stmt *));
OMPSectionDirective *Dir = new (Mem) OMPSectionDirective(StartLoc, EndLoc);
Dir->setAssociatedStmt(AssociatedStmt);
@@ -267,8 +262,7 @@ OMPSectionDirective *OMPSectionDirective::Create(const ASTContext &C,
OMPSectionDirective *OMPSectionDirective::CreateEmpty(const ASTContext &C,
EmptyShell) {
- unsigned Size =
- llvm::alignTo(sizeof(OMPSectionDirective), llvm::alignOf<Stmt *>());
+ unsigned Size = llvm::alignTo(sizeof(OMPSectionDirective), alignof(Stmt *));
void *Mem = C.Allocate(Size + sizeof(Stmt *));
return new (Mem) OMPSectionDirective();
}
@@ -279,7 +273,7 @@ OMPSingleDirective *OMPSingleDirective::Create(const ASTContext &C,
ArrayRef<OMPClause *> Clauses,
Stmt *AssociatedStmt) {
unsigned Size =
- llvm::alignTo(sizeof(OMPSingleDirective), llvm::alignOf<OMPClause *>());
+ llvm::alignTo(sizeof(OMPSingleDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
OMPSingleDirective *Dir =
@@ -293,7 +287,7 @@ OMPSingleDirective *OMPSingleDirective::CreateEmpty(const ASTContext &C,
unsigned NumClauses,
EmptyShell) {
unsigned Size =
- llvm::alignTo(sizeof(OMPSingleDirective), llvm::alignOf<OMPClause *>());
+ llvm::alignTo(sizeof(OMPSingleDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *));
return new (Mem) OMPSingleDirective(NumClauses);
@@ -303,8 +297,7 @@ OMPMasterDirective *OMPMasterDirective::Create(const ASTContext &C,
SourceLocation StartLoc,
SourceLocation EndLoc,
Stmt *AssociatedStmt) {
- unsigned Size =
- llvm::alignTo(sizeof(OMPMasterDirective), llvm::alignOf<Stmt *>());
+ unsigned Size = llvm::alignTo(sizeof(OMPMasterDirective), alignof(Stmt *));
void *Mem = C.Allocate(Size + sizeof(Stmt *));
OMPMasterDirective *Dir = new (Mem) OMPMasterDirective(StartLoc, EndLoc);
Dir->setAssociatedStmt(AssociatedStmt);
@@ -313,8 +306,7 @@ OMPMasterDirective *OMPMasterDirective::Create(const ASTContext &C,
OMPMasterDirective *OMPMasterDirective::CreateEmpty(const ASTContext &C,
EmptyShell) {
- unsigned Size =
- llvm::alignTo(sizeof(OMPMasterDirective), llvm::alignOf<Stmt *>());
+ unsigned Size = llvm::alignTo(sizeof(OMPMasterDirective), alignof(Stmt *));
void *Mem = C.Allocate(Size + sizeof(Stmt *));
return new (Mem) OMPMasterDirective();
}
@@ -324,7 +316,7 @@ OMPCriticalDirective *OMPCriticalDirective::Create(
SourceLocation StartLoc, SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) {
unsigned Size =
- llvm::alignTo(sizeof(OMPCriticalDirective), llvm::alignOf<OMPClause *>());
+ llvm::alignTo(sizeof(OMPCriticalDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
OMPCriticalDirective *Dir =
@@ -338,7 +330,7 @@ OMPCriticalDirective *OMPCriticalDirective::CreateEmpty(const ASTContext &C,
unsigned NumClauses,
EmptyShell) {
unsigned Size =
- llvm::alignTo(sizeof(OMPCriticalDirective), llvm::alignOf<OMPClause *>());
+ llvm::alignTo(sizeof(OMPCriticalDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *));
return new (Mem) OMPCriticalDirective(NumClauses);
@@ -348,8 +340,8 @@ OMPParallelForDirective *OMPParallelForDirective::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
const HelperExprs &Exprs, bool HasCancel) {
- unsigned Size = llvm::alignTo(sizeof(OMPParallelForDirective),
- llvm::alignOf<OMPClause *>());
+ unsigned Size =
+ llvm::alignTo(sizeof(OMPParallelForDirective), alignof(OMPClause *));
void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
sizeof(Stmt *) *
numLoopChildren(CollapsedNum, OMPD_parallel_for));
@@ -387,8 +379,8 @@ OMPParallelForDirective *OMPParallelForDirective::Create(
OMPParallelForDirective *
OMPParallelForDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses,
unsigned CollapsedNum, EmptyShell) {
- unsigned Size = llvm::alignTo(sizeof(OMPParallelForDirective),
- llvm::alignOf<OMPClause *>());
+ unsigned Size =
+ llvm::alignTo(sizeof(OMPParallelForDirective), alignof(OMPClause *));
void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses +
sizeof(Stmt *) *
numLoopChildren(CollapsedNum, OMPD_parallel_for));
@@ -399,8 +391,8 @@ OMPParallelForSimdDirective *OMPParallelForSimdDirective::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
const HelperExprs &Exprs) {
- unsigned Size = llvm::alignTo(sizeof(OMPParallelForSimdDirective),
- llvm::alignOf<OMPClause *>());
+ unsigned Size =
+ llvm::alignTo(sizeof(OMPParallelForSimdDirective), alignof(OMPClause *));
void *Mem = C.Allocate(
Size + sizeof(OMPClause *) * Clauses.size() +
sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_parallel_for_simd));
@@ -438,8 +430,8 @@ OMPParallelForSimdDirective *
OMPParallelForSimdDirective::CreateEmpty(const ASTContext &C,
unsigned NumClauses,
unsigned CollapsedNum, EmptyShell) {
- unsigned Size = llvm::alignTo(sizeof(OMPParallelForSimdDirective),
- llvm::alignOf<OMPClause *>());
+ unsigned Size =
+ llvm::alignTo(sizeof(OMPParallelForSimdDirective), alignof(OMPClause *));
void *Mem = C.Allocate(
Size + sizeof(OMPClause *) * NumClauses +
sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_parallel_for_simd));
@@ -449,8 +441,8 @@ OMPParallelForSimdDirective::CreateEmpty(const ASTContext &C,
OMPParallelSectionsDirective *OMPParallelSectionsDirective::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, bool HasCancel) {
- unsigned Size = llvm::alignTo(sizeof(OMPParallelSectionsDirective),
- llvm::alignOf<OMPClause *>());
+ unsigned Size =
+ llvm::alignTo(sizeof(OMPParallelSectionsDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
OMPParallelSectionsDirective *Dir =
@@ -464,8 +456,8 @@ OMPParallelSectionsDirective *OMPParallelSectionsDirective::Create(
OMPParallelSectionsDirective *
OMPParallelSectionsDirective::CreateEmpty(const ASTContext &C,
unsigned NumClauses, EmptyShell) {
- unsigned Size = llvm::alignTo(sizeof(OMPParallelSectionsDirective),
- llvm::alignOf<OMPClause *>());
+ unsigned Size =
+ llvm::alignTo(sizeof(OMPParallelSectionsDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *));
return new (Mem) OMPParallelSectionsDirective(NumClauses);
@@ -475,8 +467,7 @@ OMPTaskDirective *
OMPTaskDirective::Create(const ASTContext &C, SourceLocation StartLoc,
SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses,
Stmt *AssociatedStmt, bool HasCancel) {
- unsigned Size =
- llvm::alignTo(sizeof(OMPTaskDirective), llvm::alignOf<OMPClause *>());
+ unsigned Size = llvm::alignTo(sizeof(OMPTaskDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
OMPTaskDirective *Dir =
@@ -490,8 +481,7 @@ OMPTaskDirective::Create(const ASTContext &C, SourceLocation StartLoc,
OMPTaskDirective *OMPTaskDirective::CreateEmpty(const ASTContext &C,
unsigned NumClauses,
EmptyShell) {
- unsigned Size =
- llvm::alignTo(sizeof(OMPTaskDirective), llvm::alignOf<OMPClause *>());
+ unsigned Size = llvm::alignTo(sizeof(OMPTaskDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *));
return new (Mem) OMPTaskDirective(NumClauses);
@@ -544,8 +534,7 @@ OMPTaskgroupDirective *OMPTaskgroupDirective::Create(const ASTContext &C,
SourceLocation StartLoc,
SourceLocation EndLoc,
Stmt *AssociatedStmt) {
- unsigned Size =
- llvm::alignTo(sizeof(OMPTaskgroupDirective), llvm::alignOf<Stmt *>());
+ unsigned Size = llvm::alignTo(sizeof(OMPTaskgroupDirective), alignof(Stmt *));
void *Mem = C.Allocate(Size + sizeof(Stmt *));
OMPTaskgroupDirective *Dir =
new (Mem) OMPTaskgroupDirective(StartLoc, EndLoc);
@@ -555,8 +544,7 @@ OMPTaskgroupDirective *OMPTaskgroupDirective::Create(const ASTContext &C,
OMPTaskgroupDirective *OMPTaskgroupDirective::CreateEmpty(const ASTContext &C,
EmptyShell) {
- unsigned Size =
- llvm::alignTo(sizeof(OMPTaskgroupDirective), llvm::alignOf<Stmt *>());
+ unsigned Size = llvm::alignTo(sizeof(OMPTaskgroupDirective), alignof(Stmt *));
void *Mem = C.Allocate(Size + sizeof(Stmt *));
return new (Mem) OMPTaskgroupDirective();
}
@@ -564,8 +552,8 @@ OMPTaskgroupDirective *OMPTaskgroupDirective::CreateEmpty(const ASTContext &C,
OMPCancellationPointDirective *OMPCancellationPointDirective::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
OpenMPDirectiveKind CancelRegion) {
- unsigned Size = llvm::alignTo(sizeof(OMPCancellationPointDirective),
- llvm::alignOf<Stmt *>());
+ unsigned Size =
+ llvm::alignTo(sizeof(OMPCancellationPointDirective), alignof(Stmt *));
void *Mem = C.Allocate(Size);
OMPCancellationPointDirective *Dir =
new (Mem) OMPCancellationPointDirective(StartLoc, EndLoc);
@@ -575,8 +563,8 @@ OMPCancellationPointDirective *OMPCancellationPointDirective::Create(
OMPCancellationPointDirective *
OMPCancellationPointDirective::CreateEmpty(const ASTContext &C, EmptyShell) {
- unsigned Size = llvm::alignTo(sizeof(OMPCancellationPointDirective),
- llvm::alignOf<Stmt *>());
+ unsigned Size =
+ llvm::alignTo(sizeof(OMPCancellationPointDirective), alignof(Stmt *));
void *Mem = C.Allocate(Size);
return new (Mem) OMPCancellationPointDirective();
}
@@ -587,7 +575,7 @@ OMPCancelDirective::Create(const ASTContext &C, SourceLocation StartLoc,
OpenMPDirectiveKind CancelRegion) {
unsigned Size = llvm::alignTo(sizeof(OMPCancelDirective) +
sizeof(OMPClause *) * Clauses.size(),
- llvm::alignOf<Stmt *>());
+ alignof(Stmt *));
void *Mem = C.Allocate(Size);
OMPCancelDirective *Dir =
new (Mem) OMPCancelDirective(StartLoc, EndLoc, Clauses.size());
@@ -601,7 +589,7 @@ OMPCancelDirective *OMPCancelDirective::CreateEmpty(const ASTContext &C,
EmptyShell) {
unsigned Size = llvm::alignTo(sizeof(OMPCancelDirective) +
sizeof(OMPClause *) * NumClauses,
- llvm::alignOf<Stmt *>());
+ alignof(Stmt *));
void *Mem = C.Allocate(Size);
return new (Mem) OMPCancelDirective(NumClauses);
}
@@ -611,7 +599,7 @@ OMPFlushDirective *OMPFlushDirective::Create(const ASTContext &C,
SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses) {
unsigned Size =
- llvm::alignTo(sizeof(OMPFlushDirective), llvm::alignOf<OMPClause *>());
+ llvm::alignTo(sizeof(OMPFlushDirective), alignof(OMPClause *));
void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size());
OMPFlushDirective *Dir =
new (Mem) OMPFlushDirective(StartLoc, EndLoc, Clauses.size());
@@ -623,7 +611,7 @@ OMPFlushDirective *OMPFlushDirective::CreateEmpty(const ASTContext &C,
unsigned NumClauses,
EmptyShell) {
unsigned Size =
- llvm::alignTo(sizeof(OMPFlushDirective), llvm::alignOf<OMPClause *>());
+ llvm::alignTo(sizeof(OMPFlushDirective), alignof(OMPClause *));
void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses);
return new (Mem) OMPFlushDirective(NumClauses);
}
@@ -634,7 +622,7 @@ OMPOrderedDirective *OMPOrderedDirective::Create(const ASTContext &C,
ArrayRef<OMPClause *> Clauses,
Stmt *AssociatedStmt) {
unsigned Size =
- llvm::alignTo(sizeof(OMPOrderedDirective), llvm::alignOf<OMPClause *>());
+ llvm::alignTo(sizeof(OMPOrderedDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(Stmt *) + sizeof(OMPClause *) * Clauses.size());
OMPOrderedDirective *Dir =
@@ -648,7 +636,7 @@ OMPOrderedDirective *OMPOrderedDirective::CreateEmpty(const ASTContext &C,
unsigned NumClauses,
EmptyShell) {
unsigned Size =
- llvm::alignTo(sizeof(OMPOrderedDirective), llvm::alignOf<OMPClause *>());
+ llvm::alignTo(sizeof(OMPOrderedDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(Stmt *) + sizeof(OMPClause *) * NumClauses);
return new (Mem) OMPOrderedDirective(NumClauses);
@@ -659,7 +647,7 @@ OMPAtomicDirective *OMPAtomicDirective::Create(
ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *X, Expr *V,
Expr *E, Expr *UE, bool IsXLHSInRHSPart, bool IsPostfixUpdate) {
unsigned Size =
- llvm::alignTo(sizeof(OMPAtomicDirective), llvm::alignOf<OMPClause *>());
+ llvm::alignTo(sizeof(OMPAtomicDirective), alignof(OMPClause *));
void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
5 * sizeof(Stmt *));
OMPAtomicDirective *Dir =
@@ -679,7 +667,7 @@ OMPAtomicDirective *OMPAtomicDirective::CreateEmpty(const ASTContext &C,
unsigned NumClauses,
EmptyShell) {
unsigned Size =
- llvm::alignTo(sizeof(OMPAtomicDirective), llvm::alignOf<OMPClause *>());
+ llvm::alignTo(sizeof(OMPAtomicDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(OMPClause *) * NumClauses + 5 * sizeof(Stmt *));
return new (Mem) OMPAtomicDirective(NumClauses);
@@ -691,7 +679,7 @@ OMPTargetDirective *OMPTargetDirective::Create(const ASTContext &C,
ArrayRef<OMPClause *> Clauses,
Stmt *AssociatedStmt) {
unsigned Size =
- llvm::alignTo(sizeof(OMPTargetDirective), llvm::alignOf<OMPClause *>());
+ llvm::alignTo(sizeof(OMPTargetDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
OMPTargetDirective *Dir =
@@ -705,7 +693,7 @@ OMPTargetDirective *OMPTargetDirective::CreateEmpty(const ASTContext &C,
unsigned NumClauses,
EmptyShell) {
unsigned Size =
- llvm::alignTo(sizeof(OMPTargetDirective), llvm::alignOf<OMPClause *>());
+ llvm::alignTo(sizeof(OMPTargetDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *));
return new (Mem) OMPTargetDirective(NumClauses);
@@ -714,8 +702,8 @@ OMPTargetDirective *OMPTargetDirective::CreateEmpty(const ASTContext &C,
OMPTargetParallelDirective *OMPTargetParallelDirective::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) {
- unsigned Size = llvm::alignTo(sizeof(OMPTargetParallelDirective),
- llvm::alignOf<OMPClause *>());
+ unsigned Size =
+ llvm::alignTo(sizeof(OMPTargetParallelDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
OMPTargetParallelDirective *Dir =
@@ -728,8 +716,8 @@ OMPTargetParallelDirective *OMPTargetParallelDirective::Create(
OMPTargetParallelDirective *
OMPTargetParallelDirective::CreateEmpty(const ASTContext &C,
unsigned NumClauses, EmptyShell) {
- unsigned Size = llvm::alignTo(sizeof(OMPTargetParallelDirective),
- llvm::alignOf<OMPClause *>());
+ unsigned Size =
+ llvm::alignTo(sizeof(OMPTargetParallelDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *));
return new (Mem) OMPTargetParallelDirective(NumClauses);
@@ -740,7 +728,7 @@ OMPTargetParallelForDirective *OMPTargetParallelForDirective::Create(
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
const HelperExprs &Exprs, bool HasCancel) {
unsigned Size = llvm::alignTo(sizeof(OMPTargetParallelForDirective),
- llvm::alignOf<OMPClause *>());
+ alignof(OMPClause *));
void *Mem = C.Allocate(
Size + sizeof(OMPClause *) * Clauses.size() +
sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_target_parallel_for));
@@ -780,7 +768,7 @@ OMPTargetParallelForDirective::CreateEmpty(const ASTContext &C,
unsigned NumClauses,
unsigned CollapsedNum, EmptyShell) {
unsigned Size = llvm::alignTo(sizeof(OMPTargetParallelForDirective),
- llvm::alignOf<OMPClause *>());
+ alignof(OMPClause *));
void *Mem = C.Allocate(
Size + sizeof(OMPClause *) * NumClauses +
sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_target_parallel_for));
@@ -790,9 +778,9 @@ OMPTargetParallelForDirective::CreateEmpty(const ASTContext &C,
OMPTargetDataDirective *OMPTargetDataDirective::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) {
- void *Mem = C.Allocate(llvm::alignTo(sizeof(OMPTargetDataDirective),
- llvm::alignOf<OMPClause *>()) +
- sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
+ void *Mem = C.Allocate(
+ llvm::alignTo(sizeof(OMPTargetDataDirective), alignof(OMPClause *)) +
+ sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
OMPTargetDataDirective *Dir =
new (Mem) OMPTargetDataDirective(StartLoc, EndLoc, Clauses.size());
Dir->setClauses(Clauses);
@@ -803,18 +791,18 @@ OMPTargetDataDirective *OMPTargetDataDirective::Create(
OMPTargetDataDirective *OMPTargetDataDirective::CreateEmpty(const ASTContext &C,
unsigned N,
EmptyShell) {
- void *Mem = C.Allocate(llvm::alignTo(sizeof(OMPTargetDataDirective),
- llvm::alignOf<OMPClause *>()) +
- sizeof(OMPClause *) * N + sizeof(Stmt *));
+ void *Mem = C.Allocate(
+ llvm::alignTo(sizeof(OMPTargetDataDirective), alignof(OMPClause *)) +
+ sizeof(OMPClause *) * N + sizeof(Stmt *));
return new (Mem) OMPTargetDataDirective(N);
}
OMPTargetEnterDataDirective *OMPTargetEnterDataDirective::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses) {
- void *Mem = C.Allocate(llvm::alignTo(sizeof(OMPTargetEnterDataDirective),
- llvm::alignOf<OMPClause *>()) +
- sizeof(OMPClause *) * Clauses.size());
+ void *Mem = C.Allocate(
+ llvm::alignTo(sizeof(OMPTargetEnterDataDirective), alignof(OMPClause *)) +
+ sizeof(OMPClause *) * Clauses.size());
OMPTargetEnterDataDirective *Dir =
new (Mem) OMPTargetEnterDataDirective(StartLoc, EndLoc, Clauses.size());
Dir->setClauses(Clauses);
@@ -824,9 +812,9 @@ OMPTargetEnterDataDirective *OMPTargetEnterDataDirective::Create(
OMPTargetEnterDataDirective *
OMPTargetEnterDataDirective::CreateEmpty(const ASTContext &C, unsigned N,
EmptyShell) {
- void *Mem = C.Allocate(llvm::alignTo(sizeof(OMPTargetEnterDataDirective),
- llvm::alignOf<OMPClause *>()) +
- sizeof(OMPClause *) * N);
+ void *Mem = C.Allocate(
+ llvm::alignTo(sizeof(OMPTargetEnterDataDirective), alignof(OMPClause *)) +
+ sizeof(OMPClause *) * N);
return new (Mem) OMPTargetEnterDataDirective(N);
}
@@ -834,9 +822,9 @@ OMPTargetExitDataDirective *
OMPTargetExitDataDirective::Create(const ASTContext &C, SourceLocation StartLoc,
SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses) {
- void *Mem = C.Allocate(llvm::alignTo(sizeof(OMPTargetExitDataDirective),
- llvm::alignOf<OMPClause *>()) +
- sizeof(OMPClause *) * Clauses.size());
+ void *Mem = C.Allocate(
+ llvm::alignTo(sizeof(OMPTargetExitDataDirective), alignof(OMPClause *)) +
+ sizeof(OMPClause *) * Clauses.size());
OMPTargetExitDataDirective *Dir =
new (Mem) OMPTargetExitDataDirective(StartLoc, EndLoc, Clauses.size());
Dir->setClauses(Clauses);
@@ -846,9 +834,9 @@ OMPTargetExitDataDirective::Create(const ASTContext &C, SourceLocation StartLoc,
OMPTargetExitDataDirective *
OMPTargetExitDataDirective::CreateEmpty(const ASTContext &C, unsigned N,
EmptyShell) {
- void *Mem = C.Allocate(llvm::alignTo(sizeof(OMPTargetExitDataDirective),
- llvm::alignOf<OMPClause *>()) +
- sizeof(OMPClause *) * N);
+ void *Mem = C.Allocate(
+ llvm::alignTo(sizeof(OMPTargetExitDataDirective), alignof(OMPClause *)) +
+ sizeof(OMPClause *) * N);
return new (Mem) OMPTargetExitDataDirective(N);
}
@@ -858,7 +846,7 @@ OMPTeamsDirective *OMPTeamsDirective::Create(const ASTContext &C,
ArrayRef<OMPClause *> Clauses,
Stmt *AssociatedStmt) {
unsigned Size =
- llvm::alignTo(sizeof(OMPTeamsDirective), llvm::alignOf<OMPClause *>());
+ llvm::alignTo(sizeof(OMPTeamsDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
OMPTeamsDirective *Dir =
@@ -872,7 +860,7 @@ OMPTeamsDirective *OMPTeamsDirective::CreateEmpty(const ASTContext &C,
unsigned NumClauses,
EmptyShell) {
unsigned Size =
- llvm::alignTo(sizeof(OMPTeamsDirective), llvm::alignOf<OMPClause *>());
+ llvm::alignTo(sizeof(OMPTeamsDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *));
return new (Mem) OMPTeamsDirective(NumClauses);
@@ -883,7 +871,7 @@ OMPTaskLoopDirective *OMPTaskLoopDirective::Create(
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
const HelperExprs &Exprs) {
unsigned Size =
- llvm::alignTo(sizeof(OMPTaskLoopDirective), llvm::alignOf<OMPClause *>());
+ llvm::alignTo(sizeof(OMPTaskLoopDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_taskloop));
@@ -922,7 +910,7 @@ OMPTaskLoopDirective *OMPTaskLoopDirective::CreateEmpty(const ASTContext &C,
unsigned CollapsedNum,
EmptyShell) {
unsigned Size =
- llvm::alignTo(sizeof(OMPTaskLoopDirective), llvm::alignOf<OMPClause *>());
+ llvm::alignTo(sizeof(OMPTaskLoopDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(OMPClause *) * NumClauses +
sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_taskloop));
@@ -933,8 +921,8 @@ OMPTaskLoopSimdDirective *OMPTaskLoopSimdDirective::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
const HelperExprs &Exprs) {
- unsigned Size = llvm::alignTo(sizeof(OMPTaskLoopSimdDirective),
- llvm::alignOf<OMPClause *>());
+ unsigned Size =
+ llvm::alignTo(sizeof(OMPTaskLoopSimdDirective), alignof(OMPClause *));
void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
sizeof(Stmt *) *
numLoopChildren(CollapsedNum, OMPD_taskloop_simd));
@@ -971,8 +959,8 @@ OMPTaskLoopSimdDirective *OMPTaskLoopSimdDirective::Create(
OMPTaskLoopSimdDirective *
OMPTaskLoopSimdDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses,
unsigned CollapsedNum, EmptyShell) {
- unsigned Size = llvm::alignTo(sizeof(OMPTaskLoopSimdDirective),
- llvm::alignOf<OMPClause *>());
+ unsigned Size =
+ llvm::alignTo(sizeof(OMPTaskLoopSimdDirective), alignof(OMPClause *));
void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses +
sizeof(Stmt *) *
numLoopChildren(CollapsedNum, OMPD_taskloop_simd));
@@ -983,8 +971,8 @@ OMPDistributeDirective *OMPDistributeDirective::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
const HelperExprs &Exprs) {
- unsigned Size = llvm::alignTo(sizeof(OMPDistributeDirective),
- llvm::alignOf<OMPClause *>());
+ unsigned Size =
+ llvm::alignTo(sizeof(OMPDistributeDirective), alignof(OMPClause *));
void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
sizeof(Stmt *) *
numLoopChildren(CollapsedNum, OMPD_distribute));
@@ -1021,8 +1009,8 @@ OMPDistributeDirective *OMPDistributeDirective::Create(
OMPDistributeDirective *
OMPDistributeDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses,
unsigned CollapsedNum, EmptyShell) {
- unsigned Size = llvm::alignTo(sizeof(OMPDistributeDirective),
- llvm::alignOf<OMPClause *>());
+ unsigned Size =
+ llvm::alignTo(sizeof(OMPDistributeDirective), alignof(OMPClause *));
void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses +
sizeof(Stmt *) *
numLoopChildren(CollapsedNum, OMPD_distribute));
@@ -1033,8 +1021,8 @@ OMPTargetUpdateDirective *
OMPTargetUpdateDirective::Create(const ASTContext &C, SourceLocation StartLoc,
SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses) {
- unsigned Size = llvm::alignTo(sizeof(OMPTargetUpdateDirective),
- llvm::alignOf<OMPClause *>());
+ unsigned Size =
+ llvm::alignTo(sizeof(OMPTargetUpdateDirective), alignof(OMPClause *));
void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size());
OMPTargetUpdateDirective *Dir =
new (Mem) OMPTargetUpdateDirective(StartLoc, EndLoc, Clauses.size());
@@ -1045,8 +1033,8 @@ OMPTargetUpdateDirective::Create(const ASTContext &C, SourceLocation StartLoc,
OMPTargetUpdateDirective *
OMPTargetUpdateDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses,
EmptyShell) {
- unsigned Size = llvm::alignTo(sizeof(OMPTargetUpdateDirective),
- llvm::alignOf<OMPClause *>());
+ unsigned Size =
+ llvm::alignTo(sizeof(OMPTargetUpdateDirective), alignof(OMPClause *));
void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses);
return new (Mem) OMPTargetUpdateDirective(NumClauses);
}
@@ -1056,7 +1044,7 @@ OMPDistributeParallelForDirective *OMPDistributeParallelForDirective::Create(
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
const HelperExprs &Exprs) {
unsigned Size = llvm::alignTo(sizeof(OMPDistributeParallelForDirective),
- llvm::alignOf<OMPClause *>());
+ alignof(OMPClause *));
void *Mem = C.Allocate(
Size + sizeof(OMPClause *) * Clauses.size() +
sizeof(Stmt *) *
@@ -1098,7 +1086,7 @@ OMPDistributeParallelForDirective::CreateEmpty(const ASTContext &C,
unsigned CollapsedNum,
EmptyShell) {
unsigned Size = llvm::alignTo(sizeof(OMPDistributeParallelForDirective),
- llvm::alignOf<OMPClause *>());
+ alignof(OMPClause *));
void *Mem = C.Allocate(
Size + sizeof(OMPClause *) * NumClauses +
sizeof(Stmt *) *
@@ -1112,7 +1100,7 @@ OMPDistributeParallelForSimdDirective::Create(
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
const HelperExprs &Exprs) {
unsigned Size = llvm::alignTo(sizeof(OMPDistributeParallelForSimdDirective),
- llvm::alignOf<OMPClause *>());
+ alignof(OMPClause *));
void *Mem = C.Allocate(
Size + sizeof(OMPClause *) * Clauses.size() +
sizeof(Stmt *) *
@@ -1154,7 +1142,7 @@ OMPDistributeParallelForSimdDirective::CreateEmpty(const ASTContext &C,
unsigned CollapsedNum,
EmptyShell) {
unsigned Size = llvm::alignTo(sizeof(OMPDistributeParallelForSimdDirective),
- llvm::alignOf<OMPClause *>());
+ alignof(OMPClause *));
void *Mem = C.Allocate(
Size + sizeof(OMPClause *) * NumClauses +
sizeof(Stmt *) *
@@ -1167,8 +1155,8 @@ OMPDistributeSimdDirective *OMPDistributeSimdDirective::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
const HelperExprs &Exprs) {
- unsigned Size = llvm::alignTo(sizeof(OMPDistributeSimdDirective),
- llvm::alignOf<OMPClause *>());
+ unsigned Size =
+ llvm::alignTo(sizeof(OMPDistributeSimdDirective), alignof(OMPClause *));
void *Mem = C.Allocate(
Size + sizeof(OMPClause *) * Clauses.size() +
sizeof(Stmt *) *
@@ -1207,8 +1195,8 @@ OMPDistributeSimdDirective *
OMPDistributeSimdDirective::CreateEmpty(const ASTContext &C,
unsigned NumClauses,
unsigned CollapsedNum, EmptyShell) {
- unsigned Size = llvm::alignTo(sizeof(OMPDistributeSimdDirective),
- llvm::alignOf<OMPClause *>());
+ unsigned Size =
+ llvm::alignTo(sizeof(OMPDistributeSimdDirective), alignof(OMPClause *));
void *Mem = C.Allocate(
Size + sizeof(OMPClause *) * NumClauses +
sizeof(Stmt *) *
@@ -1221,7 +1209,7 @@ OMPTargetParallelForSimdDirective *OMPTargetParallelForSimdDirective::Create(
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
const HelperExprs &Exprs) {
unsigned Size = llvm::alignTo(sizeof(OMPTargetParallelForSimdDirective),
- llvm::alignOf<OMPClause *>());
+ alignof(OMPClause *));
void *Mem = C.Allocate(
Size + sizeof(OMPClause *) * Clauses.size() +
sizeof(Stmt *) *
@@ -1263,10 +1251,411 @@ OMPTargetParallelForSimdDirective::CreateEmpty(const ASTContext &C,
unsigned CollapsedNum,
EmptyShell) {
unsigned Size = llvm::alignTo(sizeof(OMPTargetParallelForSimdDirective),
- llvm::alignOf<OMPClause *>());
+ alignof(OMPClause *));
void *Mem = C.Allocate(
Size + sizeof(OMPClause *) * NumClauses +
sizeof(Stmt *) *
numLoopChildren(CollapsedNum, OMPD_target_parallel_for_simd));
return new (Mem) OMPTargetParallelForSimdDirective(CollapsedNum, NumClauses);
}
+
+OMPTargetSimdDirective *
+OMPTargetSimdDirective::Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation EndLoc, unsigned CollapsedNum,
+ ArrayRef<OMPClause *> Clauses,
+ Stmt *AssociatedStmt, const HelperExprs &Exprs) {
+ unsigned Size =
+ llvm::alignTo(sizeof(OMPTargetSimdDirective), alignof(OMPClause *));
+ void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
+ sizeof(Stmt *) *
+ numLoopChildren(CollapsedNum, OMPD_target_simd));
+ OMPTargetSimdDirective *Dir = new (Mem)
+ OMPTargetSimdDirective(StartLoc, EndLoc, CollapsedNum, Clauses.size());
+ Dir->setClauses(Clauses);
+ Dir->setAssociatedStmt(AssociatedStmt);
+ Dir->setIterationVariable(Exprs.IterationVarRef);
+ Dir->setLastIteration(Exprs.LastIteration);
+ Dir->setCalcLastIteration(Exprs.CalcLastIteration);
+ Dir->setPreCond(Exprs.PreCond);
+ Dir->setCond(Exprs.Cond);
+ Dir->setInit(Exprs.Init);
+ Dir->setInc(Exprs.Inc);
+ Dir->setCounters(Exprs.Counters);
+ Dir->setPrivateCounters(Exprs.PrivateCounters);
+ Dir->setInits(Exprs.Inits);
+ Dir->setUpdates(Exprs.Updates);
+ Dir->setFinals(Exprs.Finals);
+ Dir->setPreInits(Exprs.PreInits);
+ return Dir;
+}
+
+OMPTargetSimdDirective *
+OMPTargetSimdDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses,
+ unsigned CollapsedNum, EmptyShell) {
+ unsigned Size =
+ llvm::alignTo(sizeof(OMPTargetSimdDirective), alignof(OMPClause *));
+ void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses +
+ sizeof(Stmt *) *
+ numLoopChildren(CollapsedNum, OMPD_target_simd));
+ return new (Mem) OMPTargetSimdDirective(CollapsedNum, NumClauses);
+}
+
+OMPTeamsDistributeDirective *OMPTeamsDistributeDirective::Create(
+ const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
+ const HelperExprs &Exprs) {
+ unsigned Size =
+ llvm::alignTo(sizeof(OMPTeamsDistributeDirective), alignof(OMPClause *));
+ void *Mem = C.Allocate(
+ Size + sizeof(OMPClause *) * Clauses.size() +
+ sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_teams_distribute));
+ OMPTeamsDistributeDirective *Dir = new (Mem) OMPTeamsDistributeDirective(
+ StartLoc, EndLoc, CollapsedNum, Clauses.size());
+ Dir->setClauses(Clauses);
+ Dir->setAssociatedStmt(AssociatedStmt);
+ Dir->setIterationVariable(Exprs.IterationVarRef);
+ Dir->setLastIteration(Exprs.LastIteration);
+ Dir->setCalcLastIteration(Exprs.CalcLastIteration);
+ Dir->setPreCond(Exprs.PreCond);
+ Dir->setCond(Exprs.Cond);
+ Dir->setInit(Exprs.Init);
+ Dir->setInc(Exprs.Inc);
+ Dir->setIsLastIterVariable(Exprs.IL);
+ Dir->setLowerBoundVariable(Exprs.LB);
+ Dir->setUpperBoundVariable(Exprs.UB);
+ Dir->setStrideVariable(Exprs.ST);
+ Dir->setEnsureUpperBound(Exprs.EUB);
+ Dir->setNextLowerBound(Exprs.NLB);
+ Dir->setNextUpperBound(Exprs.NUB);
+ Dir->setNumIterations(Exprs.NumIterations);
+ Dir->setPrevLowerBoundVariable(Exprs.PrevLB);
+ Dir->setPrevUpperBoundVariable(Exprs.PrevUB);
+ Dir->setCounters(Exprs.Counters);
+ Dir->setPrivateCounters(Exprs.PrivateCounters);
+ Dir->setInits(Exprs.Inits);
+ Dir->setUpdates(Exprs.Updates);
+ Dir->setFinals(Exprs.Finals);
+ Dir->setPreInits(Exprs.PreInits);
+ return Dir;
+}
+
+OMPTeamsDistributeDirective *
+OMPTeamsDistributeDirective::CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ unsigned CollapsedNum, EmptyShell) {
+ unsigned Size =
+ llvm::alignTo(sizeof(OMPTeamsDistributeDirective), alignof(OMPClause *));
+ void *Mem = C.Allocate(
+ Size + sizeof(OMPClause *) * NumClauses +
+ sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_teams_distribute));
+ return new (Mem) OMPTeamsDistributeDirective(CollapsedNum, NumClauses);
+}
+
+OMPTeamsDistributeSimdDirective *OMPTeamsDistributeSimdDirective::Create(
+ const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
+ const HelperExprs &Exprs) {
+ unsigned Size = llvm::alignTo(sizeof(OMPTeamsDistributeSimdDirective),
+ alignof(OMPClause *));
+ void *Mem =
+ C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
+ sizeof(Stmt *) *
+ numLoopChildren(CollapsedNum, OMPD_teams_distribute_simd));
+ OMPTeamsDistributeSimdDirective *Dir =
+ new (Mem) OMPTeamsDistributeSimdDirective(StartLoc, EndLoc, CollapsedNum,
+ Clauses.size());
+ Dir->setClauses(Clauses);
+ Dir->setAssociatedStmt(AssociatedStmt);
+ Dir->setIterationVariable(Exprs.IterationVarRef);
+ Dir->setLastIteration(Exprs.LastIteration);
+ Dir->setCalcLastIteration(Exprs.CalcLastIteration);
+ Dir->setPreCond(Exprs.PreCond);
+ Dir->setCond(Exprs.Cond);
+ Dir->setInit(Exprs.Init);
+ Dir->setInc(Exprs.Inc);
+ Dir->setIsLastIterVariable(Exprs.IL);
+ Dir->setLowerBoundVariable(Exprs.LB);
+ Dir->setUpperBoundVariable(Exprs.UB);
+ Dir->setStrideVariable(Exprs.ST);
+ Dir->setEnsureUpperBound(Exprs.EUB);
+ Dir->setNextLowerBound(Exprs.NLB);
+ Dir->setNextUpperBound(Exprs.NUB);
+ Dir->setNumIterations(Exprs.NumIterations);
+ Dir->setPrevLowerBoundVariable(Exprs.PrevLB);
+ Dir->setPrevUpperBoundVariable(Exprs.PrevUB);
+ Dir->setCounters(Exprs.Counters);
+ Dir->setPrivateCounters(Exprs.PrivateCounters);
+ Dir->setInits(Exprs.Inits);
+ Dir->setUpdates(Exprs.Updates);
+ Dir->setFinals(Exprs.Finals);
+ Dir->setPreInits(Exprs.PreInits);
+ return Dir;
+}
+
+OMPTeamsDistributeSimdDirective *OMPTeamsDistributeSimdDirective::CreateEmpty(
+ const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum,
+ EmptyShell) {
+ unsigned Size = llvm::alignTo(sizeof(OMPTeamsDistributeSimdDirective),
+ alignof(OMPClause *));
+ void *Mem =
+ C.Allocate(Size + sizeof(OMPClause *) * NumClauses +
+ sizeof(Stmt *) *
+ numLoopChildren(CollapsedNum, OMPD_teams_distribute_simd));
+ return new (Mem) OMPTeamsDistributeSimdDirective(CollapsedNum, NumClauses);
+}
+
+OMPTeamsDistributeParallelForSimdDirective *
+OMPTeamsDistributeParallelForSimdDirective::Create(
+ const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
+ const HelperExprs &Exprs) {
+ auto Size = llvm::alignTo(sizeof(OMPTeamsDistributeParallelForSimdDirective),
+ alignof(OMPClause *));
+ void *Mem =
+ C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
+ sizeof(Stmt *) *
+ numLoopChildren(CollapsedNum,
+ OMPD_teams_distribute_parallel_for_simd));
+ OMPTeamsDistributeParallelForSimdDirective *Dir = new (Mem)
+ OMPTeamsDistributeParallelForSimdDirective(StartLoc, EndLoc, CollapsedNum,
+ Clauses.size());
+ Dir->setClauses(Clauses);
+ Dir->setAssociatedStmt(AssociatedStmt);
+ Dir->setIterationVariable(Exprs.IterationVarRef);
+ Dir->setLastIteration(Exprs.LastIteration);
+ Dir->setCalcLastIteration(Exprs.CalcLastIteration);
+ Dir->setPreCond(Exprs.PreCond);
+ Dir->setCond(Exprs.Cond);
+ Dir->setInit(Exprs.Init);
+ Dir->setInc(Exprs.Inc);
+ Dir->setIsLastIterVariable(Exprs.IL);
+ Dir->setLowerBoundVariable(Exprs.LB);
+ Dir->setUpperBoundVariable(Exprs.UB);
+ Dir->setStrideVariable(Exprs.ST);
+ Dir->setEnsureUpperBound(Exprs.EUB);
+ Dir->setNextLowerBound(Exprs.NLB);
+ Dir->setNextUpperBound(Exprs.NUB);
+ Dir->setNumIterations(Exprs.NumIterations);
+ Dir->setPrevLowerBoundVariable(Exprs.PrevLB);
+ Dir->setPrevUpperBoundVariable(Exprs.PrevUB);
+ Dir->setCounters(Exprs.Counters);
+ Dir->setPrivateCounters(Exprs.PrivateCounters);
+ Dir->setInits(Exprs.Inits);
+ Dir->setUpdates(Exprs.Updates);
+ Dir->setFinals(Exprs.Finals);
+ Dir->setPreInits(Exprs.PreInits);
+ return Dir;
+}
+
+OMPTeamsDistributeParallelForSimdDirective *
+OMPTeamsDistributeParallelForSimdDirective::CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ unsigned CollapsedNum,
+ EmptyShell) {
+ auto Size = llvm::alignTo(sizeof(OMPTeamsDistributeParallelForSimdDirective),
+ alignof(OMPClause *));
+ void *Mem =
+ C.Allocate(Size + sizeof(OMPClause *) * NumClauses +
+ sizeof(Stmt *) *
+ numLoopChildren(CollapsedNum,
+ OMPD_teams_distribute_parallel_for_simd));
+ return new (Mem)
+ OMPTeamsDistributeParallelForSimdDirective(CollapsedNum, NumClauses);
+}
+
+OMPTeamsDistributeParallelForDirective *
+OMPTeamsDistributeParallelForDirective::Create(
+ const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
+ const HelperExprs &Exprs) {
+ auto Size = llvm::alignTo(sizeof(OMPTeamsDistributeParallelForDirective),
+ alignof(OMPClause *));
+ void *Mem = C.Allocate(
+ Size + sizeof(OMPClause *) * Clauses.size() +
+ sizeof(Stmt *) *
+ numLoopChildren(CollapsedNum, OMPD_teams_distribute_parallel_for));
+ OMPTeamsDistributeParallelForDirective *Dir = new (Mem)
+ OMPTeamsDistributeParallelForDirective(StartLoc, EndLoc, CollapsedNum,
+ Clauses.size());
+ Dir->setClauses(Clauses);
+ Dir->setAssociatedStmt(AssociatedStmt);
+ Dir->setIterationVariable(Exprs.IterationVarRef);
+ Dir->setLastIteration(Exprs.LastIteration);
+ Dir->setCalcLastIteration(Exprs.CalcLastIteration);
+ Dir->setPreCond(Exprs.PreCond);
+ Dir->setCond(Exprs.Cond);
+ Dir->setInit(Exprs.Init);
+ Dir->setInc(Exprs.Inc);
+ Dir->setIsLastIterVariable(Exprs.IL);
+ Dir->setLowerBoundVariable(Exprs.LB);
+ Dir->setUpperBoundVariable(Exprs.UB);
+ Dir->setStrideVariable(Exprs.ST);
+ Dir->setEnsureUpperBound(Exprs.EUB);
+ Dir->setNextLowerBound(Exprs.NLB);
+ Dir->setNextUpperBound(Exprs.NUB);
+ Dir->setNumIterations(Exprs.NumIterations);
+ Dir->setPrevLowerBoundVariable(Exprs.PrevLB);
+ Dir->setPrevUpperBoundVariable(Exprs.PrevUB);
+ Dir->setCounters(Exprs.Counters);
+ Dir->setPrivateCounters(Exprs.PrivateCounters);
+ Dir->setInits(Exprs.Inits);
+ Dir->setUpdates(Exprs.Updates);
+ Dir->setFinals(Exprs.Finals);
+ Dir->setPreInits(Exprs.PreInits);
+ return Dir;
+}
+
+OMPTeamsDistributeParallelForDirective *
+OMPTeamsDistributeParallelForDirective::CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ unsigned CollapsedNum,
+ EmptyShell) {
+ auto Size = llvm::alignTo(sizeof(OMPTeamsDistributeParallelForDirective),
+ alignof(OMPClause *));
+ void *Mem = C.Allocate(
+ Size + sizeof(OMPClause *) * NumClauses +
+ sizeof(Stmt *) *
+ numLoopChildren(CollapsedNum, OMPD_teams_distribute_parallel_for));
+ return new (Mem)
+ OMPTeamsDistributeParallelForDirective(CollapsedNum, NumClauses);
+}
+
+OMPTargetTeamsDirective *OMPTargetTeamsDirective::Create(
+ const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) {
+ auto Size =
+ llvm::alignTo(sizeof(OMPTargetTeamsDirective), alignof(OMPClause *));
+ void *Mem =
+ C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
+ OMPTargetTeamsDirective *Dir =
+ new (Mem) OMPTargetTeamsDirective(StartLoc, EndLoc, Clauses.size());
+ Dir->setClauses(Clauses);
+ Dir->setAssociatedStmt(AssociatedStmt);
+ return Dir;
+}
+
+OMPTargetTeamsDirective *
+OMPTargetTeamsDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses,
+ EmptyShell) {
+ auto Size =
+ llvm::alignTo(sizeof(OMPTargetTeamsDirective), alignof(OMPClause *));
+ void *Mem =
+ C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *));
+ return new (Mem) OMPTargetTeamsDirective(NumClauses);
+}
+
+OMPTargetTeamsDistributeDirective *OMPTargetTeamsDistributeDirective::Create(
+ const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
+ const HelperExprs &Exprs) {
+ auto Size = llvm::alignTo(sizeof(OMPTargetTeamsDistributeDirective),
+ alignof(OMPClause *));
+ void *Mem = C.Allocate(
+ Size + sizeof(OMPClause *) * Clauses.size() +
+ sizeof(Stmt *) *
+ numLoopChildren(CollapsedNum, OMPD_target_teams_distribute));
+ OMPTargetTeamsDistributeDirective *Dir =
+ new (Mem) OMPTargetTeamsDistributeDirective(StartLoc, EndLoc, CollapsedNum,
+ Clauses.size());
+ Dir->setClauses(Clauses);
+ Dir->setAssociatedStmt(AssociatedStmt);
+ Dir->setIterationVariable(Exprs.IterationVarRef);
+ Dir->setLastIteration(Exprs.LastIteration);
+ Dir->setCalcLastIteration(Exprs.CalcLastIteration);
+ Dir->setPreCond(Exprs.PreCond);
+ Dir->setCond(Exprs.Cond);
+ Dir->setInit(Exprs.Init);
+ Dir->setInc(Exprs.Inc);
+ Dir->setIsLastIterVariable(Exprs.IL);
+ Dir->setLowerBoundVariable(Exprs.LB);
+ Dir->setUpperBoundVariable(Exprs.UB);
+ Dir->setStrideVariable(Exprs.ST);
+ Dir->setEnsureUpperBound(Exprs.EUB);
+ Dir->setNextLowerBound(Exprs.NLB);
+ Dir->setNextUpperBound(Exprs.NUB);
+ Dir->setNumIterations(Exprs.NumIterations);
+ Dir->setPrevLowerBoundVariable(Exprs.PrevLB);
+ Dir->setPrevUpperBoundVariable(Exprs.PrevUB);
+ Dir->setCounters(Exprs.Counters);
+ Dir->setPrivateCounters(Exprs.PrivateCounters);
+ Dir->setInits(Exprs.Inits);
+ Dir->setUpdates(Exprs.Updates);
+ Dir->setFinals(Exprs.Finals);
+ Dir->setPreInits(Exprs.PreInits);
+ return Dir;
+}
+
+OMPTargetTeamsDistributeDirective *
+OMPTargetTeamsDistributeDirective::CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ unsigned CollapsedNum,
+ EmptyShell) {
+ auto Size = llvm::alignTo(sizeof(OMPTargetTeamsDistributeDirective),
+ alignof(OMPClause *));
+ void *Mem = C.Allocate(
+ Size + sizeof(OMPClause *) * NumClauses +
+ sizeof(Stmt *) *
+ numLoopChildren(CollapsedNum, OMPD_target_teams_distribute));
+ return new (Mem) OMPTargetTeamsDistributeDirective(CollapsedNum, NumClauses);
+}
+
+OMPTargetTeamsDistributeParallelForDirective *
+OMPTargetTeamsDistributeParallelForDirective::Create(
+ const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
+ const HelperExprs &Exprs) {
+ auto Size =
+ llvm::alignTo(sizeof(OMPTargetTeamsDistributeParallelForDirective),
+ alignof(OMPClause *));
+ void *Mem = C.Allocate(
+ Size + sizeof(OMPClause *) * Clauses.size() +
+ sizeof(Stmt *) *
+ numLoopChildren(CollapsedNum,
+ OMPD_target_teams_distribute_parallel_for));
+ OMPTargetTeamsDistributeParallelForDirective *Dir =
+ new (Mem) OMPTargetTeamsDistributeParallelForDirective(
+ StartLoc, EndLoc, CollapsedNum, Clauses.size());
+ Dir->setClauses(Clauses);
+ Dir->setAssociatedStmt(AssociatedStmt);
+ Dir->setIterationVariable(Exprs.IterationVarRef);
+ Dir->setLastIteration(Exprs.LastIteration);
+ Dir->setCalcLastIteration(Exprs.CalcLastIteration);
+ Dir->setPreCond(Exprs.PreCond);
+ Dir->setCond(Exprs.Cond);
+ Dir->setInit(Exprs.Init);
+ Dir->setInc(Exprs.Inc);
+ Dir->setIsLastIterVariable(Exprs.IL);
+ Dir->setLowerBoundVariable(Exprs.LB);
+ Dir->setUpperBoundVariable(Exprs.UB);
+ Dir->setStrideVariable(Exprs.ST);
+ Dir->setEnsureUpperBound(Exprs.EUB);
+ Dir->setNextLowerBound(Exprs.NLB);
+ Dir->setNextUpperBound(Exprs.NUB);
+ Dir->setNumIterations(Exprs.NumIterations);
+ Dir->setPrevLowerBoundVariable(Exprs.PrevLB);
+ Dir->setPrevUpperBoundVariable(Exprs.PrevUB);
+ Dir->setCounters(Exprs.Counters);
+ Dir->setPrivateCounters(Exprs.PrivateCounters);
+ Dir->setInits(Exprs.Inits);
+ Dir->setUpdates(Exprs.Updates);
+ Dir->setFinals(Exprs.Finals);
+ Dir->setPreInits(Exprs.PreInits);
+ return Dir;
+}
+
+OMPTargetTeamsDistributeParallelForDirective *
+OMPTargetTeamsDistributeParallelForDirective::CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ unsigned CollapsedNum,
+ EmptyShell) {
+ auto Size =
+ llvm::alignTo(sizeof(OMPTargetTeamsDistributeParallelForDirective),
+ alignof(OMPClause *));
+ void *Mem = C.Allocate(
+ Size + sizeof(OMPClause *) * NumClauses +
+ sizeof(Stmt *) *
+ numLoopChildren(CollapsedNum,
+ OMPD_target_teams_distribute_parallel_for));
+ return new (Mem)
+ OMPTargetTeamsDistributeParallelForDirective(CollapsedNum, NumClauses);
+}
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index 8797a13335c4..a8f493dca07d 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -1198,6 +1198,52 @@ void StmtPrinter::VisitOMPTargetParallelForSimdDirective(
PrintOMPExecutableDirective(Node);
}
+void StmtPrinter::VisitOMPTargetSimdDirective(OMPTargetSimdDirective *Node) {
+ Indent() << "#pragma omp target simd ";
+ PrintOMPExecutableDirective(Node);
+}
+
+void StmtPrinter::VisitOMPTeamsDistributeDirective(
+ OMPTeamsDistributeDirective *Node) {
+ Indent() << "#pragma omp teams distribute ";
+ PrintOMPExecutableDirective(Node);
+}
+
+void StmtPrinter::VisitOMPTeamsDistributeSimdDirective(
+ OMPTeamsDistributeSimdDirective *Node) {
+ Indent() << "#pragma omp teams distribute simd ";
+ PrintOMPExecutableDirective(Node);
+}
+
+void StmtPrinter::VisitOMPTeamsDistributeParallelForSimdDirective(
+ OMPTeamsDistributeParallelForSimdDirective *Node) {
+ Indent() << "#pragma omp teams distribute parallel for simd ";
+ PrintOMPExecutableDirective(Node);
+}
+
+void StmtPrinter::VisitOMPTeamsDistributeParallelForDirective(
+ OMPTeamsDistributeParallelForDirective *Node) {
+ Indent() << "#pragma omp teams distribute parallel for ";
+ PrintOMPExecutableDirective(Node);
+}
+
+void StmtPrinter::VisitOMPTargetTeamsDirective(OMPTargetTeamsDirective *Node) {
+ Indent() << "#pragma omp target teams ";
+ PrintOMPExecutableDirective(Node);
+}
+
+void StmtPrinter::VisitOMPTargetTeamsDistributeDirective(
+ OMPTargetTeamsDistributeDirective *Node) {
+ Indent() << "#pragma omp target teams distribute ";
+ PrintOMPExecutableDirective(Node);
+}
+
+void StmtPrinter::VisitOMPTargetTeamsDistributeParallelForDirective(
+ OMPTargetTeamsDistributeParallelForDirective *Node) {
+ Indent() << "#pragma omp target teams distribute parallel for ";
+ PrintOMPExecutableDirective(Node);
+}
+
//===----------------------------------------------------------------------===//
// Expr printing methods.
//===----------------------------------------------------------------------===//
@@ -1676,6 +1722,18 @@ void StmtPrinter::VisitInitListExpr(InitListExpr* Node) {
OS << "}";
}
+void StmtPrinter::VisitArrayInitLoopExpr(ArrayInitLoopExpr *Node) {
+ // There's no way to express this expression in any of our supported
+ // languages, so just emit something terse and (hopefully) clear.
+ OS << "{";
+ PrintExpr(Node->getSubExpr());
+ OS << "}";
+}
+
+void StmtPrinter::VisitArrayInitIndexExpr(ArrayInitIndexExpr *Node) {
+ OS << "*";
+}
+
void StmtPrinter::VisitParenListExpr(ParenListExpr* Node) {
OS << "(";
for (unsigned i = 0, e = Node->getNumExprs(); i != e; ++i) {
diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp
index 0a39413853a0..dd59a9b96c98 100644
--- a/lib/AST/StmtProfile.cpp
+++ b/lib/AST/StmtProfile.cpp
@@ -93,10 +93,6 @@ void StmtProfiler::VisitCompoundStmt(const CompoundStmt *S) {
VisitStmt(S);
}
-void StmtProfiler::VisitSwitchCase(const SwitchCase *S) {
- VisitStmt(S);
-}
-
void StmtProfiler::VisitCaseStmt(const CaseStmt *S) {
VisitStmt(S);
}
@@ -727,6 +723,46 @@ void StmtProfiler::VisitOMPTargetParallelForSimdDirective(
VisitOMPLoopDirective(S);
}
+void StmtProfiler::VisitOMPTargetSimdDirective(
+ const OMPTargetSimdDirective *S) {
+ VisitOMPLoopDirective(S);
+}
+
+void StmtProfiler::VisitOMPTeamsDistributeDirective(
+ const OMPTeamsDistributeDirective *S) {
+ VisitOMPLoopDirective(S);
+}
+
+void StmtProfiler::VisitOMPTeamsDistributeSimdDirective(
+ const OMPTeamsDistributeSimdDirective *S) {
+ VisitOMPLoopDirective(S);
+}
+
+void StmtProfiler::VisitOMPTeamsDistributeParallelForSimdDirective(
+ const OMPTeamsDistributeParallelForSimdDirective *S) {
+ VisitOMPLoopDirective(S);
+}
+
+void StmtProfiler::VisitOMPTeamsDistributeParallelForDirective(
+ const OMPTeamsDistributeParallelForDirective *S) {
+ VisitOMPLoopDirective(S);
+}
+
+void StmtProfiler::VisitOMPTargetTeamsDirective(
+ const OMPTargetTeamsDirective *S) {
+ VisitOMPExecutableDirective(S);
+}
+
+void StmtProfiler::VisitOMPTargetTeamsDistributeDirective(
+ const OMPTargetTeamsDistributeDirective *S) {
+ VisitOMPLoopDirective(S);
+}
+
+void StmtProfiler::VisitOMPTargetTeamsDistributeParallelForDirective(
+ const OMPTargetTeamsDistributeParallelForDirective *S) {
+ VisitOMPLoopDirective(S);
+}
+
void StmtProfiler::VisitExpr(const Expr *S) {
VisitStmt(S);
}
@@ -951,6 +987,14 @@ void StmtProfiler::VisitDesignatedInitUpdateExpr(
"initializer");
}
+void StmtProfiler::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *S) {
+ VisitExpr(S);
+}
+
+void StmtProfiler::VisitArrayInitIndexExpr(const ArrayInitIndexExpr *S) {
+ VisitExpr(S);
+}
+
void StmtProfiler::VisitNoInitExpr(const NoInitExpr *S) {
llvm_unreachable("Unexpected NoInitExpr in syntactic form of initializer");
}
@@ -1184,6 +1228,12 @@ void StmtProfiler::VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *S) {
if (S->isTypeDependent()) {
// Type-dependent operator calls are profiled like their underlying
// syntactic operator.
+ //
+ // An operator call to operator-> is always implicit, so just skip it. The
+ // enclosing MemberExpr will profile the actual member access.
+ if (S->getOperator() == OO_Arrow)
+ return Visit(S->getArg(0));
+
UnaryOperatorKind UnaryOp = UO_Extension;
BinaryOperatorKind BinaryOp = BO_Comma;
Stmt::StmtClass SC = DecodeOperatorCall(S, UnaryOp, BinaryOp);
diff --git a/lib/AST/TemplateBase.cpp b/lib/AST/TemplateBase.cpp
index b75ede862f7a..099f939c7a75 100644
--- a/lib/AST/TemplateBase.cpp
+++ b/lib/AST/TemplateBase.cpp
@@ -243,6 +243,31 @@ Optional<unsigned> TemplateArgument::getNumTemplateExpansions() const {
return None;
}
+QualType TemplateArgument::getNonTypeTemplateArgumentType() const {
+ switch (getKind()) {
+ case TemplateArgument::Null:
+ case TemplateArgument::Type:
+ case TemplateArgument::Template:
+ case TemplateArgument::TemplateExpansion:
+ case TemplateArgument::Pack:
+ return QualType();
+
+ case TemplateArgument::Integral:
+ return getIntegralType();
+
+ case TemplateArgument::Expression:
+ return getAsExpr()->getType();
+
+ case TemplateArgument::Declaration:
+ return getParamTypeForDecl();
+
+ case TemplateArgument::NullPtr:
+ return getNullPtrType();
+ }
+
+ llvm_unreachable("Invalid TemplateArgument Kind!");
+}
+
void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID,
const ASTContext &Context) const {
ID.AddInteger(getKind());
@@ -530,7 +555,7 @@ const ASTTemplateArgumentListInfo *
ASTTemplateArgumentListInfo::Create(ASTContext &C,
const TemplateArgumentListInfo &List) {
std::size_t size = totalSizeToAlloc<TemplateArgumentLoc>(List.size());
- void *Mem = C.Allocate(size, llvm::alignOf<ASTTemplateArgumentListInfo>());
+ void *Mem = C.Allocate(size, alignof(ASTTemplateArgumentListInfo));
return new (Mem) ASTTemplateArgumentListInfo(List);
}
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 99b024701aa3..0d0cd2e305be 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -11,6 +11,7 @@
//
//===----------------------------------------------------------------------===//
+#include "clang/AST/Type.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
#include "clang/AST/CharUnits.h"
@@ -19,13 +20,11 @@
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
#include "clang/AST/PrettyPrinter.h"
-#include "clang/AST/Type.h"
#include "clang/AST/TypeVisitor.h"
#include "clang/Basic/Specifiers.h"
#include "clang/Basic/TargetInfo.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/StringExtras.h"
-#include "llvm/Support/raw_ostream.h"
#include <algorithm>
using namespace clang;
@@ -532,6 +531,18 @@ bool Type::isObjCInertUnsafeUnretainedType() const {
}
}
+ObjCTypeParamType::ObjCTypeParamType(const ObjCTypeParamDecl *D,
+ QualType can,
+ ArrayRef<ObjCProtocolDecl *> protocols)
+ : Type(ObjCTypeParam, can, can->isDependentType(),
+ can->isInstantiationDependentType(),
+ can->isVariablyModifiedType(),
+ /*ContainsUnexpandedParameterPack=*/false),
+ OTPDecl(const_cast<ObjCTypeParamDecl*>(D))
+{
+ initialize(protocols);
+}
+
ObjCObjectType::ObjCObjectType(QualType Canonical, QualType Base,
ArrayRef<QualType> typeArgs,
ArrayRef<ObjCProtocolDecl *> protocols,
@@ -547,15 +558,9 @@ ObjCObjectType::ObjCObjectType(QualType Canonical, QualType Base,
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 (!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())
@@ -566,6 +571,9 @@ ObjCObjectType::ObjCObjectType(QualType Canonical, QualType Base,
if (typeArg->containsUnexpandedParameterPack())
setContainsUnexpandedParameterPack();
}
+ // Initialize the protocol qualifiers. The protocol storage is known
+ // after we set number of type arguments.
+ initialize(protocols);
}
bool ObjCObjectType::isSpecialized() const {
@@ -883,6 +891,7 @@ public:
}
TRIVIAL_TYPE_CLASS(Typedef)
+ TRIVIAL_TYPE_CLASS(ObjCTypeParam)
QualType VisitAdjustedType(const AdjustedType *T) {
QualType originalType = recurse(T->getOriginalType());
@@ -1048,7 +1057,7 @@ QualType simpleTransform(ASTContext &ctx, QualType type, F &&f) {
SplitQualType splitType = type.split();
// Visit the type itself.
- SimpleTransformVisitor<F> visitor(ctx, std::move(f));
+ SimpleTransformVisitor<F> visitor(ctx, std::forward<F>(f));
QualType result = visitor.Visit(splitType.Ty);
if (result.isNull())
return result;
@@ -1072,13 +1081,24 @@ QualType QualType::substObjCTypeArgs(
// 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 (const auto *OTPTy = dyn_cast<ObjCTypeParamType>(splitType.Ty)) {
+ if (auto *typeParam = dyn_cast<ObjCTypeParamDecl>(OTPTy->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);
+ if (OTPTy->qual_empty())
+ return ctx.getQualifiedType(argType, splitType.Quals);
+
+ // Apply protocol lists if exists.
+ bool hasError;
+ SmallVector<ObjCProtocolDecl*, 8> protocolsVec;
+ protocolsVec.append(OTPTy->qual_begin(),
+ OTPTy->qual_end());
+ ArrayRef<ObjCProtocolDecl *> protocolsToApply = protocolsVec;
+ QualType resultTy = ctx.applyObjCProtocolQualifiers(argType,
+ protocolsToApply, hasError, true/*allowOnPointerType*/);
+
+ return ctx.getQualifiedType(resultTy, splitType.Quals);
}
switch (context) {
@@ -2317,6 +2337,15 @@ bool QualType::isCXX11PODType(const ASTContext &Context) const {
return false;
}
+bool Type::isAlignValT() const {
+ if (auto *ET = getAs<EnumType>()) {
+ auto *II = ET->getDecl()->getIdentifier();
+ if (II && II->isStr("align_val_t") && ET->getDecl()->isInStdNamespace())
+ return true;
+ }
+ return false;
+}
+
bool Type::isPromotableIntegerType() const {
if (const BuiltinType *BT = getAs<BuiltinType>())
switch (BT->getKind()) {
@@ -2638,6 +2667,7 @@ StringRef FunctionType::getNameForCallConv(CallingConv CC) {
case CC_X86VectorCall: return "vectorcall";
case CC_X86_64Win64: return "ms_abi";
case CC_X86_64SysV: return "sysv_abi";
+ case CC_X86RegCall : return "regcall";
case CC_AAPCS: return "aapcs";
case CC_AAPCS_VFP: return "aapcs-vfp";
case CC_IntelOclBicc: return "intel_ocl_bicc";
@@ -2688,8 +2718,9 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params,
QualType *exnSlot = argSlot + NumParams;
unsigned I = 0;
for (QualType ExceptionType : epi.ExceptionSpec.Exceptions) {
- // Note that a dependent exception specification does *not* make
- // a type dependent; it's not even part of the C++ type system.
+ // Note that, before C++17, a dependent exception specification does
+ // *not* make a type dependent; it's not even part of the C++ type
+ // system.
if (ExceptionType->isInstantiationDependentType())
setInstantiationDependent();
@@ -2728,6 +2759,19 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params,
slot[0] = epi.ExceptionSpec.SourceDecl;
}
+ // If this is a canonical type, and its exception specification is dependent,
+ // then it's a dependent type. This only happens in C++17 onwards.
+ if (isCanonicalUnqualified()) {
+ if (getExceptionSpecType() == EST_Dynamic ||
+ getExceptionSpecType() == EST_ComputedNoexcept) {
+ assert(hasDependentExceptionSpec() && "type should not be canonical");
+ setDependent();
+ }
+ } else if (getCanonicalTypeInternal()->isDependentType()) {
+ // Ask our canonical type whether our exception specification was dependent.
+ setDependent();
+ }
+
if (epi.ExtParameterInfos) {
ExtParameterInfo *extParamInfos =
const_cast<ExtParameterInfo *>(getExtParameterInfosBuffer());
@@ -2748,6 +2792,15 @@ bool FunctionProtoType::hasDependentExceptionSpec() const {
return false;
}
+bool FunctionProtoType::hasInstantiationDependentExceptionSpec() const {
+ if (Expr *NE = getNoexceptExpr())
+ return NE->isInstantiationDependent();
+ for (QualType ET : exceptions())
+ if (ET->isInstantiationDependentType())
+ return true;
+ return false;
+}
+
FunctionProtoType::NoexceptResult
FunctionProtoType::getNoexceptSpec(const ASTContext &ctx) const {
ExceptionSpecificationType est = getExceptionSpecType();
@@ -2772,29 +2825,28 @@ FunctionProtoType::getNoexceptSpec(const ASTContext &ctx) const {
return value.getBoolValue() ? NR_Nothrow : NR_Throw;
}
-bool FunctionProtoType::isNothrow(const ASTContext &Ctx,
- bool ResultIfDependent) const {
+CanThrowResult FunctionProtoType::canThrow(const ASTContext &Ctx) const {
ExceptionSpecificationType EST = getExceptionSpecType();
assert(EST != EST_Unevaluated && EST != EST_Uninstantiated);
if (EST == EST_DynamicNone || EST == EST_BasicNoexcept)
- return true;
+ return CT_Cannot;
- if (EST == EST_Dynamic && ResultIfDependent) {
+ if (EST == EST_Dynamic) {
// A dynamic exception specification is throwing unless every exception
// type is an (unexpanded) pack expansion type.
for (unsigned I = 0, N = NumExceptions; I != N; ++I)
if (!getExceptionType(I)->getAs<PackExpansionType>())
- return false;
- return ResultIfDependent;
+ return CT_Can;
+ return CT_Dependent;
}
if (EST != EST_ComputedNoexcept)
- return false;
+ return CT_Can;
NoexceptResult NR = getNoexceptSpec(Ctx);
if (NR == NR_Dependent)
- return ResultIfDependent;
- return NR == NR_Nothrow;
+ return CT_Dependent;
+ return NR == NR_Nothrow ? CT_Cannot : CT_Can;
}
bool FunctionProtoType::isTemplateVariadic() const {
@@ -2808,7 +2860,7 @@ bool FunctionProtoType::isTemplateVariadic() const {
void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result,
const QualType *ArgTys, unsigned NumParams,
const ExtProtoInfo &epi,
- const ASTContext &Context) {
+ const ASTContext &Context, bool Canonical) {
// We have to be careful not to get ambiguous profile encodings.
// Note that valid type pointers are never ambiguous with anything else.
@@ -2847,7 +2899,7 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result,
ID.AddPointer(Ex.getAsOpaquePtr());
} else if (epi.ExceptionSpec.Type == EST_ComputedNoexcept &&
epi.ExceptionSpec.NoexceptExpr) {
- epi.ExceptionSpec.NoexceptExpr->Profile(ID, Context, false);
+ epi.ExceptionSpec.NoexceptExpr->Profile(ID, Context, Canonical);
} else if (epi.ExceptionSpec.Type == EST_Uninstantiated ||
epi.ExceptionSpec.Type == EST_Unevaluated) {
ID.AddPointer(epi.ExceptionSpec.SourceDecl->getCanonicalDecl());
@@ -2863,7 +2915,7 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result,
void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID,
const ASTContext &Ctx) {
Profile(ID, getReturnType(), param_type_begin(), NumParams, getExtProtoInfo(),
- Ctx);
+ Ctx, isCanonicalUnqualified());
}
QualType TypedefType::desugar() const {
@@ -2992,6 +3044,7 @@ bool AttributedType::isQualifier() const {
case AttributedType::attr_fastcall:
case AttributedType::attr_stdcall:
case AttributedType::attr_thiscall:
+ case AttributedType::attr_regcall:
case AttributedType::attr_pascal:
case AttributedType::attr_swiftcall:
case AttributedType::attr_vectorcall:
@@ -3049,6 +3102,7 @@ bool AttributedType::isCallingConv() const {
case attr_fastcall:
case attr_stdcall:
case attr_thiscall:
+ case attr_regcall:
case attr_swiftcall:
case attr_vectorcall:
case attr_pascal:
@@ -3212,6 +3266,20 @@ void ObjCObjectTypeImpl::Profile(llvm::FoldingSetNodeID &ID) {
isKindOfTypeAsWritten());
}
+void ObjCTypeParamType::Profile(llvm::FoldingSetNodeID &ID,
+ const ObjCTypeParamDecl *OTPDecl,
+ ArrayRef<ObjCProtocolDecl *> protocols) {
+ ID.AddPointer(OTPDecl);
+ ID.AddInteger(protocols.size());
+ for (auto proto : protocols)
+ ID.AddPointer(proto);
+}
+
+void ObjCTypeParamType::Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getDecl(),
+ llvm::makeArrayRef(qual_begin(), getNumProtocols()));
+}
+
namespace {
/// \brief The cached properties of a type.
@@ -3687,10 +3755,18 @@ bool Type::isObjCARCImplicitlyUnretainedType() const {
}
bool Type::isObjCNSObjectType() const {
- if (const TypedefType *typedefType = dyn_cast<TypedefType>(this))
- return typedefType->getDecl()->hasAttr<ObjCNSObjectAttr>();
- return false;
+ const Type *cur = this;
+ while (true) {
+ if (const TypedefType *typedefType = dyn_cast<TypedefType>(cur))
+ return typedefType->getDecl()->hasAttr<ObjCNSObjectAttr>();
+
+ // Single-step desugar until we run out of sugar.
+ QualType next = cur->getLocallyUnqualifiedSingleStepDesugaredType();
+ if (next.getTypePtr() == cur) return false;
+ cur = next.getTypePtr();
+ }
}
+
bool Type::isObjCIndependentClassType() const {
if (const TypedefType *typedefType = dyn_cast<TypedefType>(this))
return typedefType->getDecl()->hasAttr<ObjCIndependentClassAttr>();
diff --git a/lib/AST/TypeLoc.cpp b/lib/AST/TypeLoc.cpp
index 78947d18f953..7242858f21e6 100644
--- a/lib/AST/TypeLoc.cpp
+++ b/lib/AST/TypeLoc.cpp
@@ -16,10 +16,9 @@
#include "clang/AST/Expr.h"
#include "clang/AST/TypeLocVisitor.h"
#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/raw_ostream.h"
using namespace clang;
-static const unsigned TypeLocMaxDataAlign = llvm::alignOf<void *>();
+static const unsigned TypeLocMaxDataAlign = alignof(void *);
//===----------------------------------------------------------------------===//
// TypeLoc Implementation
@@ -211,7 +210,7 @@ SourceLocation TypeLoc::getEndLoc() const {
switch (Cur.getTypeLocClass()) {
default:
if (!Last)
- Last = Cur;
+ Last = Cur;
return Last.getLocalSourceRange().getEnd();
case Paren:
case ConstantArray:
@@ -389,6 +388,17 @@ TypeLoc TypeLoc::findExplicitQualifierLoc() const {
return TypeLoc();
}
+void ObjCTypeParamTypeLoc::initializeLocal(ASTContext &Context,
+ SourceLocation Loc) {
+ setNameLoc(Loc);
+ if (!getNumProtocols()) return;
+
+ setProtocolLAngleLoc(Loc);
+ setProtocolRAngleLoc(Loc);
+ for (unsigned i = 0, e = getNumProtocols(); i != e; ++i)
+ setProtocolLoc(i, Loc);
+}
+
void ObjCObjectTypeLoc::initializeLocal(ASTContext &Context,
SourceLocation Loc) {
setHasBaseTypeAsWritten(true);
diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp
index 065a2db09141..cccc90876321 100644
--- a/lib/AST/TypePrinter.cpp
+++ b/lib/AST/TypePrinter.cpp
@@ -194,6 +194,7 @@ bool TypePrinter::canPrefixQualifiers(const Type *T,
case Type::DependentName:
case Type::DependentTemplateSpecialization:
case Type::ObjCObject:
+ case Type::ObjCTypeParam:
case Type::ObjCInterface:
case Type::Atomic:
case Type::Pipe:
@@ -724,6 +725,9 @@ void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T,
case CC_X86_64SysV:
OS << " __attribute__((sysv_abi))";
break;
+ case CC_X86RegCall:
+ OS << " __attribute__((regcall))";
+ break;
case CC_SpirFunction:
case CC_OpenCLKernel:
// Do nothing. These CCs are not available as attributes.
@@ -897,6 +901,10 @@ void TypePrinter::printAtomicAfter(const AtomicType *T, raw_ostream &OS) { }
void TypePrinter::printPipeBefore(const PipeType *T, raw_ostream &OS) {
IncludeStrongLifetimeRAII Strong(Policy);
+ if (T->isReadOnly())
+ OS << "read_only ";
+ else
+ OS << "write_only ";
OS << "pipe ";
print(T->getElementType(), OS, StringRef());
spaceBeforePlaceHolder(OS);
@@ -1338,6 +1346,7 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
case AttributedType::attr_pascal: OS << "pascal"; break;
case AttributedType::attr_ms_abi: OS << "ms_abi"; break;
case AttributedType::attr_sysv_abi: OS << "sysv_abi"; break;
+ case AttributedType::attr_regcall: OS << "regcall"; break;
case AttributedType::attr_pcs:
case AttributedType::attr_pcs_vfp: {
OS << "pcs(";
@@ -1368,6 +1377,28 @@ void TypePrinter::printObjCInterfaceBefore(const ObjCInterfaceType *T,
void TypePrinter::printObjCInterfaceAfter(const ObjCInterfaceType *T,
raw_ostream &OS) { }
+void TypePrinter::printObjCTypeParamBefore(const ObjCTypeParamType *T,
+ raw_ostream &OS) {
+ OS << T->getDecl()->getName();
+ 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::printObjCTypeParamAfter(const ObjCTypeParamType *T,
+ raw_ostream &OS) { }
+
void TypePrinter::printObjCObjectBefore(const ObjCObjectType *T,
raw_ostream &OS) {
if (T->qual_empty() && T->isUnspecializedAsWritten() &&
diff --git a/lib/AST/VTableBuilder.cpp b/lib/AST/VTableBuilder.cpp
index 640fbf47aeab..e60ae33f2e5c 100644
--- a/lib/AST/VTableBuilder.cpp
+++ b/lib/AST/VTableBuilder.cpp
@@ -777,9 +777,8 @@ public:
typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits>
VBaseOffsetOffsetsMapTy;
-
- typedef llvm::DenseMap<BaseSubobject, uint64_t>
- AddressPointsMapTy;
+
+ typedef VTableLayout::AddressPointsMapTy AddressPointsMapTy;
typedef llvm::DenseMap<GlobalDecl, int64_t> MethodVTableIndicesTy;
@@ -817,7 +816,7 @@ private:
/// VBaseOffsetOffsets - Contains the offsets of the virtual base offsets for
/// the most derived class.
VBaseOffsetOffsetsMapTy VBaseOffsetOffsets;
-
+
/// Components - The components of the vtable being built.
SmallVector<VTableComponent, 64> Components;
@@ -982,6 +981,10 @@ private:
}
public:
+ /// Component indices of the first component of each of the vtables in the
+ /// vtable group.
+ SmallVector<size_t, 4> VTableIndices;
+
ItaniumVTableBuilder(ItaniumVTableContext &VTables,
const CXXRecordDecl *MostDerivedClass,
CharUnits MostDerivedClassOffset,
@@ -1028,20 +1031,8 @@ public:
return MethodVTableIndices.end();
}
- /// getNumVTableComponents - Return the number of components in the vtable
- /// currently built.
- uint64_t getNumVTableComponents() const {
- return Components.size();
- }
+ ArrayRef<VTableComponent> vtable_components() const { return Components; }
- const VTableComponent *vtable_component_begin() const {
- return Components.begin();
- }
-
- const VTableComponent *vtable_component_end() const {
- return Components.end();
- }
-
AddressPointsMapTy::const_iterator address_points_begin() const {
return AddressPoints.begin();
}
@@ -1639,6 +1630,9 @@ void ItaniumVTableBuilder::LayoutPrimaryAndSecondaryVTables(
bool BaseIsVirtualInLayoutClass, CharUnits OffsetInLayoutClass) {
assert(Base.getBase()->isDynamicClass() && "class does not have a vtable!");
+ unsigned VTableIndex = Components.size();
+ VTableIndices.push_back(VTableIndex);
+
// Add vcall and vbase offsets for this vtable.
VCallAndVBaseOffsetBuilder Builder(MostDerivedClass, LayoutClass, &Overriders,
Base, BaseIsVirtualInLayoutClass,
@@ -1695,9 +1689,11 @@ void ItaniumVTableBuilder::LayoutPrimaryAndSecondaryVTables(
// Add all address points.
while (true) {
- AddressPoints.insert(std::make_pair(
- BaseSubobject(RD, OffsetInLayoutClass),
- AddressPoint));
+ AddressPoints.insert(
+ std::make_pair(BaseSubobject(RD, OffsetInLayoutClass),
+ VTableLayout::AddressPointLocation{
+ unsigned(VTableIndices.size() - 1),
+ unsigned(AddressPoint - VTableIndex)}));
const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
@@ -1901,7 +1897,8 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) {
std::multimap<uint64_t, BaseSubobject> AddressPointsByIndex;
for (const auto &AP : AddressPoints) {
const BaseSubobject &Base = AP.first;
- uint64_t Index = AP.second;
+ uint64_t Index =
+ VTableIndices[AP.second.VTableIndex] + AP.second.AddressPointIndex;
AddressPointsByIndex.insert(std::make_pair(Index, Base));
}
@@ -2203,30 +2200,24 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) {
}
}
-VTableLayout::VTableLayout(uint64_t NumVTableComponents,
- const VTableComponent *VTableComponents,
- uint64_t NumVTableThunks,
- const VTableThunkTy *VTableThunks,
- const AddressPointsMapTy &AddressPoints,
- bool IsMicrosoftABI)
- : NumVTableComponents(NumVTableComponents),
- VTableComponents(new VTableComponent[NumVTableComponents]),
- NumVTableThunks(NumVTableThunks),
- VTableThunks(new VTableThunkTy[NumVTableThunks]),
- AddressPoints(AddressPoints),
- IsMicrosoftABI(IsMicrosoftABI) {
- std::copy(VTableComponents, VTableComponents+NumVTableComponents,
- this->VTableComponents.get());
- std::copy(VTableThunks, VTableThunks+NumVTableThunks,
- this->VTableThunks.get());
- std::sort(this->VTableThunks.get(),
- this->VTableThunks.get() + NumVTableThunks,
+VTableLayout::VTableLayout(ArrayRef<size_t> VTableIndices,
+ ArrayRef<VTableComponent> VTableComponents,
+ ArrayRef<VTableThunkTy> VTableThunks,
+ const AddressPointsMapTy &AddressPoints)
+ : VTableComponents(VTableComponents), VTableThunks(VTableThunks),
+ AddressPoints(AddressPoints) {
+ if (VTableIndices.size() <= 1)
+ assert(VTableIndices.size() == 1 && VTableIndices[0] == 0);
+ else
+ this->VTableIndices = OwningArrayRef<size_t>(VTableIndices);
+
+ std::sort(this->VTableThunks.begin(), this->VTableThunks.end(),
[](const VTableLayout::VTableThunkTy &LHS,
const VTableLayout::VTableThunkTy &RHS) {
- assert((LHS.first != RHS.first || LHS.second == RHS.second) &&
- "Different thunks should have unique indices!");
- return LHS.first < RHS.first;
- });
+ assert((LHS.first != RHS.first || LHS.second == RHS.second) &&
+ "Different thunks should have unique indices!");
+ return LHS.first < RHS.first;
+ });
}
VTableLayout::~VTableLayout() { }
@@ -2234,9 +2225,7 @@ VTableLayout::~VTableLayout() { }
ItaniumVTableContext::ItaniumVTableContext(ASTContext &Context)
: VTableContextBase(/*MS=*/false) {}
-ItaniumVTableContext::~ItaniumVTableContext() {
- llvm::DeleteContainerSeconds(VTableLayouts);
-}
+ItaniumVTableContext::~ItaniumVTableContext() {}
uint64_t ItaniumVTableContext::getMethodVTableIndex(GlobalDecl GD) {
MethodVTableIndicesTy::iterator I = MethodVTableIndices.find(GD);
@@ -2280,21 +2269,19 @@ ItaniumVTableContext::getVirtualBaseOffsetOffset(const CXXRecordDecl *RD,
return I->second;
}
-static VTableLayout *CreateVTableLayout(const ItaniumVTableBuilder &Builder) {
+static std::unique_ptr<VTableLayout>
+CreateVTableLayout(const ItaniumVTableBuilder &Builder) {
SmallVector<VTableLayout::VTableThunkTy, 1>
VTableThunks(Builder.vtable_thunks_begin(), Builder.vtable_thunks_end());
- return new VTableLayout(Builder.getNumVTableComponents(),
- Builder.vtable_component_begin(),
- VTableThunks.size(),
- VTableThunks.data(),
- Builder.getAddressPoints(),
- /*IsMicrosoftABI=*/false);
+ return llvm::make_unique<VTableLayout>(
+ Builder.VTableIndices, Builder.vtable_components(), VTableThunks,
+ Builder.getAddressPoints());
}
void
ItaniumVTableContext::computeVTableRelatedInformation(const CXXRecordDecl *RD) {
- const VTableLayout *&Entry = VTableLayouts[RD];
+ std::unique_ptr<const VTableLayout> &Entry = VTableLayouts[RD];
// Check if we've computed this information before.
if (Entry)
@@ -2330,7 +2317,8 @@ ItaniumVTableContext::computeVTableRelatedInformation(const CXXRecordDecl *RD) {
}
}
-VTableLayout *ItaniumVTableContext::createConstructionVTableLayout(
+std::unique_ptr<VTableLayout>
+ItaniumVTableContext::createConstructionVTableLayout(
const CXXRecordDecl *MostDerivedClass, CharUnits MostDerivedClassOffset,
bool MostDerivedClassIsVirtual, const CXXRecordDecl *LayoutClass) {
ItaniumVTableBuilder Builder(*this, MostDerivedClass, MostDerivedClassOffset,
@@ -2538,12 +2526,12 @@ private:
public:
VFTableBuilder(MicrosoftVTableContext &VTables,
- const CXXRecordDecl *MostDerivedClass, const VPtrInfo *Which)
+ const CXXRecordDecl *MostDerivedClass, const VPtrInfo &Which)
: VTables(VTables),
Context(MostDerivedClass->getASTContext()),
MostDerivedClass(MostDerivedClass),
MostDerivedClassLayout(Context.getASTRecordLayout(MostDerivedClass)),
- WhichVFPtr(*Which),
+ WhichVFPtr(Which),
Overriders(MostDerivedClass, CharUnits(), MostDerivedClass) {
// Provide the RTTI component if RTTIData is enabled. If the vftable would
// be available externally, we should not provide the RTTI componenent. It
@@ -2570,15 +2558,7 @@ public:
MethodVFTableLocations.end());
}
- uint64_t getNumVTableComponents() const { return Components.size(); }
-
- const VTableComponent *vtable_component_begin() const {
- return Components.begin();
- }
-
- const VTableComponent *vtable_component_end() const {
- return Components.end();
- }
+ ArrayRef<VTableComponent> vtable_components() const { return Components; }
VTableThunksMapTy::const_iterator vtable_thunks_begin() const {
return VTableThunks.begin();
@@ -2931,8 +2911,8 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth,
// class.
const CXXRecordDecl *NextBase = nullptr, *NextLastVBase = LastVBase;
CharUnits NextBaseOffset;
- if (BaseDepth < WhichVFPtr.PathToBaseWithVPtr.size()) {
- NextBase = WhichVFPtr.PathToBaseWithVPtr[BaseDepth];
+ if (BaseDepth < WhichVFPtr.PathToIntroducingObject.size()) {
+ NextBase = WhichVFPtr.PathToIntroducingObject[BaseDepth];
if (isDirectVBase(NextBase, RD)) {
NextLastVBase = NextBase;
NextBaseOffset = MostDerivedClassLayout.getVBaseClassOffset(NextBase);
@@ -3124,7 +3104,7 @@ static void dumpMicrosoftThunkAdjustment(const ThunkInfo &TI, raw_ostream &Out,
void VFTableBuilder::dumpLayout(raw_ostream &Out) {
Out << "VFTable for ";
- PrintBasePath(WhichVFPtr.PathToBaseWithVPtr, Out);
+ PrintBasePath(WhichVFPtr.PathToIntroducingObject, Out);
Out << "'";
MostDerivedClass->printQualifiedName(Out);
Out << "' (" << Components.size()
@@ -3278,7 +3258,7 @@ void MicrosoftVTableContext::computeVTablePaths(bool ForVBTables,
// Base case: this subobject has its own vptr.
if (ForVBTables ? Layout.hasOwnVBPtr() : Layout.hasOwnVFPtr())
- Paths.push_back(new VPtrInfo(RD));
+ Paths.push_back(llvm::make_unique<VPtrInfo>(RD));
// Recursive case: get all the vbtables from our bases and remove anything
// that shares a virtual base.
@@ -3294,14 +3274,14 @@ void MicrosoftVTableContext::computeVTablePaths(bool ForVBTables,
const VPtrInfoVector &BasePaths =
ForVBTables ? enumerateVBTables(Base) : getVFPtrOffsets(Base);
- for (VPtrInfo *BaseInfo : BasePaths) {
+ for (const std::unique_ptr<VPtrInfo> &BaseInfo : BasePaths) {
// Don't include the path if it goes through a virtual base that we've
// already included.
if (setsIntersect(VBasesSeen, BaseInfo->ContainingVBases))
continue;
// Copy the path and adjust it as necessary.
- VPtrInfo *P = new VPtrInfo(*BaseInfo);
+ auto P = llvm::make_unique<VPtrInfo>(*BaseInfo);
// We mangle Base into the path if the path would've been ambiguous and it
// wasn't already extended with Base.
@@ -3311,10 +3291,10 @@ void MicrosoftVTableContext::computeVTablePaths(bool ForVBTables,
// Keep track of which vtable the derived class is going to extend with
// new methods or bases. We append to either the vftable of our primary
// base, or the first non-virtual base that has a vbtable.
- if (P->ReusingBase == Base &&
+ if (P->ObjectWithVPtr == Base &&
Base == (ForVBTables ? Layout.getBaseSharingVBPtr()
: Layout.getPrimaryBase()))
- P->ReusingBase = RD;
+ P->ObjectWithVPtr = RD;
// Keep track of the full adjustment from the MDC to this vtable. The
// adjustment is captured by an optional vbase and a non-virtual offset.
@@ -3328,7 +3308,7 @@ void MicrosoftVTableContext::computeVTablePaths(bool ForVBTables,
if (const CXXRecordDecl *VB = P->getVBaseWithVPtr())
P->FullOffsetInMDC += Layout.getVBaseClassOffset(VB);
- Paths.push_back(P);
+ Paths.push_back(std::move(P));
}
if (B.isVirtual())
@@ -3347,10 +3327,10 @@ void MicrosoftVTableContext::computeVTablePaths(bool ForVBTables,
Changed = rebucketPaths(Paths);
}
-static bool extendPath(VPtrInfo *P) {
- if (P->NextBaseToMangle) {
- P->MangledPath.push_back(P->NextBaseToMangle);
- P->NextBaseToMangle = nullptr;// Prevent the path from being extended twice.
+static bool extendPath(VPtrInfo &P) {
+ if (P.NextBaseToMangle) {
+ P.MangledPath.push_back(P.NextBaseToMangle);
+ P.NextBaseToMangle = nullptr;// Prevent the path from being extended twice.
return true;
}
return false;
@@ -3363,10 +3343,13 @@ static bool rebucketPaths(VPtrInfoVector &Paths) {
// sorted vector to implement a multiset to form the buckets. Note that the
// ordering is based on pointers, but it doesn't change our output order. The
// current algorithm is designed to match MSVC 2012's names.
- VPtrInfoVector PathsSorted(Paths);
+ llvm::SmallVector<std::reference_wrapper<VPtrInfo>, 2> PathsSorted;
+ PathsSorted.reserve(Paths.size());
+ for (auto& P : Paths)
+ PathsSorted.push_back(*P);
std::sort(PathsSorted.begin(), PathsSorted.end(),
- [](const VPtrInfo *LHS, const VPtrInfo *RHS) {
- return LHS->MangledPath < RHS->MangledPath;
+ [](const VPtrInfo &LHS, const VPtrInfo &RHS) {
+ return LHS.MangledPath < RHS.MangledPath;
});
bool Changed = false;
for (size_t I = 0, E = PathsSorted.size(); I != E;) {
@@ -3374,8 +3357,9 @@ static bool rebucketPaths(VPtrInfoVector &Paths) {
size_t BucketStart = I;
do {
++I;
- } while (I != E && PathsSorted[BucketStart]->MangledPath ==
- PathsSorted[I]->MangledPath);
+ } while (I != E &&
+ PathsSorted[BucketStart].get().MangledPath ==
+ PathsSorted[I].get().MangledPath);
// If this bucket has multiple paths, extend them all.
if (I - BucketStart > 1) {
@@ -3387,13 +3371,7 @@ static bool rebucketPaths(VPtrInfoVector &Paths) {
return Changed;
}
-MicrosoftVTableContext::~MicrosoftVTableContext() {
- for (auto &P : VFPtrLocations)
- llvm::DeleteContainerPointers(*P.second);
- llvm::DeleteContainerSeconds(VFPtrLocations);
- llvm::DeleteContainerSeconds(VFTableLayouts);
- llvm::DeleteContainerSeconds(VBaseInfo);
-}
+MicrosoftVTableContext::~MicrosoftVTableContext() {}
namespace {
typedef llvm::SetVector<BaseSubobject, std::vector<BaseSubobject>,
@@ -3401,14 +3379,14 @@ typedef llvm::SetVector<BaseSubobject, std::vector<BaseSubobject>,
}
// This recursive function finds all paths from a subobject centered at
-// (RD, Offset) to the subobject located at BaseWithVPtr.
+// (RD, Offset) to the subobject located at IntroducingObject.
static void findPathsToSubobject(ASTContext &Context,
const ASTRecordLayout &MostDerivedLayout,
const CXXRecordDecl *RD, CharUnits Offset,
- BaseSubobject BaseWithVPtr,
+ BaseSubobject IntroducingObject,
FullPathTy &FullPath,
std::list<FullPathTy> &Paths) {
- if (BaseSubobject(RD, Offset) == BaseWithVPtr) {
+ if (BaseSubobject(RD, Offset) == IntroducingObject) {
Paths.push_back(FullPath);
return;
}
@@ -3422,7 +3400,7 @@ static void findPathsToSubobject(ASTContext &Context,
: Offset + Layout.getBaseClassOffset(Base);
FullPath.insert(BaseSubobject(Base, NewOffset));
findPathsToSubobject(Context, MostDerivedLayout, Base, NewOffset,
- BaseWithVPtr, FullPath, Paths);
+ IntroducingObject, FullPath, Paths);
FullPath.pop_back();
}
}
@@ -3477,7 +3455,8 @@ static CharUnits getOffsetOfFullPath(ASTContext &Context,
// 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,
+ const CXXRecordDecl *RD,
+ const VPtrInfo &Info,
std::list<FullPathTy> &FullPaths) {
// Handle some easy cases first.
if (FullPaths.empty())
@@ -3497,7 +3476,7 @@ static const FullPathTy *selectBestPath(ASTContext &Context,
CharUnits BaseOffset =
getOffsetOfFullPath(Context, TopLevelRD, SpecificPath);
FinalOverriders Overriders(TopLevelRD, CharUnits::Zero(), TopLevelRD);
- for (const CXXMethodDecl *MD : Info->BaseWithVPtr->methods()) {
+ for (const CXXMethodDecl *MD : Info.IntroducingObject->methods()) {
if (!MD->isVirtual())
continue;
FinalOverriders::OverriderInfo OI =
@@ -3552,18 +3531,18 @@ static void computeFullPathsForVFTables(ASTContext &Context,
const ASTRecordLayout &MostDerivedLayout = Context.getASTRecordLayout(RD);
FullPathTy FullPath;
std::list<FullPathTy> FullPaths;
- for (VPtrInfo *Info : Paths) {
+ for (const std::unique_ptr<VPtrInfo>& Info : Paths) {
findPathsToSubobject(
Context, MostDerivedLayout, RD, CharUnits::Zero(),
- BaseSubobject(Info->BaseWithVPtr, Info->FullOffsetInMDC), FullPath,
+ BaseSubobject(Info->IntroducingObject, Info->FullOffsetInMDC), FullPath,
FullPaths);
FullPath.clear();
removeRedundantPaths(FullPaths);
- Info->PathToBaseWithVPtr.clear();
+ Info->PathToIntroducingObject.clear();
if (const FullPathTy *BestPath =
- selectBestPath(Context, RD, Info, FullPaths))
+ selectBestPath(Context, RD, *Info, FullPaths))
for (const BaseSubobject &BSO : *BestPath)
- Info->PathToBaseWithVPtr.push_back(BSO.getBase());
+ Info->PathToIntroducingObject.push_back(BSO.getBase());
FullPaths.clear();
}
}
@@ -3578,22 +3557,24 @@ void MicrosoftVTableContext::computeVTableRelatedInformation(
const VTableLayout::AddressPointsMapTy EmptyAddressPointsMap;
- VPtrInfoVector *VFPtrs = new VPtrInfoVector();
- computeVTablePaths(/*ForVBTables=*/false, RD, *VFPtrs);
- computeFullPathsForVFTables(Context, RD, *VFPtrs);
- VFPtrLocations[RD] = VFPtrs;
+ {
+ VPtrInfoVector VFPtrs;
+ computeVTablePaths(/*ForVBTables=*/false, RD, VFPtrs);
+ computeFullPathsForVFTables(Context, RD, VFPtrs);
+ VFPtrLocations[RD] = std::move(VFPtrs);
+ }
MethodVFTableLocationsTy NewMethodLocations;
- for (const VPtrInfo *VFPtr : *VFPtrs) {
- VFTableBuilder Builder(*this, RD, VFPtr);
+ for (const std::unique_ptr<VPtrInfo> &VFPtr : VFPtrLocations[RD]) {
+ VFTableBuilder Builder(*this, RD, *VFPtr);
VFTableIdTy id(RD, VFPtr->FullOffsetInMDC);
assert(VFTableLayouts.count(id) == 0);
SmallVector<VTableLayout::VTableThunkTy, 1> VTableThunks(
Builder.vtable_thunks_begin(), Builder.vtable_thunks_end());
- VFTableLayouts[id] = new VTableLayout(
- Builder.getNumVTableComponents(), Builder.vtable_component_begin(),
- VTableThunks.size(), VTableThunks.data(), EmptyAddressPointsMap, true);
+ VFTableLayouts[id] = llvm::make_unique<VTableLayout>(
+ ArrayRef<size_t>{0}, Builder.vtable_components(), VTableThunks,
+ EmptyAddressPointsMap);
Thunks.insert(Builder.thunks_begin(), Builder.thunks_end());
for (const auto &Loc : Builder.vtable_locations()) {
@@ -3670,17 +3651,18 @@ void MicrosoftVTableContext::dumpMethodLocations(
Out.flush();
}
-const VirtualBaseInfo *MicrosoftVTableContext::computeVBTableRelatedInformation(
+const VirtualBaseInfo &MicrosoftVTableContext::computeVBTableRelatedInformation(
const CXXRecordDecl *RD) {
VirtualBaseInfo *VBI;
{
// Get or create a VBI for RD. Don't hold a reference to the DenseMap cell,
// as it may be modified and rehashed under us.
- VirtualBaseInfo *&Entry = VBaseInfo[RD];
+ std::unique_ptr<VirtualBaseInfo> &Entry = VBaseInfo[RD];
if (Entry)
- return Entry;
- Entry = VBI = new VirtualBaseInfo();
+ return *Entry;
+ Entry = llvm::make_unique<VirtualBaseInfo>();
+ VBI = Entry.get();
}
computeVTablePaths(/*ForVBTables=*/true, RD, VBI->VBPtrPaths);
@@ -3690,10 +3672,10 @@ const VirtualBaseInfo *MicrosoftVTableContext::computeVBTableRelatedInformation(
if (const CXXRecordDecl *VBPtrBase = Layout.getBaseSharingVBPtr()) {
// If the Derived class shares the vbptr with a non-virtual base, the shared
// virtual bases come first so that the layout is the same.
- const VirtualBaseInfo *BaseInfo =
+ const VirtualBaseInfo &BaseInfo =
computeVBTableRelatedInformation(VBPtrBase);
- VBI->VBTableIndices.insert(BaseInfo->VBTableIndices.begin(),
- BaseInfo->VBTableIndices.end());
+ VBI->VBTableIndices.insert(BaseInfo.VBTableIndices.begin(),
+ BaseInfo.VBTableIndices.end());
}
// New vbases are added to the end of the vbtable.
@@ -3705,19 +3687,19 @@ const VirtualBaseInfo *MicrosoftVTableContext::computeVBTableRelatedInformation(
VBI->VBTableIndices[CurVBase] = VBTableIndex++;
}
- return VBI;
+ return *VBI;
}
unsigned MicrosoftVTableContext::getVBTableIndex(const CXXRecordDecl *Derived,
const CXXRecordDecl *VBase) {
- const VirtualBaseInfo *VBInfo = computeVBTableRelatedInformation(Derived);
- assert(VBInfo->VBTableIndices.count(VBase));
- return VBInfo->VBTableIndices.find(VBase)->second;
+ const VirtualBaseInfo &VBInfo = computeVBTableRelatedInformation(Derived);
+ assert(VBInfo.VBTableIndices.count(VBase));
+ return VBInfo.VBTableIndices.find(VBase)->second;
}
const VPtrInfoVector &
MicrosoftVTableContext::enumerateVBTables(const CXXRecordDecl *RD) {
- return computeVBTableRelatedInformation(RD)->VBPtrPaths;
+ return computeVBTableRelatedInformation(RD).VBPtrPaths;
}
const VPtrInfoVector &
@@ -3725,7 +3707,7 @@ MicrosoftVTableContext::getVFPtrOffsets(const CXXRecordDecl *RD) {
computeVTableRelatedInformation(RD);
assert(VFPtrLocations.count(RD) && "Couldn't find vfptr locations");
- return *VFPtrLocations[RD];
+ return VFPtrLocations[RD];
}
const VTableLayout &
diff --git a/lib/ASTMatchers/ASTMatchFinder.cpp b/lib/ASTMatchers/ASTMatchFinder.cpp
index 19e5743ea1cb..49b15ee68500 100644
--- a/lib/ASTMatchers/ASTMatchFinder.cpp
+++ b/lib/ASTMatchers/ASTMatchFinder.cpp
@@ -126,6 +126,8 @@ public:
traverse(*Q);
else if (const TypeLoc *T = DynNode.get<TypeLoc>())
traverse(*T);
+ else if (const auto *C = DynNode.get<CXXCtorInitializer>())
+ traverse(*C);
// FIXME: Add other base types after adding tests.
// It's OK to always overwrite the bound nodes, as if there was
@@ -194,6 +196,12 @@ public:
return false;
return traverse(NNS);
}
+ bool TraverseConstructorInitializer(CXXCtorInitializer *CtorInit) {
+ if (!CtorInit)
+ return true;
+ ScopedIncrement ScopedDepth(&CurrentDepth);
+ return traverse(*CtorInit);
+ }
bool shouldVisitTemplateInstantiations() const { return true; }
bool shouldVisitImplicitCode() const { return true; }
@@ -235,6 +243,10 @@ private:
bool baseTraverse(NestedNameSpecifierLoc NNS) {
return VisitorBase::TraverseNestedNameSpecifierLoc(NNS);
}
+ bool baseTraverse(const CXXCtorInitializer &CtorInit) {
+ return VisitorBase::TraverseConstructorInitializer(
+ const_cast<CXXCtorInitializer *>(&CtorInit));
+ }
// Sets 'Matched' to true if 'Matcher' matches 'Node' and:
// 0 < CurrentDepth <= MaxDepth.
@@ -371,6 +383,7 @@ public:
bool TraverseTypeLoc(TypeLoc TypeNode);
bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS);
bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS);
+ bool TraverseConstructorInitializer(CXXCtorInitializer *CtorInit);
// Matches children or descendants of 'Node' with 'BaseMatcher'.
bool memoizedMatchesRecursively(const ast_type_traits::DynTypedNode &Node,
@@ -472,6 +485,8 @@ public:
match(*N);
} else if (auto *N = Node.get<TypeLoc>()) {
match(*N);
+ } else if (auto *N = Node.get<CXXCtorInitializer>()) {
+ match(*N);
}
}
@@ -593,6 +608,9 @@ private:
void matchDispatch(const NestedNameSpecifierLoc *Node) {
matchWithoutFilter(*Node, Matchers->NestedNameSpecifierLoc);
}
+ void matchDispatch(const CXXCtorInitializer *Node) {
+ matchWithoutFilter(*Node, Matchers->CtorInit);
+ }
void matchDispatch(const void *) { /* Do nothing. */ }
/// @}
@@ -864,6 +882,17 @@ bool MatchASTVisitor::TraverseNestedNameSpecifierLoc(
RecursiveASTVisitor<MatchASTVisitor>::TraverseNestedNameSpecifierLoc(NNS);
}
+bool MatchASTVisitor::TraverseConstructorInitializer(
+ CXXCtorInitializer *CtorInit) {
+ if (!CtorInit)
+ return true;
+
+ match(*CtorInit);
+
+ return RecursiveASTVisitor<MatchASTVisitor>::TraverseConstructorInitializer(
+ CtorInit);
+}
+
class MatchASTConsumer : public ASTConsumer {
public:
MatchASTConsumer(MatchFinder *Finder,
@@ -934,6 +963,12 @@ void MatchFinder::addMatcher(const TypeLocMatcher &NodeMatch,
Matchers.AllCallbacks.insert(Action);
}
+void MatchFinder::addMatcher(const CXXCtorInitializerMatcher &NodeMatch,
+ MatchCallback *Action) {
+ Matchers.CtorInit.emplace_back(NodeMatch, Action);
+ Matchers.AllCallbacks.insert(Action);
+}
+
bool MatchFinder::addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch,
MatchCallback *Action) {
if (NodeMatch.canConvertTo<Decl>()) {
@@ -954,6 +989,9 @@ bool MatchFinder::addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch,
} else if (NodeMatch.canConvertTo<TypeLoc>()) {
addMatcher(NodeMatch.convertTo<TypeLoc>(), Action);
return true;
+ } else if (NodeMatch.canConvertTo<CXXCtorInitializer>()) {
+ addMatcher(NodeMatch.convertTo<CXXCtorInitializer>(), Action);
+ return true;
}
return false;
}
diff --git a/lib/ASTMatchers/ASTMatchersInternal.cpp b/lib/ASTMatchers/ASTMatchersInternal.cpp
index 107052ef1ded..f0bfbf9e32d8 100644
--- a/lib/ASTMatchers/ASTMatchersInternal.cpp
+++ b/lib/ASTMatchers/ASTMatchersInternal.cpp
@@ -72,10 +72,10 @@ private:
};
class IdDynMatcher : public DynMatcherInterface {
- public:
+public:
IdDynMatcher(StringRef ID,
- const IntrusiveRefCntPtr<DynMatcherInterface> &InnerMatcher)
- : ID(ID), InnerMatcher(InnerMatcher) {}
+ IntrusiveRefCntPtr<DynMatcherInterface> InnerMatcher)
+ : ID(ID), InnerMatcher(std::move(InnerMatcher)) {}
bool dynMatches(const ast_type_traits::DynTypedNode &DynNode,
ASTMatchFinder *Finder,
@@ -85,7 +85,7 @@ class IdDynMatcher : public DynMatcherInterface {
return Result;
}
- private:
+private:
const std::string ID;
const IntrusiveRefCntPtr<DynMatcherInterface> InnerMatcher;
};
@@ -210,8 +210,9 @@ bool DynTypedMatcher::matchesNoKindCheck(
llvm::Optional<DynTypedMatcher> DynTypedMatcher::tryBind(StringRef ID) const {
if (!AllowBind) return llvm::None;
auto Result = *this;
- Result.Implementation = new IdDynMatcher(ID, Result.Implementation);
- return Result;
+ Result.Implementation =
+ new IdDynMatcher(ID, std::move(Result.Implementation));
+ return std::move(Result);
}
bool DynTypedMatcher::canConvertTo(ast_type_traits::ASTNodeKind To) const {
diff --git a/lib/ASTMatchers/Dynamic/Marshallers.h b/lib/ASTMatchers/Dynamic/Marshallers.h
index 7b1a30702633..fb6b349a811c 100644
--- a/lib/ASTMatchers/Dynamic/Marshallers.h
+++ b/lib/ASTMatchers/Dynamic/Marshallers.h
@@ -480,8 +480,8 @@ template <template <typename ToArg, typename FromArg> class ArgumentAdapterT,
typename FromTypes, typename ToTypes>
class AdaptativeOverloadCollector {
public:
- AdaptativeOverloadCollector(StringRef Name,
- std::vector<MatcherDescriptor *> &Out)
+ AdaptativeOverloadCollector(
+ StringRef Name, std::vector<std::unique_ptr<MatcherDescriptor>> &Out)
: Name(Name), Out(Out) {
collect(FromTypes());
}
@@ -499,7 +499,7 @@ private:
inline void collect(FromTypeList);
StringRef Name;
- std::vector<MatcherDescriptor *> &Out;
+ std::vector<std::unique_ptr<MatcherDescriptor>> &Out;
};
/// \brief MatcherDescriptor that wraps multiple "overloads" of the same
@@ -509,8 +509,10 @@ private:
/// more than one overloads match the arguments.
class OverloadedMatcherDescriptor : public MatcherDescriptor {
public:
- OverloadedMatcherDescriptor(ArrayRef<MatcherDescriptor *> Callbacks)
- : Overloads(Callbacks.begin(), Callbacks.end()) {}
+ OverloadedMatcherDescriptor(
+ MutableArrayRef<std::unique_ptr<MatcherDescriptor>> Callbacks)
+ : Overloads(std::make_move_iterator(Callbacks.begin()),
+ std::make_move_iterator(Callbacks.end())) {}
~OverloadedMatcherDescriptor() override {}
@@ -641,36 +643,37 @@ private:
/// \brief 0-arg overload
template <typename ReturnType>
-MatcherDescriptor *makeMatcherAutoMarshall(ReturnType (*Func)(),
- StringRef MatcherName) {
+std::unique_ptr<MatcherDescriptor>
+makeMatcherAutoMarshall(ReturnType (*Func)(), StringRef MatcherName) {
std::vector<ast_type_traits::ASTNodeKind> RetTypes;
BuildReturnTypeVector<ReturnType>::build(RetTypes);
- return new FixedArgCountMatcherDescriptor(
+ return llvm::make_unique<FixedArgCountMatcherDescriptor>(
matcherMarshall0<ReturnType>, reinterpret_cast<void (*)()>(Func),
MatcherName, RetTypes, None);
}
/// \brief 1-arg overload
template <typename ReturnType, typename ArgType1>
-MatcherDescriptor *makeMatcherAutoMarshall(ReturnType (*Func)(ArgType1),
- StringRef MatcherName) {
+std::unique_ptr<MatcherDescriptor>
+makeMatcherAutoMarshall(ReturnType (*Func)(ArgType1), StringRef MatcherName) {
std::vector<ast_type_traits::ASTNodeKind> RetTypes;
BuildReturnTypeVector<ReturnType>::build(RetTypes);
ArgKind AK = ArgTypeTraits<ArgType1>::getKind();
- return new FixedArgCountMatcherDescriptor(
+ return llvm::make_unique<FixedArgCountMatcherDescriptor>(
matcherMarshall1<ReturnType, ArgType1>,
reinterpret_cast<void (*)()>(Func), MatcherName, RetTypes, AK);
}
/// \brief 2-arg overload
template <typename ReturnType, typename ArgType1, typename ArgType2>
-MatcherDescriptor *makeMatcherAutoMarshall(ReturnType (*Func)(ArgType1, ArgType2),
- StringRef MatcherName) {
+std::unique_ptr<MatcherDescriptor>
+makeMatcherAutoMarshall(ReturnType (*Func)(ArgType1, ArgType2),
+ StringRef MatcherName) {
std::vector<ast_type_traits::ASTNodeKind> RetTypes;
BuildReturnTypeVector<ReturnType>::build(RetTypes);
ArgKind AKs[] = { ArgTypeTraits<ArgType1>::getKind(),
ArgTypeTraits<ArgType2>::getKind() };
- return new FixedArgCountMatcherDescriptor(
+ return llvm::make_unique<FixedArgCountMatcherDescriptor>(
matcherMarshall2<ReturnType, ArgType1, ArgType2>,
reinterpret_cast<void (*)()>(Func), MatcherName, RetTypes, AKs);
}
@@ -678,10 +681,10 @@ MatcherDescriptor *makeMatcherAutoMarshall(ReturnType (*Func)(ArgType1, ArgType2
/// \brief Variadic overload.
template <typename ResultT, typename ArgT,
ResultT (*Func)(ArrayRef<const ArgT *>)>
-MatcherDescriptor *makeMatcherAutoMarshall(
+std::unique_ptr<MatcherDescriptor> makeMatcherAutoMarshall(
ast_matchers::internal::VariadicFunction<ResultT, ArgT, Func> VarFunc,
StringRef MatcherName) {
- return new VariadicFuncMatcherDescriptor(VarFunc, MatcherName);
+ return llvm::make_unique<VariadicFuncMatcherDescriptor>(VarFunc, MatcherName);
}
/// \brief Overload for VariadicDynCastAllOfMatchers.
@@ -689,24 +692,24 @@ MatcherDescriptor *makeMatcherAutoMarshall(
/// Not strictly necessary, but DynCastAllOfMatcherDescriptor gives us better
/// completion results for that type of matcher.
template <typename BaseT, typename DerivedT>
-MatcherDescriptor *
-makeMatcherAutoMarshall(ast_matchers::internal::VariadicDynCastAllOfMatcher<
- BaseT, DerivedT> VarFunc,
- StringRef MatcherName) {
- return new DynCastAllOfMatcherDescriptor(VarFunc, MatcherName);
+std::unique_ptr<MatcherDescriptor> makeMatcherAutoMarshall(
+ ast_matchers::internal::VariadicDynCastAllOfMatcher<BaseT, DerivedT>
+ VarFunc,
+ StringRef MatcherName) {
+ return llvm::make_unique<DynCastAllOfMatcherDescriptor>(VarFunc, MatcherName);
}
/// \brief Argument adaptative overload.
template <template <typename ToArg, typename FromArg> class ArgumentAdapterT,
typename FromTypes, typename ToTypes>
-MatcherDescriptor *
-makeMatcherAutoMarshall(ast_matchers::internal::ArgumentAdaptingMatcherFunc<
- ArgumentAdapterT, FromTypes, ToTypes>,
- StringRef MatcherName) {
- std::vector<MatcherDescriptor *> Overloads;
+std::unique_ptr<MatcherDescriptor> makeMatcherAutoMarshall(
+ ast_matchers::internal::ArgumentAdaptingMatcherFunc<ArgumentAdapterT,
+ FromTypes, ToTypes>,
+ StringRef MatcherName) {
+ std::vector<std::unique_ptr<MatcherDescriptor>> Overloads;
AdaptativeOverloadCollector<ArgumentAdapterT, FromTypes, ToTypes>(MatcherName,
Overloads);
- return new OverloadedMatcherDescriptor(Overloads);
+ return llvm::make_unique<OverloadedMatcherDescriptor>(Overloads);
}
template <template <typename ToArg, typename FromArg> class ArgumentAdapterT,
@@ -721,12 +724,12 @@ inline void AdaptativeOverloadCollector<ArgumentAdapterT, FromTypes,
/// \brief Variadic operator overload.
template <unsigned MinCount, unsigned MaxCount>
-MatcherDescriptor *
-makeMatcherAutoMarshall(ast_matchers::internal::VariadicOperatorMatcherFunc<
- MinCount, MaxCount> Func,
- StringRef MatcherName) {
- return new VariadicOperatorMatcherDescriptor(MinCount, MaxCount, Func.Op,
- MatcherName);
+std::unique_ptr<MatcherDescriptor> makeMatcherAutoMarshall(
+ ast_matchers::internal::VariadicOperatorMatcherFunc<MinCount, MaxCount>
+ Func,
+ StringRef MatcherName) {
+ return llvm::make_unique<VariadicOperatorMatcherDescriptor>(
+ MinCount, MaxCount, Func.Op, MatcherName);
}
} // namespace internal
diff --git a/lib/ASTMatchers/Dynamic/Parser.cpp b/lib/ASTMatchers/Dynamic/Parser.cpp
index cf9dab6dc7db..ce8d0a9a0206 100644
--- a/lib/ASTMatchers/Dynamic/Parser.cpp
+++ b/lib/ASTMatchers/Dynamic/Parser.cpp
@@ -16,7 +16,6 @@
#include "clang/ASTMatchers/Dynamic/Registry.h"
#include "clang/Basic/CharInfo.h"
#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/Twine.h"
#include "llvm/Support/ManagedStatic.h"
#include <string>
#include <vector>
diff --git a/lib/ASTMatchers/Dynamic/Registry.cpp b/lib/ASTMatchers/Dynamic/Registry.cpp
index a8d4b88d8580..d1cab80c1a53 100644
--- a/lib/ASTMatchers/Dynamic/Registry.cpp
+++ b/lib/ASTMatchers/Dynamic/Registry.cpp
@@ -31,7 +31,7 @@ namespace {
using internal::MatcherDescriptor;
-typedef llvm::StringMap<const MatcherDescriptor *> ConstructorMap;
+typedef llvm::StringMap<std::unique_ptr<const MatcherDescriptor>> ConstructorMap;
class RegistryMaps {
public:
RegistryMaps();
@@ -40,14 +40,16 @@ public:
const ConstructorMap &constructors() const { return Constructors; }
private:
- void registerMatcher(StringRef MatcherName, MatcherDescriptor *Callback);
+ void registerMatcher(StringRef MatcherName,
+ std::unique_ptr<MatcherDescriptor> Callback);
+
ConstructorMap Constructors;
};
-void RegistryMaps::registerMatcher(StringRef MatcherName,
- MatcherDescriptor *Callback) {
+void RegistryMaps::registerMatcher(
+ StringRef MatcherName, std::unique_ptr<MatcherDescriptor> Callback) {
assert(Constructors.find(MatcherName) == Constructors.end());
- Constructors[MatcherName] = Callback;
+ Constructors[MatcherName] = std::move(Callback);
}
#define REGISTER_MATCHER(name) \
@@ -55,19 +57,19 @@ void RegistryMaps::registerMatcher(StringRef MatcherName,
::clang::ast_matchers::name, #name));
#define SPECIFIC_MATCHER_OVERLOAD(name, Id) \
- static_cast< ::clang::ast_matchers::name##_Type##Id>( \
+ static_cast<::clang::ast_matchers::name##_Type##Id>( \
::clang::ast_matchers::name)
#define REGISTER_OVERLOADED_2(name) \
do { \
- MatcherDescriptor *Callbacks[] = { \
- internal::makeMatcherAutoMarshall(SPECIFIC_MATCHER_OVERLOAD(name, 0), \
- #name), \
- internal::makeMatcherAutoMarshall(SPECIFIC_MATCHER_OVERLOAD(name, 1), \
- #name) \
- }; \
- registerMatcher(#name, \
- new internal::OverloadedMatcherDescriptor(Callbacks)); \
+ std::unique_ptr<MatcherDescriptor> Callbacks[] = { \
+ internal::makeMatcherAutoMarshall(SPECIFIC_MATCHER_OVERLOAD(name, 0), \
+ #name), \
+ internal::makeMatcherAutoMarshall(SPECIFIC_MATCHER_OVERLOAD(name, 1), \
+ #name)}; \
+ registerMatcher( \
+ #name, \
+ llvm::make_unique<internal::OverloadedMatcherDescriptor>(Callbacks)); \
} while (0)
/// \brief Generate a registry map with all the known matchers.
@@ -198,6 +200,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(hasAncestor);
REGISTER_MATCHER(hasAnyArgument);
REGISTER_MATCHER(hasAnyConstructorInitializer);
+ REGISTER_MATCHER(hasAnyDeclaration);
REGISTER_MATCHER(hasAnyName);
REGISTER_MATCHER(hasAnyParameter);
REGISTER_MATCHER(hasAnySubstatement);
@@ -225,9 +228,11 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(hasEitherOperand);
REGISTER_MATCHER(hasElementType);
REGISTER_MATCHER(hasElse);
+ REGISTER_MATCHER(hasExternalFormalLinkage);
REGISTER_MATCHER(hasFalseExpression);
REGISTER_MATCHER(hasGlobalStorage);
REGISTER_MATCHER(hasImplicitDestinationType);
+ REGISTER_MATCHER(hasInClassInitializer);
REGISTER_MATCHER(hasIncrement);
REGISTER_MATCHER(hasIndex);
REGISTER_MATCHER(hasInitializer);
@@ -248,6 +253,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(hasQualifier);
REGISTER_MATCHER(hasRangeInit);
REGISTER_MATCHER(hasReceiverType);
+ REGISTER_MATCHER(hasReplacementType);
REGISTER_MATCHER(hasReturnValue);
REGISTER_MATCHER(hasRHS);
REGISTER_MATCHER(hasSelector);
@@ -265,6 +271,8 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(hasTypeLoc);
REGISTER_MATCHER(hasUnaryOperand);
REGISTER_MATCHER(hasUnarySelector);
+ REGISTER_MATCHER(hasUnderlyingDecl);
+ REGISTER_MATCHER(hasUnqualifiedDesugaredType);
REGISTER_MATCHER(hasValueType);
REGISTER_MATCHER(ifStmt);
REGISTER_MATCHER(ignoringImplicit);
@@ -391,8 +399,10 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(switchCase);
REGISTER_MATCHER(switchStmt);
REGISTER_MATCHER(templateArgument);
+ REGISTER_MATCHER(templateName);
REGISTER_MATCHER(templateArgumentCountIs);
REGISTER_MATCHER(templateSpecializationType);
+ REGISTER_MATCHER(templateTypeParmDecl);
REGISTER_MATCHER(templateTypeParmType);
REGISTER_MATCHER(throughUsingDecl);
REGISTER_MATCHER(to);
@@ -421,9 +431,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(withInitializer);
}
-RegistryMaps::~RegistryMaps() {
- llvm::DeleteContainerSeconds(Constructors);
-}
+RegistryMaps::~RegistryMaps() {}
static llvm::ManagedStatic<RegistryMaps> RegistryData;
@@ -431,11 +439,10 @@ static llvm::ManagedStatic<RegistryMaps> RegistryData;
// static
llvm::Optional<MatcherCtor> Registry::lookupMatcherCtor(StringRef MatcherName) {
- ConstructorMap::const_iterator it =
- RegistryData->constructors().find(MatcherName);
+ auto it = RegistryData->constructors().find(MatcherName);
return it == RegistryData->constructors().end()
? llvm::Optional<MatcherCtor>()
- : it->second;
+ : it->second.get();
}
namespace {
@@ -494,12 +501,12 @@ Registry::getMatcherCompletions(ArrayRef<ArgKind> AcceptedTypes) {
// Search the registry for acceptable matchers.
for (const auto &M : RegistryData->constructors()) {
- const auto *Matcher = M.getValue();
+ const MatcherDescriptor& Matcher = *M.getValue();
StringRef Name = M.getKey();
std::set<ASTNodeKind> RetKinds;
- unsigned NumArgs = Matcher->isVariadic() ? 1 : Matcher->getNumArgs();
- bool IsPolymorphic = Matcher->isPolymorphic();
+ unsigned NumArgs = Matcher.isVariadic() ? 1 : Matcher.getNumArgs();
+ bool IsPolymorphic = Matcher.isPolymorphic();
std::vector<std::vector<ArgKind>> ArgsKinds(NumArgs);
unsigned MaxSpecificity = 0;
for (const ArgKind& Kind : AcceptedTypes) {
@@ -507,13 +514,13 @@ Registry::getMatcherCompletions(ArrayRef<ArgKind> AcceptedTypes) {
continue;
unsigned Specificity;
ASTNodeKind LeastDerivedKind;
- if (Matcher->isConvertibleTo(Kind.getMatcherKind(), &Specificity,
- &LeastDerivedKind)) {
+ if (Matcher.isConvertibleTo(Kind.getMatcherKind(), &Specificity,
+ &LeastDerivedKind)) {
if (MaxSpecificity < Specificity)
MaxSpecificity = Specificity;
RetKinds.insert(LeastDerivedKind);
for (unsigned Arg = 0; Arg != NumArgs; ++Arg)
- Matcher->getArgKinds(Kind.getMatcherKind(), Arg, ArgsKinds[Arg]);
+ Matcher.getArgKinds(Kind.getMatcherKind(), Arg, ArgsKinds[Arg]);
if (IsPolymorphic)
break;
}
@@ -549,7 +556,7 @@ Registry::getMatcherCompletions(ArrayRef<ArgKind> AcceptedTypes) {
}
}
}
- if (Matcher->isVariadic())
+ if (Matcher.isVariadic())
OS << "...";
OS << ")";
diff --git a/lib/Analysis/AnalysisDeclContext.cpp b/lib/Analysis/AnalysisDeclContext.cpp
index 6bbe8f86d48e..6b58916162f6 100644
--- a/lib/Analysis/AnalysisDeclContext.cpp
+++ b/lib/Analysis/AnalysisDeclContext.cpp
@@ -81,9 +81,7 @@ AnalysisDeclContextManager::AnalysisDeclContextManager(bool useUnoptimizedCFG,
cfgBuildOptions.AddCXXNewAllocator = addCXXNewAllocator;
}
-void AnalysisDeclContextManager::clear() {
- llvm::DeleteContainerSeconds(Contexts);
-}
+void AnalysisDeclContextManager::clear() { Contexts.clear(); }
static BodyFarm &getBodyFarm(ASTContext &C, CodeInjector *injector = nullptr) {
static BodyFarm *BF = new BodyFarm(C, injector);
@@ -307,10 +305,10 @@ AnalysisDeclContext *AnalysisDeclContextManager::getContext(const Decl *D) {
D = FD;
}
- AnalysisDeclContext *&AC = Contexts[D];
+ std::unique_ptr<AnalysisDeclContext> &AC = Contexts[D];
if (!AC)
- AC = new AnalysisDeclContext(this, D, cfgBuildOptions);
- return AC;
+ AC = llvm::make_unique<AnalysisDeclContext>(this, D, cfgBuildOptions);
+ return AC.get();
}
const StackFrameContext *
@@ -606,9 +604,7 @@ AnalysisDeclContext::~AnalysisDeclContext() {
}
}
-AnalysisDeclContextManager::~AnalysisDeclContextManager() {
- llvm::DeleteContainerSeconds(Contexts);
-}
+AnalysisDeclContextManager::~AnalysisDeclContextManager() {}
LocationContext::~LocationContext() {}
diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp
index a67f0910e15a..bf3cc05cdb6e 100644
--- a/lib/Analysis/CFG.cpp
+++ b/lib/Analysis/CFG.cpp
@@ -1164,7 +1164,8 @@ CFGBlock *CFGBuilder::addInitializer(CXXCtorInitializer *I) {
/// \brief Retrieve the type of the temporary object whose lifetime was
/// extended by a local reference with the given initializer.
static QualType getReferenceInitTemporaryType(ASTContext &Context,
- const Expr *Init) {
+ const Expr *Init,
+ bool *FoundMTE = nullptr) {
while (true) {
// Skip parentheses.
Init = Init->IgnoreParens();
@@ -1179,6 +1180,8 @@ static QualType getReferenceInitTemporaryType(ASTContext &Context,
if (const MaterializeTemporaryExpr *MTE
= dyn_cast<MaterializeTemporaryExpr>(Init)) {
Init = MTE->GetTemporaryExpr();
+ if (FoundMTE)
+ *FoundMTE = true;
continue;
}
@@ -1370,13 +1373,12 @@ LocalScope* CFGBuilder::addLocalScopeForVarDecl(VarDecl *VD,
const Expr *Init = VD->getInit();
if (!Init)
return Scope;
- if (const ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(Init))
- Init = EWC->getSubExpr();
- if (!isa<MaterializeTemporaryExpr>(Init))
- return Scope;
// Lifetime-extending a temporary.
- QT = getReferenceInitTemporaryType(*Context, Init);
+ bool FoundMTE = false;
+ QT = getReferenceInitTemporaryType(*Context, Init, &FoundMTE);
+ if (!FoundMTE)
+ return Scope;
}
// Check for constant size array. Set type to array element type.
@@ -2050,8 +2052,7 @@ CFGBlock *CFGBuilder::VisitDeclStmt(DeclStmt *DS) {
E = DS->decl_rend();
I != E; ++I) {
// Get the alignment of the new DeclStmt, padding out to >=8 bytes.
- unsigned A = llvm::AlignOf<DeclStmt>::Alignment < 8
- ? 8 : llvm::AlignOf<DeclStmt>::Alignment;
+ unsigned A = alignof(DeclStmt) < 8 ? 8 : alignof(DeclStmt);
// Allocate the DeclStmt using the BumpPtrAllocator. It will get
// automatically freed with the CFG.
@@ -2983,20 +2984,19 @@ CFGBlock *CFGBuilder::VisitDoStmt(DoStmt *D) {
return nullptr;
}
- if (!KnownVal.isFalse()) {
- // Add an intermediate block between the BodyBlock and the
- // ExitConditionBlock to represent the "loop back" transition. Create an
- // empty block to represent the transition block for looping back to the
- // head of the loop.
- // FIXME: Can we do this more efficiently without adding another block?
- Block = nullptr;
- Succ = BodyBlock;
- CFGBlock *LoopBackBlock = createBlock();
- LoopBackBlock->setLoopTarget(D);
+ // Add an intermediate block between the BodyBlock and the
+ // ExitConditionBlock to represent the "loop back" transition. Create an
+ // empty block to represent the transition block for looping back to the
+ // head of the loop.
+ // FIXME: Can we do this more efficiently without adding another block?
+ Block = nullptr;
+ Succ = BodyBlock;
+ CFGBlock *LoopBackBlock = createBlock();
+ LoopBackBlock->setLoopTarget(D);
+ if (!KnownVal.isFalse())
// Add the loop body entry as a successor to the condition.
addSuccessor(ExitConditionBlock, LoopBackBlock);
- }
else
addSuccessor(ExitConditionBlock, nullptr);
}
@@ -3583,11 +3583,13 @@ CFGBlock *CFGBuilder::VisitCXXDeleteExpr(CXXDeleteExpr *DE,
autoCreateBlock();
appendStmt(Block, DE);
QualType DTy = DE->getDestroyedType();
- DTy = DTy.getNonReferenceType();
- CXXRecordDecl *RD = Context->getBaseElementType(DTy)->getAsCXXRecordDecl();
- if (RD) {
- if (RD->isCompleteDefinition() && !RD->hasTrivialDestructor())
- appendDeleteDtor(Block, RD, DE);
+ if (!DTy.isNull()) {
+ DTy = DTy.getNonReferenceType();
+ CXXRecordDecl *RD = Context->getBaseElementType(DTy)->getAsCXXRecordDecl();
+ if (RD) {
+ if (RD->isCompleteDefinition() && !RD->hasTrivialDestructor())
+ appendDeleteDtor(Block, RD, DE);
+ }
}
return VisitChildren(DE);
diff --git a/lib/Analysis/CMakeLists.txt b/lib/Analysis/CMakeLists.txt
index 1df093d85098..fdc9e6cee8e1 100644
--- a/lib/Analysis/CMakeLists.txt
+++ b/lib/Analysis/CMakeLists.txt
@@ -9,12 +9,14 @@ add_clang_library(clangAnalysis
CFGReachabilityAnalysis.cpp
CFGStmtMap.cpp
CallGraph.cpp
+ CloneDetection.cpp
CocoaConventions.cpp
Consumed.cpp
CodeInjector.cpp
Dominators.cpp
FormatString.cpp
LiveVariables.cpp
+ OSLog.cpp
ObjCNoReturn.cpp
PostOrderCFGView.cpp
PrintfFormatString.cpp
diff --git a/lib/Analysis/CallGraph.cpp b/lib/Analysis/CallGraph.cpp
index 9d522fe7c6c5..8c126b09d057 100644
--- a/lib/Analysis/CallGraph.cpp
+++ b/lib/Analysis/CallGraph.cpp
@@ -55,7 +55,7 @@ public:
void addCalledDecl(Decl *D) {
if (G->includeInGraph(D)) {
CallGraphNode *CalleeNode = G->getOrInsertNode(D);
- CallerNode->addCallee(CalleeNode, G);
+ CallerNode->addCallee(CalleeNode);
}
}
@@ -104,9 +104,7 @@ CallGraph::CallGraph() {
Root = getOrInsertNode(nullptr);
}
-CallGraph::~CallGraph() {
- llvm::DeleteContainerSeconds(FunctionMap);
-}
+CallGraph::~CallGraph() {}
bool CallGraph::includeInGraph(const Decl *D) {
assert(D);
@@ -142,22 +140,22 @@ void CallGraph::addNodeForDecl(Decl* D, bool IsGlobal) {
CallGraphNode *CallGraph::getNode(const Decl *F) const {
FunctionMapTy::const_iterator I = FunctionMap.find(F);
if (I == FunctionMap.end()) return nullptr;
- return I->second;
+ return I->second.get();
}
CallGraphNode *CallGraph::getOrInsertNode(Decl *F) {
if (F && !isa<ObjCMethodDecl>(F))
F = F->getCanonicalDecl();
- CallGraphNode *&Node = FunctionMap[F];
+ std::unique_ptr<CallGraphNode> &Node = FunctionMap[F];
if (Node)
- return Node;
+ return Node.get();
- Node = new CallGraphNode(F);
+ Node = llvm::make_unique<CallGraphNode>(F);
// Make Root node a parent of all functions to make sure all are reachable.
if (F)
- Root->addCallee(Node, this);
- return Node;
+ Root->addCallee(Node.get());
+ return Node.get();
}
void CallGraph::print(raw_ostream &OS) const {
diff --git a/lib/Analysis/CloneDetection.cpp b/lib/Analysis/CloneDetection.cpp
new file mode 100644
index 000000000000..e761738214c6
--- /dev/null
+++ b/lib/Analysis/CloneDetection.cpp
@@ -0,0 +1,894 @@
+//===--- CloneDetection.cpp - Finds code clones in an AST -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// This file implements classes for searching and anlyzing source code clones.
+///
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/CloneDetection.h"
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/Stmt.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/Lex/Lexer.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/MD5.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang;
+
+StmtSequence::StmtSequence(const CompoundStmt *Stmt, ASTContext &Context,
+ unsigned StartIndex, unsigned EndIndex)
+ : S(Stmt), Context(&Context), StartIndex(StartIndex), EndIndex(EndIndex) {
+ assert(Stmt && "Stmt must not be a nullptr");
+ assert(StartIndex < EndIndex && "Given array should not be empty");
+ assert(EndIndex <= Stmt->size() && "Given array too big for this Stmt");
+}
+
+StmtSequence::StmtSequence(const Stmt *Stmt, ASTContext &Context)
+ : S(Stmt), Context(&Context), StartIndex(0), EndIndex(0) {}
+
+StmtSequence::StmtSequence()
+ : S(nullptr), Context(nullptr), StartIndex(0), EndIndex(0) {}
+
+bool StmtSequence::contains(const StmtSequence &Other) const {
+ // If both sequences reside in different translation units, they can never
+ // contain each other.
+ if (Context != Other.Context)
+ return false;
+
+ const SourceManager &SM = Context->getSourceManager();
+
+ // Otherwise check if the start and end locations of the current sequence
+ // surround the other sequence.
+ bool StartIsInBounds =
+ SM.isBeforeInTranslationUnit(getStartLoc(), Other.getStartLoc()) ||
+ getStartLoc() == Other.getStartLoc();
+ if (!StartIsInBounds)
+ return false;
+
+ bool EndIsInBounds =
+ SM.isBeforeInTranslationUnit(Other.getEndLoc(), getEndLoc()) ||
+ Other.getEndLoc() == getEndLoc();
+ return EndIsInBounds;
+}
+
+StmtSequence::iterator StmtSequence::begin() const {
+ if (!holdsSequence()) {
+ return &S;
+ }
+ auto CS = cast<CompoundStmt>(S);
+ return CS->body_begin() + StartIndex;
+}
+
+StmtSequence::iterator StmtSequence::end() const {
+ if (!holdsSequence()) {
+ return reinterpret_cast<StmtSequence::iterator>(&S) + 1;
+ }
+ auto CS = cast<CompoundStmt>(S);
+ return CS->body_begin() + EndIndex;
+}
+
+SourceLocation StmtSequence::getStartLoc() const {
+ return front()->getLocStart();
+}
+
+SourceLocation StmtSequence::getEndLoc() const { return back()->getLocEnd(); }
+
+SourceRange StmtSequence::getSourceRange() const {
+ return SourceRange(getStartLoc(), getEndLoc());
+}
+
+namespace {
+
+/// \brief Analyzes the pattern of the referenced variables in a statement.
+class VariablePattern {
+
+ /// \brief Describes an occurence of a variable reference in a statement.
+ struct VariableOccurence {
+ /// The index of the associated VarDecl in the Variables vector.
+ size_t KindID;
+ /// The statement in the code where the variable was referenced.
+ const Stmt *Mention;
+
+ VariableOccurence(size_t KindID, const Stmt *Mention)
+ : KindID(KindID), Mention(Mention) {}
+ };
+
+ /// All occurences of referenced variables in the order of appearance.
+ std::vector<VariableOccurence> Occurences;
+ /// List of referenced variables in the order of appearance.
+ /// Every item in this list is unique.
+ std::vector<const VarDecl *> Variables;
+
+ /// \brief Adds a new variable referenced to this pattern.
+ /// \param VarDecl The declaration of the variable that is referenced.
+ /// \param Mention The SourceRange where this variable is referenced.
+ void addVariableOccurence(const VarDecl *VarDecl, const Stmt *Mention) {
+ // First check if we already reference this variable
+ for (size_t KindIndex = 0; KindIndex < Variables.size(); ++KindIndex) {
+ if (Variables[KindIndex] == VarDecl) {
+ // If yes, add a new occurence that points to the existing entry in
+ // the Variables vector.
+ Occurences.emplace_back(KindIndex, Mention);
+ return;
+ }
+ }
+ // If this variable wasn't already referenced, add it to the list of
+ // referenced variables and add a occurence that points to this new entry.
+ Occurences.emplace_back(Variables.size(), Mention);
+ Variables.push_back(VarDecl);
+ }
+
+ /// \brief Adds each referenced variable from the given statement.
+ void addVariables(const Stmt *S) {
+ // Sometimes we get a nullptr (such as from IfStmts which often have nullptr
+ // children). We skip such statements as they don't reference any
+ // variables.
+ if (!S)
+ return;
+
+ // Check if S is a reference to a variable. If yes, add it to the pattern.
+ if (auto D = dyn_cast<DeclRefExpr>(S)) {
+ if (auto VD = dyn_cast<VarDecl>(D->getDecl()->getCanonicalDecl()))
+ addVariableOccurence(VD, D);
+ }
+
+ // Recursively check all children of the given statement.
+ for (const Stmt *Child : S->children()) {
+ addVariables(Child);
+ }
+ }
+
+public:
+ /// \brief Creates an VariablePattern object with information about the given
+ /// StmtSequence.
+ VariablePattern(const StmtSequence &Sequence) {
+ for (const Stmt *S : Sequence)
+ addVariables(S);
+ }
+
+ /// \brief Counts the differences between this pattern and the given one.
+ /// \param Other The given VariablePattern to compare with.
+ /// \param FirstMismatch Output parameter that will be filled with information
+ /// about the first difference between the two patterns. This parameter
+ /// can be a nullptr, in which case it will be ignored.
+ /// \return Returns the number of differences between the pattern this object
+ /// is following and the given VariablePattern.
+ ///
+ /// For example, the following statements all have the same pattern and this
+ /// function would return zero:
+ ///
+ /// if (a < b) return a; return b;
+ /// if (x < y) return x; return y;
+ /// if (u2 < u1) return u2; return u1;
+ ///
+ /// But the following statement has a different pattern (note the changed
+ /// variables in the return statements) and would have two differences when
+ /// compared with one of the statements above.
+ ///
+ /// if (a < b) return b; return a;
+ ///
+ /// This function should only be called if the related statements of the given
+ /// pattern and the statements of this objects are clones of each other.
+ unsigned countPatternDifferences(
+ const VariablePattern &Other,
+ CloneDetector::SuspiciousClonePair *FirstMismatch = nullptr) {
+ unsigned NumberOfDifferences = 0;
+
+ assert(Other.Occurences.size() == Occurences.size());
+ for (unsigned i = 0; i < Occurences.size(); ++i) {
+ auto ThisOccurence = Occurences[i];
+ auto OtherOccurence = Other.Occurences[i];
+ if (ThisOccurence.KindID == OtherOccurence.KindID)
+ continue;
+
+ ++NumberOfDifferences;
+
+ // If FirstMismatch is not a nullptr, we need to store information about
+ // the first difference between the two patterns.
+ if (FirstMismatch == nullptr)
+ continue;
+
+ // Only proceed if we just found the first difference as we only store
+ // information about the first difference.
+ if (NumberOfDifferences != 1)
+ continue;
+
+ const VarDecl *FirstSuggestion = nullptr;
+ // If there is a variable available in the list of referenced variables
+ // which wouldn't break the pattern if it is used in place of the
+ // current variable, we provide this variable as the suggested fix.
+ if (OtherOccurence.KindID < Variables.size())
+ FirstSuggestion = Variables[OtherOccurence.KindID];
+
+ // Store information about the first clone.
+ FirstMismatch->FirstCloneInfo =
+ CloneDetector::SuspiciousClonePair::SuspiciousCloneInfo(
+ Variables[ThisOccurence.KindID], ThisOccurence.Mention,
+ FirstSuggestion);
+
+ // Same as above but with the other clone. We do this for both clones as
+ // we don't know which clone is the one containing the unintended
+ // pattern error.
+ const VarDecl *SecondSuggestion = nullptr;
+ if (ThisOccurence.KindID < Other.Variables.size())
+ SecondSuggestion = Other.Variables[ThisOccurence.KindID];
+
+ // Store information about the second clone.
+ FirstMismatch->SecondCloneInfo =
+ CloneDetector::SuspiciousClonePair::SuspiciousCloneInfo(
+ Other.Variables[OtherOccurence.KindID], OtherOccurence.Mention,
+ SecondSuggestion);
+
+ // SuspiciousClonePair guarantees that the first clone always has a
+ // suggested variable associated with it. As we know that one of the two
+ // clones in the pair always has suggestion, we swap the two clones
+ // in case the first clone has no suggested variable which means that
+ // the second clone has a suggested variable and should be first.
+ if (!FirstMismatch->FirstCloneInfo.Suggestion)
+ std::swap(FirstMismatch->FirstCloneInfo,
+ FirstMismatch->SecondCloneInfo);
+
+ // This ensures that we always have at least one suggestion in a pair.
+ assert(FirstMismatch->FirstCloneInfo.Suggestion);
+ }
+
+ return NumberOfDifferences;
+ }
+};
+}
+
+/// \brief Prints the macro name that contains the given SourceLocation into
+/// the given raw_string_ostream.
+static void printMacroName(llvm::raw_string_ostream &MacroStack,
+ ASTContext &Context, SourceLocation Loc) {
+ MacroStack << Lexer::getImmediateMacroName(Loc, Context.getSourceManager(),
+ Context.getLangOpts());
+
+ // Add an empty space at the end as a padding to prevent
+ // that macro names concatenate to the names of other macros.
+ MacroStack << " ";
+}
+
+/// \brief Returns a string that represents all macro expansions that
+/// expanded into the given SourceLocation.
+///
+/// If 'getMacroStack(A) == getMacroStack(B)' is true, then the SourceLocations
+/// A and B are expanded from the same macros in the same order.
+static std::string getMacroStack(SourceLocation Loc, ASTContext &Context) {
+ std::string MacroStack;
+ llvm::raw_string_ostream MacroStackStream(MacroStack);
+ SourceManager &SM = Context.getSourceManager();
+
+ // Iterate over all macros that expanded into the given SourceLocation.
+ while (Loc.isMacroID()) {
+ // Add the macro name to the stream.
+ printMacroName(MacroStackStream, Context, Loc);
+ Loc = SM.getImmediateMacroCallerLoc(Loc);
+ }
+ MacroStackStream.flush();
+ return MacroStack;
+}
+
+namespace {
+/// \brief Collects the data of a single Stmt.
+///
+/// This class defines what a code clone is: If it collects for two statements
+/// the same data, then those two statements are considered to be clones of each
+/// other.
+///
+/// All collected data is forwarded to the given data consumer of the type T.
+/// The data consumer class needs to provide a member method with the signature:
+/// update(StringRef Str)
+template <typename T>
+class StmtDataCollector : public ConstStmtVisitor<StmtDataCollector<T>> {
+
+ ASTContext &Context;
+ /// \brief The data sink to which all data is forwarded.
+ T &DataConsumer;
+
+public:
+ /// \brief Collects data of the given Stmt.
+ /// \param S The given statement.
+ /// \param Context The ASTContext of S.
+ /// \param DataConsumer The data sink to which all data is forwarded.
+ StmtDataCollector(const Stmt *S, ASTContext &Context, T &DataConsumer)
+ : Context(Context), DataConsumer(DataConsumer) {
+ this->Visit(S);
+ }
+
+ // Below are utility methods for appending different data to the vector.
+
+ void addData(CloneDetector::DataPiece Integer) {
+ DataConsumer.update(
+ StringRef(reinterpret_cast<char *>(&Integer), sizeof(Integer)));
+ }
+
+ void addData(llvm::StringRef Str) { DataConsumer.update(Str); }
+
+ void addData(const QualType &QT) { addData(QT.getAsString()); }
+
+// The functions below collect the class specific data of each Stmt subclass.
+
+// Utility macro for defining a visit method for a given class. This method
+// calls back to the ConstStmtVisitor to visit all parent classes.
+#define DEF_ADD_DATA(CLASS, CODE) \
+ void Visit##CLASS(const CLASS *S) { \
+ CODE; \
+ ConstStmtVisitor<StmtDataCollector>::Visit##CLASS(S); \
+ }
+
+ DEF_ADD_DATA(Stmt, {
+ addData(S->getStmtClass());
+ // This ensures that macro generated code isn't identical to macro-generated
+ // code.
+ addData(getMacroStack(S->getLocStart(), Context));
+ addData(getMacroStack(S->getLocEnd(), Context));
+ })
+ DEF_ADD_DATA(Expr, { addData(S->getType()); })
+
+ //--- Builtin functionality ----------------------------------------------//
+ DEF_ADD_DATA(ArrayTypeTraitExpr, { addData(S->getTrait()); })
+ DEF_ADD_DATA(ExpressionTraitExpr, { addData(S->getTrait()); })
+ DEF_ADD_DATA(PredefinedExpr, { addData(S->getIdentType()); })
+ DEF_ADD_DATA(TypeTraitExpr, {
+ addData(S->getTrait());
+ for (unsigned i = 0; i < S->getNumArgs(); ++i)
+ addData(S->getArg(i)->getType());
+ })
+
+ //--- Calls --------------------------------------------------------------//
+ DEF_ADD_DATA(CallExpr, {
+ // Function pointers don't have a callee and we just skip hashing it.
+ if (const FunctionDecl *D = S->getDirectCallee()) {
+ // If the function is a template specialization, we also need to handle
+ // the template arguments as they are not included in the qualified name.
+ if (auto Args = D->getTemplateSpecializationArgs()) {
+ std::string ArgString;
+
+ // Print all template arguments into ArgString
+ llvm::raw_string_ostream OS(ArgString);
+ for (unsigned i = 0; i < Args->size(); ++i) {
+ Args->get(i).print(Context.getLangOpts(), OS);
+ // Add a padding character so that 'foo<X, XX>()' != 'foo<XX, X>()'.
+ OS << '\n';
+ }
+ OS.flush();
+
+ addData(ArgString);
+ }
+ addData(D->getQualifiedNameAsString());
+ }
+ })
+
+ //--- Exceptions ---------------------------------------------------------//
+ DEF_ADD_DATA(CXXCatchStmt, { addData(S->getCaughtType()); })
+
+ //--- C++ OOP Stmts ------------------------------------------------------//
+ DEF_ADD_DATA(CXXDeleteExpr, {
+ addData(S->isArrayFormAsWritten());
+ addData(S->isGlobalDelete());
+ })
+
+ //--- Casts --------------------------------------------------------------//
+ DEF_ADD_DATA(ObjCBridgedCastExpr, { addData(S->getBridgeKind()); })
+
+ //--- Miscellaneous Exprs ------------------------------------------------//
+ DEF_ADD_DATA(BinaryOperator, { addData(S->getOpcode()); })
+ DEF_ADD_DATA(UnaryOperator, { addData(S->getOpcode()); })
+
+ //--- Control flow -------------------------------------------------------//
+ DEF_ADD_DATA(GotoStmt, { addData(S->getLabel()->getName()); })
+ DEF_ADD_DATA(IndirectGotoStmt, {
+ if (S->getConstantTarget())
+ addData(S->getConstantTarget()->getName());
+ })
+ DEF_ADD_DATA(LabelStmt, { addData(S->getDecl()->getName()); })
+ DEF_ADD_DATA(MSDependentExistsStmt, { addData(S->isIfExists()); })
+ DEF_ADD_DATA(AddrLabelExpr, { addData(S->getLabel()->getName()); })
+
+ //--- Objective-C --------------------------------------------------------//
+ DEF_ADD_DATA(ObjCIndirectCopyRestoreExpr, { addData(S->shouldCopy()); })
+ DEF_ADD_DATA(ObjCPropertyRefExpr, {
+ addData(S->isSuperReceiver());
+ addData(S->isImplicitProperty());
+ })
+ DEF_ADD_DATA(ObjCAtCatchStmt, { addData(S->hasEllipsis()); })
+
+ //--- Miscellaneous Stmts ------------------------------------------------//
+ DEF_ADD_DATA(CXXFoldExpr, {
+ addData(S->isRightFold());
+ addData(S->getOperator());
+ })
+ DEF_ADD_DATA(GenericSelectionExpr, {
+ for (unsigned i = 0; i < S->getNumAssocs(); ++i) {
+ addData(S->getAssocType(i));
+ }
+ })
+ DEF_ADD_DATA(LambdaExpr, {
+ for (const LambdaCapture &C : S->captures()) {
+ addData(C.isPackExpansion());
+ addData(C.getCaptureKind());
+ if (C.capturesVariable())
+ addData(C.getCapturedVar()->getType());
+ }
+ addData(S->isGenericLambda());
+ addData(S->isMutable());
+ })
+ DEF_ADD_DATA(DeclStmt, {
+ auto numDecls = std::distance(S->decl_begin(), S->decl_end());
+ addData(static_cast<CloneDetector::DataPiece>(numDecls));
+ for (const Decl *D : S->decls()) {
+ if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ addData(VD->getType());
+ }
+ }
+ })
+ DEF_ADD_DATA(AsmStmt, {
+ addData(S->isSimple());
+ addData(S->isVolatile());
+ addData(S->generateAsmString(Context));
+ for (unsigned i = 0; i < S->getNumInputs(); ++i) {
+ addData(S->getInputConstraint(i));
+ }
+ for (unsigned i = 0; i < S->getNumOutputs(); ++i) {
+ addData(S->getOutputConstraint(i));
+ }
+ for (unsigned i = 0; i < S->getNumClobbers(); ++i) {
+ addData(S->getClobber(i));
+ }
+ })
+ DEF_ADD_DATA(AttributedStmt, {
+ for (const Attr *A : S->getAttrs()) {
+ addData(std::string(A->getSpelling()));
+ }
+ })
+};
+} // end anonymous namespace
+
+namespace {
+/// Generates CloneSignatures for a set of statements and stores the results in
+/// a CloneDetector object.
+class CloneSignatureGenerator {
+
+ CloneDetector &CD;
+ ASTContext &Context;
+
+ /// \brief Generates CloneSignatures for all statements in the given statement
+ /// tree and stores them in the CloneDetector.
+ ///
+ /// \param S The root of the given statement tree.
+ /// \param ParentMacroStack A string representing the macros that generated
+ /// the parent statement or an empty string if no
+ /// macros generated the parent statement.
+ /// See getMacroStack() for generating such a string.
+ /// \return The CloneSignature of the root statement.
+ CloneDetector::CloneSignature
+ generateSignatures(const Stmt *S, const std::string &ParentMacroStack) {
+ // Create an empty signature that will be filled in this method.
+ CloneDetector::CloneSignature Signature;
+
+ llvm::MD5 Hash;
+
+ // Collect all relevant data from S and hash it.
+ StmtDataCollector<llvm::MD5>(S, Context, Hash);
+
+ // Look up what macros expanded into the current statement.
+ std::string StartMacroStack = getMacroStack(S->getLocStart(), Context);
+ std::string EndMacroStack = getMacroStack(S->getLocEnd(), Context);
+
+ // First, check if ParentMacroStack is not empty which means we are currently
+ // dealing with a parent statement which was expanded from a macro.
+ // If this parent statement was expanded from the same macros as this
+ // statement, we reduce the initial complexity of this statement to zero.
+ // This causes that a group of statements that were generated by a single
+ // macro expansion will only increase the total complexity by one.
+ // Note: This is not the final complexity of this statement as we still
+ // add the complexity of the child statements to the complexity value.
+ if (!ParentMacroStack.empty() && (StartMacroStack == ParentMacroStack &&
+ EndMacroStack == ParentMacroStack)) {
+ Signature.Complexity = 0;
+ }
+
+ // Storage for the signatures of the direct child statements. This is only
+ // needed if the current statement is a CompoundStmt.
+ std::vector<CloneDetector::CloneSignature> ChildSignatures;
+ const CompoundStmt *CS = dyn_cast<const CompoundStmt>(S);
+
+ // The signature of a statement includes the signatures of its children.
+ // Therefore we create the signatures for every child and add them to the
+ // current signature.
+ for (const Stmt *Child : S->children()) {
+ // Some statements like 'if' can have nullptr children that we will skip.
+ if (!Child)
+ continue;
+
+ // Recursive call to create the signature of the child statement. This
+ // will also create and store all clone groups in this child statement.
+ // We pass only the StartMacroStack along to keep things simple.
+ auto ChildSignature = generateSignatures(Child, StartMacroStack);
+
+ // Add the collected data to the signature of the current statement.
+ Signature.Complexity += ChildSignature.Complexity;
+ Hash.update(StringRef(reinterpret_cast<char *>(&ChildSignature.Hash),
+ sizeof(ChildSignature.Hash)));
+
+ // If the current statement is a CompoundStatement, we need to store the
+ // signature for the generation of the sub-sequences.
+ if (CS)
+ ChildSignatures.push_back(ChildSignature);
+ }
+
+ // If the current statement is a CompoundStmt, we also need to create the
+ // clone groups from the sub-sequences inside the children.
+ if (CS)
+ handleSubSequences(CS, ChildSignatures);
+
+ // Create the final hash code for the current signature.
+ llvm::MD5::MD5Result HashResult;
+ Hash.final(HashResult);
+
+ // Copy as much of the generated hash code to the signature's hash code.
+ std::memcpy(&Signature.Hash, &HashResult,
+ std::min(sizeof(Signature.Hash), sizeof(HashResult)));
+
+ // Save the signature for the current statement in the CloneDetector object.
+ CD.add(StmtSequence(S, Context), Signature);
+
+ return Signature;
+ }
+
+ /// \brief Adds all possible sub-sequences in the child array of the given
+ /// CompoundStmt to the CloneDetector.
+ /// \param CS The given CompoundStmt.
+ /// \param ChildSignatures A list of calculated signatures for each child in
+ /// the given CompoundStmt.
+ void handleSubSequences(
+ const CompoundStmt *CS,
+ const std::vector<CloneDetector::CloneSignature> &ChildSignatures) {
+
+ // FIXME: This function has quadratic runtime right now. Check if skipping
+ // this function for too long CompoundStmts is an option.
+
+ // The length of the sub-sequence. We don't need to handle sequences with
+ // the length 1 as they are already handled in CollectData().
+ for (unsigned Length = 2; Length <= CS->size(); ++Length) {
+ // The start index in the body of the CompoundStmt. We increase the
+ // position until the end of the sub-sequence reaches the end of the
+ // CompoundStmt body.
+ for (unsigned Pos = 0; Pos <= CS->size() - Length; ++Pos) {
+ // Create an empty signature and add the signatures of all selected
+ // child statements to it.
+ CloneDetector::CloneSignature SubSignature;
+ llvm::MD5 SubHash;
+
+ for (unsigned i = Pos; i < Pos + Length; ++i) {
+ SubSignature.Complexity += ChildSignatures[i].Complexity;
+ size_t ChildHash = ChildSignatures[i].Hash;
+
+ SubHash.update(StringRef(reinterpret_cast<char *>(&ChildHash),
+ sizeof(ChildHash)));
+ }
+
+ // Create the final hash code for the current signature.
+ llvm::MD5::MD5Result HashResult;
+ SubHash.final(HashResult);
+
+ // Copy as much of the generated hash code to the signature's hash code.
+ std::memcpy(&SubSignature.Hash, &HashResult,
+ std::min(sizeof(SubSignature.Hash), sizeof(HashResult)));
+
+ // Save the signature together with the information about what children
+ // sequence we selected.
+ CD.add(StmtSequence(CS, Context, Pos, Pos + Length), SubSignature);
+ }
+ }
+ }
+
+public:
+ explicit CloneSignatureGenerator(CloneDetector &CD, ASTContext &Context)
+ : CD(CD), Context(Context) {}
+
+ /// \brief Generates signatures for all statements in the given function body.
+ void consumeCodeBody(const Stmt *S) { generateSignatures(S, ""); }
+};
+} // end anonymous namespace
+
+void CloneDetector::analyzeCodeBody(const Decl *D) {
+ assert(D);
+ assert(D->hasBody());
+ CloneSignatureGenerator Generator(*this, D->getASTContext());
+ Generator.consumeCodeBody(D->getBody());
+}
+
+void CloneDetector::add(const StmtSequence &S,
+ const CloneSignature &Signature) {
+ Sequences.push_back(std::make_pair(Signature, S));
+}
+
+namespace {
+/// \brief Returns true if and only if \p Stmt contains at least one other
+/// sequence in the \p Group.
+bool containsAnyInGroup(StmtSequence &Stmt, CloneDetector::CloneGroup &Group) {
+ for (StmtSequence &GroupStmt : Group.Sequences) {
+ if (Stmt.contains(GroupStmt))
+ return true;
+ }
+ return false;
+}
+
+/// \brief Returns true if and only if all sequences in \p OtherGroup are
+/// contained by a sequence in \p Group.
+bool containsGroup(CloneDetector::CloneGroup &Group,
+ CloneDetector::CloneGroup &OtherGroup) {
+ // We have less sequences in the current group than we have in the other,
+ // so we will never fulfill the requirement for returning true. This is only
+ // possible because we know that a sequence in Group can contain at most
+ // one sequence in OtherGroup.
+ if (Group.Sequences.size() < OtherGroup.Sequences.size())
+ return false;
+
+ for (StmtSequence &Stmt : Group.Sequences) {
+ if (!containsAnyInGroup(Stmt, OtherGroup))
+ return false;
+ }
+ return true;
+}
+} // end anonymous namespace
+
+namespace {
+/// \brief Wrapper around FoldingSetNodeID that it can be used as the template
+/// argument of the StmtDataCollector.
+class FoldingSetNodeIDWrapper {
+
+ llvm::FoldingSetNodeID &FS;
+
+public:
+ FoldingSetNodeIDWrapper(llvm::FoldingSetNodeID &FS) : FS(FS) {}
+
+ void update(StringRef Str) { FS.AddString(Str); }
+};
+} // end anonymous namespace
+
+/// \brief Writes the relevant data from all statements and child statements
+/// in the given StmtSequence into the given FoldingSetNodeID.
+static void CollectStmtSequenceData(const StmtSequence &Sequence,
+ FoldingSetNodeIDWrapper &OutputData) {
+ for (const Stmt *S : Sequence) {
+ StmtDataCollector<FoldingSetNodeIDWrapper>(S, Sequence.getASTContext(),
+ OutputData);
+
+ for (const Stmt *Child : S->children()) {
+ if (!Child)
+ continue;
+
+ CollectStmtSequenceData(StmtSequence(Child, Sequence.getASTContext()),
+ OutputData);
+ }
+ }
+}
+
+/// \brief Returns true if both sequences are clones of each other.
+static bool areSequencesClones(const StmtSequence &LHS,
+ const StmtSequence &RHS) {
+ // We collect the data from all statements in the sequence as we did before
+ // when generating a hash value for each sequence. But this time we don't
+ // hash the collected data and compare the whole data set instead. This
+ // prevents any false-positives due to hash code collisions.
+ llvm::FoldingSetNodeID DataLHS, DataRHS;
+ FoldingSetNodeIDWrapper LHSWrapper(DataLHS);
+ FoldingSetNodeIDWrapper RHSWrapper(DataRHS);
+
+ CollectStmtSequenceData(LHS, LHSWrapper);
+ CollectStmtSequenceData(RHS, RHSWrapper);
+
+ return DataLHS == DataRHS;
+}
+
+/// \brief Finds all actual clone groups in a single group of presumed clones.
+/// \param Result Output parameter to which all found groups are added.
+/// \param Group A group of presumed clones. The clones are allowed to have a
+/// different variable pattern and may not be actual clones of each
+/// other.
+/// \param CheckVariablePattern If true, every clone in a group that was added
+/// to the output follows the same variable pattern as the other
+/// clones in its group.
+static void createCloneGroups(std::vector<CloneDetector::CloneGroup> &Result,
+ const CloneDetector::CloneGroup &Group,
+ bool CheckVariablePattern) {
+ // We remove the Sequences one by one, so a list is more appropriate.
+ std::list<StmtSequence> UnassignedSequences(Group.Sequences.begin(),
+ Group.Sequences.end());
+
+ // Search for clones as long as there could be clones in UnassignedSequences.
+ while (UnassignedSequences.size() > 1) {
+
+ // Pick the first Sequence as a protoype for a new clone group.
+ StmtSequence Prototype = UnassignedSequences.front();
+ UnassignedSequences.pop_front();
+
+ CloneDetector::CloneGroup FilteredGroup(Prototype, Group.Signature);
+
+ // Analyze the variable pattern of the prototype. Every other StmtSequence
+ // needs to have the same pattern to get into the new clone group.
+ VariablePattern PrototypeFeatures(Prototype);
+
+ // Search all remaining StmtSequences for an identical variable pattern
+ // and assign them to our new clone group.
+ auto I = UnassignedSequences.begin(), E = UnassignedSequences.end();
+ while (I != E) {
+ // If the sequence doesn't fit to the prototype, we have encountered
+ // an unintended hash code collision and we skip it.
+ if (!areSequencesClones(Prototype, *I)) {
+ ++I;
+ continue;
+ }
+
+ // If we weren't asked to check for a matching variable pattern in clone
+ // groups we can add the sequence now to the new clone group.
+ // If we were asked to check for matching variable pattern, we first have
+ // to check that there are no differences between the two patterns and
+ // only proceed if they match.
+ if (!CheckVariablePattern ||
+ VariablePattern(*I).countPatternDifferences(PrototypeFeatures) == 0) {
+ FilteredGroup.Sequences.push_back(*I);
+ I = UnassignedSequences.erase(I);
+ continue;
+ }
+
+ // We didn't found a matching variable pattern, so we continue with the
+ // next sequence.
+ ++I;
+ }
+
+ // Add a valid clone group to the list of found clone groups.
+ if (!FilteredGroup.isValid())
+ continue;
+
+ Result.push_back(FilteredGroup);
+ }
+}
+
+void CloneDetector::findClones(std::vector<CloneGroup> &Result,
+ unsigned MinGroupComplexity,
+ bool CheckPatterns) {
+ // A shortcut (and necessary for the for-loop later in this function).
+ if (Sequences.empty())
+ return;
+
+ // We need to search for groups of StmtSequences with the same hash code to
+ // create our initial clone groups. By sorting all known StmtSequences by
+ // their hash value we make sure that StmtSequences with the same hash code
+ // are grouped together in the Sequences vector.
+ // Note: We stable sort here because the StmtSequences are added in the order
+ // in which they appear in the source file. We want to preserve that order
+ // because we also want to report them in that order in the CloneChecker.
+ std::stable_sort(Sequences.begin(), Sequences.end(),
+ [](std::pair<CloneSignature, StmtSequence> LHS,
+ std::pair<CloneSignature, StmtSequence> RHS) {
+ return LHS.first.Hash < RHS.first.Hash;
+ });
+
+ std::vector<CloneGroup> CloneGroups;
+
+ // Check for each CloneSignature if its successor has the same hash value.
+ // We don't check the last CloneSignature as it has no successor.
+ // Note: The 'size - 1' in the condition is safe because we check for an empty
+ // Sequences vector at the beginning of this function.
+ for (unsigned i = 0; i < Sequences.size() - 1; ++i) {
+ const auto Current = Sequences[i];
+ const auto Next = Sequences[i + 1];
+
+ if (Current.first.Hash != Next.first.Hash)
+ continue;
+
+ // It's likely that we just found an sequence of CloneSignatures that
+ // represent a CloneGroup, so we create a new group and start checking and
+ // adding the CloneSignatures in this sequence.
+ CloneGroup Group;
+ Group.Signature = Current.first;
+
+ for (; i < Sequences.size(); ++i) {
+ const auto &Signature = Sequences[i];
+
+ // A different hash value means we have reached the end of the sequence.
+ if (Current.first.Hash != Signature.first.Hash) {
+ // The current Signature could be the start of a new CloneGroup. So we
+ // decrement i so that we visit it again in the outer loop.
+ // Note: i can never be 0 at this point because we are just comparing
+ // the hash of the Current CloneSignature with itself in the 'if' above.
+ assert(i != 0);
+ --i;
+ break;
+ }
+
+ // Skip CloneSignatures that won't pass the complexity requirement.
+ if (Signature.first.Complexity < MinGroupComplexity)
+ continue;
+
+ Group.Sequences.push_back(Signature.second);
+ }
+
+ // There is a chance that we haven't found more than two fitting
+ // CloneSignature because not enough CloneSignatures passed the complexity
+ // requirement. As a CloneGroup with less than two members makes no sense,
+ // we ignore this CloneGroup and won't add it to the result.
+ if (!Group.isValid())
+ continue;
+
+ CloneGroups.push_back(Group);
+ }
+
+ // Add every valid clone group that fulfills the complexity requirement.
+ for (const CloneGroup &Group : CloneGroups) {
+ createCloneGroups(Result, Group, CheckPatterns);
+ }
+
+ std::vector<unsigned> IndexesToRemove;
+
+ // Compare every group in the result with the rest. If one groups contains
+ // another group, we only need to return the bigger group.
+ // Note: This doesn't scale well, so if possible avoid calling any heavy
+ // function from this loop to minimize the performance impact.
+ for (unsigned i = 0; i < Result.size(); ++i) {
+ for (unsigned j = 0; j < Result.size(); ++j) {
+ // Don't compare a group with itself.
+ if (i == j)
+ continue;
+
+ if (containsGroup(Result[j], Result[i])) {
+ IndexesToRemove.push_back(i);
+ break;
+ }
+ }
+ }
+
+ // Erasing a list of indexes from the vector should be done with decreasing
+ // indexes. As IndexesToRemove is constructed with increasing values, we just
+ // reverse iterate over it to get the desired order.
+ for (auto I = IndexesToRemove.rbegin(); I != IndexesToRemove.rend(); ++I) {
+ Result.erase(Result.begin() + *I);
+ }
+}
+
+void CloneDetector::findSuspiciousClones(
+ std::vector<CloneDetector::SuspiciousClonePair> &Result,
+ unsigned MinGroupComplexity) {
+ std::vector<CloneGroup> Clones;
+ // Reuse the normal search for clones but specify that the clone groups don't
+ // need to have a common referenced variable pattern so that we can manually
+ // search for the kind of pattern errors this function is supposed to find.
+ findClones(Clones, MinGroupComplexity, false);
+
+ for (const CloneGroup &Group : Clones) {
+ for (unsigned i = 0; i < Group.Sequences.size(); ++i) {
+ VariablePattern PatternA(Group.Sequences[i]);
+
+ for (unsigned j = i + 1; j < Group.Sequences.size(); ++j) {
+ VariablePattern PatternB(Group.Sequences[j]);
+
+ CloneDetector::SuspiciousClonePair ClonePair;
+ // For now, we only report clones which break the variable pattern just
+ // once because multiple differences in a pattern are an indicator that
+ // those differences are maybe intended (e.g. because it's actually
+ // a different algorithm).
+ // TODO: In very big clones even multiple variables can be unintended,
+ // so replacing this number with a percentage could better handle such
+ // cases. On the other hand it could increase the false-positive rate
+ // for all clones if the percentage is too high.
+ if (PatternA.countPatternDifferences(PatternB, &ClonePair) == 1) {
+ Result.push_back(ClonePair);
+ break;
+ }
+ }
+ }
+ }
+}
diff --git a/lib/Analysis/Consumed.cpp b/lib/Analysis/Consumed.cpp
index 47bef1b927c9..f6fe78ac4619 100644
--- a/lib/Analysis/Consumed.cpp
+++ b/lib/Analysis/Consumed.cpp
@@ -12,6 +12,7 @@
//
//===----------------------------------------------------------------------===//
+#include "clang/Analysis/Analyses/Consumed.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
#include "clang/AST/DeclCXX.h"
@@ -20,16 +21,12 @@
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/AST/Type.h"
-#include "clang/Analysis/Analyses/Consumed.h"
#include "clang/Analysis/Analyses/PostOrderCFGView.h"
#include "clang/Analysis/AnalysisContext.h"
#include "clang/Analysis/CFG.h"
#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/raw_ostream.h"
#include <memory>
// TODO: Adjust states of args to constructors in the same way that arguments to
diff --git a/lib/Analysis/FormatString.cpp b/lib/Analysis/FormatString.cpp
index 83d08b55427f..c62e537e92dd 100644
--- a/lib/Analysis/FormatString.cpp
+++ b/lib/Analysis/FormatString.cpp
@@ -266,14 +266,15 @@ bool clang::analyze_format_string::ParseUTF8InvalidSpecifier(
if (SpecifierBegin + 1 >= FmtStrEnd)
return false;
- const UTF8 *SB = reinterpret_cast<const UTF8 *>(SpecifierBegin + 1);
- const UTF8 *SE = reinterpret_cast<const UTF8 *>(FmtStrEnd);
+ const llvm::UTF8 *SB =
+ reinterpret_cast<const llvm::UTF8 *>(SpecifierBegin + 1);
+ const llvm::UTF8 *SE = reinterpret_cast<const llvm::UTF8 *>(FmtStrEnd);
const char FirstByte = *SB;
// If the invalid specifier is a multibyte UTF-8 string, return the
// total length accordingly so that the conversion specifier can be
// properly updated to reflect a complete UTF-8 specifier.
- unsigned NumBytes = getNumBytesForUTF8(FirstByte);
+ unsigned NumBytes = llvm::getNumBytesForUTF8(FirstByte);
if (NumBytes == 1)
return false;
if (SB + NumBytes > SE)
@@ -310,8 +311,13 @@ ArgType::matchesType(ASTContext &C, QualType argTy) const {
return Match;
case AnyCharTy: {
- if (const EnumType *ETy = argTy->getAs<EnumType>())
+ if (const EnumType *ETy = argTy->getAs<EnumType>()) {
+ // If the enum is incomplete we know nothing about the underlying type.
+ // Assume that it's 'int'.
+ if (!ETy->getDecl()->isComplete())
+ return NoMatch;
argTy = ETy->getDecl()->getIntegerType();
+ }
if (const BuiltinType *BT = argTy->getAs<BuiltinType>())
switch (BT->getKind()) {
@@ -327,8 +333,14 @@ ArgType::matchesType(ASTContext &C, QualType argTy) const {
}
case SpecificTy: {
- if (const EnumType *ETy = argTy->getAs<EnumType>())
- argTy = ETy->getDecl()->getIntegerType();
+ if (const EnumType *ETy = argTy->getAs<EnumType>()) {
+ // If the enum is incomplete we know nothing about the underlying type.
+ // Assume that it's 'int'.
+ if (!ETy->getDecl()->isComplete())
+ argTy = C.IntTy;
+ else
+ argTy = ETy->getDecl()->getIntegerType();
+ }
argTy = C.getCanonicalType(argTy).getUnqualifiedType();
if (T == argTy)
@@ -579,6 +591,8 @@ const char *ConversionSpecifier::toString() const {
case cArg: return "c";
case sArg: return "s";
case pArg: return "p";
+ case PArg:
+ return "P";
case nArg: return "n";
case PercentArg: return "%";
case ScanListArg: return "[";
@@ -854,6 +868,7 @@ bool FormatSpecifier::hasStandardConversionSpecifier(
case ConversionSpecifier::ObjCObjArg:
case ConversionSpecifier::ScanListArg:
case ConversionSpecifier::PercentArg:
+ case ConversionSpecifier::PArg:
return true;
case ConversionSpecifier::CArg:
case ConversionSpecifier::SArg:
diff --git a/lib/Analysis/FormatStringParsing.h b/lib/Analysis/FormatStringParsing.h
index 8463fcec5bf4..17fd2f6aefb8 100644
--- a/lib/Analysis/FormatStringParsing.h
+++ b/lib/Analysis/FormatStringParsing.h
@@ -4,7 +4,6 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/Type.h"
#include "clang/Analysis/Analyses/FormatString.h"
-#include "llvm/Support/raw_ostream.h"
namespace clang {
diff --git a/lib/Analysis/LiveVariables.cpp b/lib/Analysis/LiveVariables.cpp
index 5e0a9a0d73c8..cd73a62e6918 100644
--- a/lib/Analysis/LiveVariables.cpp
+++ b/lib/Analysis/LiveVariables.cpp
@@ -19,6 +19,7 @@
#include "clang/Analysis/CFG.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/PostOrderIterator.h"
+#include "llvm/ADT/PriorityQueue.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <vector>
@@ -28,20 +29,21 @@ using namespace clang;
namespace {
class DataflowWorklist {
- SmallVector<const CFGBlock *, 20> worklist;
llvm::BitVector enqueuedBlocks;
PostOrderCFGView *POV;
+ llvm::PriorityQueue<const CFGBlock *, SmallVector<const CFGBlock *, 20>,
+ PostOrderCFGView::BlockOrderCompare> worklist;
+
public:
DataflowWorklist(const CFG &cfg, AnalysisDeclContext &Ctx)
: enqueuedBlocks(cfg.getNumBlockIDs()),
- POV(Ctx.getAnalysis<PostOrderCFGView>()) {}
+ POV(Ctx.getAnalysis<PostOrderCFGView>()),
+ worklist(POV->getComparator()) {}
void enqueueBlock(const CFGBlock *block);
void enqueuePredecessors(const CFGBlock *block);
const CFGBlock *dequeue();
-
- void sortWorklist();
};
}
@@ -49,31 +51,22 @@ public:
void DataflowWorklist::enqueueBlock(const clang::CFGBlock *block) {
if (block && !enqueuedBlocks[block->getBlockID()]) {
enqueuedBlocks[block->getBlockID()] = true;
- worklist.push_back(block);
+ worklist.push(block);
}
}
void DataflowWorklist::enqueuePredecessors(const clang::CFGBlock *block) {
- const unsigned OldWorklistSize = worklist.size();
for (CFGBlock::const_pred_iterator I = block->pred_begin(),
E = block->pred_end(); I != E; ++I) {
enqueueBlock(*I);
}
-
- if (OldWorklistSize == 0 || OldWorklistSize == worklist.size())
- return;
-
- sortWorklist();
-}
-
-void DataflowWorklist::sortWorklist() {
- std::sort(worklist.begin(), worklist.end(), POV->getComparator());
}
const CFGBlock *DataflowWorklist::dequeue() {
if (worklist.empty())
return nullptr;
- const CFGBlock *b = worklist.pop_back_val();
+ const CFGBlock *b = worklist.top();
+ worklist.pop();
enqueuedBlocks[b->getBlockID()] = false;
return b;
}
@@ -528,8 +521,6 @@ LiveVariables::computeLiveness(AnalysisDeclContext &AC,
}
}
- worklist.sortWorklist();
-
while (const CFGBlock *block = worklist.dequeue()) {
// Determine if the block's end value has changed. If not, we
// have nothing left to do for this block.
diff --git a/lib/Analysis/OSLog.cpp b/lib/Analysis/OSLog.cpp
new file mode 100644
index 000000000000..3e13a153c65f
--- /dev/null
+++ b/lib/Analysis/OSLog.cpp
@@ -0,0 +1,202 @@
+// TODO: header template
+
+#include "clang/Analysis/Analyses/OSLog.h"
+#include "clang/AST/Attr.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/Analysis/Analyses/FormatString.h"
+#include "clang/Basic/Builtins.h"
+#include "llvm/ADT/SmallBitVector.h"
+
+using namespace clang;
+using llvm::APInt;
+
+using clang::analyze_os_log::OSLogBufferItem;
+using clang::analyze_os_log::OSLogBufferLayout;
+
+class OSLogFormatStringHandler
+ : public analyze_format_string::FormatStringHandler {
+private:
+ struct ArgData {
+ const Expr *E = nullptr;
+ Optional<OSLogBufferItem::Kind> Kind;
+ Optional<unsigned> Size;
+ Optional<const Expr *> Count;
+ Optional<const Expr *> Precision;
+ Optional<const Expr *> FieldWidth;
+ unsigned char Flags = 0;
+ };
+ SmallVector<ArgData, 4> ArgsData;
+ ArrayRef<const Expr *> Args;
+
+ OSLogBufferItem::Kind
+ getKind(analyze_format_string::ConversionSpecifier::Kind K) {
+ switch (K) {
+ case clang::analyze_format_string::ConversionSpecifier::sArg: // "%s"
+ return OSLogBufferItem::StringKind;
+ case clang::analyze_format_string::ConversionSpecifier::SArg: // "%S"
+ return OSLogBufferItem::WideStringKind;
+ case clang::analyze_format_string::ConversionSpecifier::PArg: { // "%P"
+ return OSLogBufferItem::PointerKind;
+ case clang::analyze_format_string::ConversionSpecifier::ObjCObjArg: // "%@"
+ return OSLogBufferItem::ObjCObjKind;
+ case clang::analyze_format_string::ConversionSpecifier::PrintErrno: // "%m"
+ return OSLogBufferItem::ErrnoKind;
+ default:
+ return OSLogBufferItem::ScalarKind;
+ }
+ }
+ }
+
+public:
+ OSLogFormatStringHandler(ArrayRef<const Expr *> Args) : Args(Args) {
+ ArgsData.reserve(Args.size());
+ }
+
+ virtual bool HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier &FS,
+ const char *StartSpecifier,
+ unsigned SpecifierLen) {
+ if (!FS.consumesDataArgument() &&
+ FS.getConversionSpecifier().getKind() !=
+ clang::analyze_format_string::ConversionSpecifier::PrintErrno)
+ return true;
+
+ ArgsData.emplace_back();
+ unsigned ArgIndex = FS.getArgIndex();
+ if (ArgIndex < Args.size())
+ ArgsData.back().E = Args[ArgIndex];
+
+ // First get the Kind
+ ArgsData.back().Kind = getKind(FS.getConversionSpecifier().getKind());
+ if (ArgsData.back().Kind != OSLogBufferItem::ErrnoKind &&
+ !ArgsData.back().E) {
+ // missing argument
+ ArgsData.pop_back();
+ return false;
+ }
+
+ switch (FS.getConversionSpecifier().getKind()) {
+ case clang::analyze_format_string::ConversionSpecifier::sArg: // "%s"
+ case clang::analyze_format_string::ConversionSpecifier::SArg: { // "%S"
+ auto &precision = FS.getPrecision();
+ switch (precision.getHowSpecified()) {
+ case clang::analyze_format_string::OptionalAmount::NotSpecified: // "%s"
+ break;
+ case clang::analyze_format_string::OptionalAmount::Constant: // "%.16s"
+ ArgsData.back().Size = precision.getConstantAmount();
+ break;
+ case clang::analyze_format_string::OptionalAmount::Arg: // "%.*s"
+ ArgsData.back().Count = Args[precision.getArgIndex()];
+ break;
+ case clang::analyze_format_string::OptionalAmount::Invalid:
+ return false;
+ }
+ break;
+ }
+ case clang::analyze_format_string::ConversionSpecifier::PArg: { // "%P"
+ auto &precision = FS.getPrecision();
+ switch (precision.getHowSpecified()) {
+ case clang::analyze_format_string::OptionalAmount::NotSpecified: // "%P"
+ return false; // length must be supplied with pointer format specifier
+ case clang::analyze_format_string::OptionalAmount::Constant: // "%.16P"
+ ArgsData.back().Size = precision.getConstantAmount();
+ break;
+ case clang::analyze_format_string::OptionalAmount::Arg: // "%.*P"
+ ArgsData.back().Count = Args[precision.getArgIndex()];
+ break;
+ case clang::analyze_format_string::OptionalAmount::Invalid:
+ return false;
+ }
+ break;
+ }
+ default:
+ if (FS.getPrecision().hasDataArgument()) {
+ ArgsData.back().Precision = Args[FS.getPrecision().getArgIndex()];
+ }
+ break;
+ }
+ if (FS.getFieldWidth().hasDataArgument()) {
+ ArgsData.back().FieldWidth = Args[FS.getFieldWidth().getArgIndex()];
+ }
+
+ if (FS.isPrivate()) {
+ ArgsData.back().Flags |= OSLogBufferItem::IsPrivate;
+ }
+ if (FS.isPublic()) {
+ ArgsData.back().Flags |= OSLogBufferItem::IsPublic;
+ }
+ return true;
+ }
+
+ void computeLayout(ASTContext &Ctx, OSLogBufferLayout &Layout) const {
+ Layout.Items.clear();
+ for (auto &Data : ArgsData) {
+ if (Data.FieldWidth) {
+ CharUnits Size = Ctx.getTypeSizeInChars((*Data.FieldWidth)->getType());
+ Layout.Items.emplace_back(OSLogBufferItem::ScalarKind, *Data.FieldWidth,
+ Size, 0);
+ }
+ if (Data.Precision) {
+ CharUnits Size = Ctx.getTypeSizeInChars((*Data.Precision)->getType());
+ Layout.Items.emplace_back(OSLogBufferItem::ScalarKind, *Data.Precision,
+ Size, 0);
+ }
+ if (Data.Count) {
+ // "%.*P" has an extra "count" that we insert before the argument.
+ CharUnits Size = Ctx.getTypeSizeInChars((*Data.Count)->getType());
+ Layout.Items.emplace_back(OSLogBufferItem::CountKind, *Data.Count, Size,
+ 0);
+ }
+ if (Data.Size)
+ Layout.Items.emplace_back(Ctx, CharUnits::fromQuantity(*Data.Size),
+ Data.Flags);
+ if (Data.Kind) {
+ CharUnits Size;
+ if (*Data.Kind == OSLogBufferItem::ErrnoKind)
+ Size = CharUnits::Zero();
+ else
+ Size = Ctx.getTypeSizeInChars(Data.E->getType());
+ Layout.Items.emplace_back(*Data.Kind, Data.E, Size, Data.Flags);
+ } else {
+ auto Size = Ctx.getTypeSizeInChars(Data.E->getType());
+ Layout.Items.emplace_back(OSLogBufferItem::ScalarKind, Data.E, Size,
+ Data.Flags);
+ }
+ }
+ }
+};
+
+bool clang::analyze_os_log::computeOSLogBufferLayout(
+ ASTContext &Ctx, const CallExpr *E, OSLogBufferLayout &Layout) {
+ ArrayRef<const Expr *> Args(E->getArgs(), E->getArgs() + E->getNumArgs());
+
+ const Expr *StringArg;
+ ArrayRef<const Expr *> VarArgs;
+ switch (E->getBuiltinCallee()) {
+ case Builtin::BI__builtin_os_log_format_buffer_size:
+ assert(E->getNumArgs() >= 1 &&
+ "__builtin_os_log_format_buffer_size takes at least 1 argument");
+ StringArg = E->getArg(0);
+ VarArgs = Args.slice(1);
+ break;
+ case Builtin::BI__builtin_os_log_format:
+ assert(E->getNumArgs() >= 2 &&
+ "__builtin_os_log_format takes at least 2 arguments");
+ StringArg = E->getArg(1);
+ VarArgs = Args.slice(2);
+ break;
+ default:
+ llvm_unreachable("non-os_log builtin passed to computeOSLogBufferLayout");
+ }
+
+ const StringLiteral *Lit = cast<StringLiteral>(StringArg->IgnoreParenCasts());
+ assert(Lit && (Lit->isAscii() || Lit->isUTF8()));
+ StringRef Data = Lit->getString();
+ OSLogFormatStringHandler H(VarArgs);
+ ParsePrintfString(H, Data.begin(), Data.end(), Ctx.getLangOpts(),
+ Ctx.getTargetInfo(), /*isFreeBSDKPrintf*/ false);
+
+ H.computeLayout(Ctx, Layout);
+ return true;
+}
diff --git a/lib/Analysis/PrintfFormatString.cpp b/lib/Analysis/PrintfFormatString.cpp
index ac6cef9d0842..ed7193ecb437 100644
--- a/lib/Analysis/PrintfFormatString.cpp
+++ b/lib/Analysis/PrintfFormatString.cpp
@@ -119,6 +119,39 @@ static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H,
return true;
}
+ const char *OSLogVisibilityFlagsStart = nullptr,
+ *OSLogVisibilityFlagsEnd = nullptr;
+ if (*I == '{') {
+ OSLogVisibilityFlagsStart = I++;
+ // Find the end of the modifier.
+ while (I != E && *I != '}') {
+ I++;
+ }
+ if (I == E) {
+ if (Warn)
+ H.HandleIncompleteSpecifier(Start, E - Start);
+ return true;
+ }
+ assert(*I == '}');
+ OSLogVisibilityFlagsEnd = I++;
+
+ // Just see if 'private' or 'public' is the first word. os_log itself will
+ // do any further parsing.
+ const char *P = OSLogVisibilityFlagsStart + 1;
+ while (P < OSLogVisibilityFlagsEnd && isspace(*P))
+ P++;
+ const char *WordStart = P;
+ while (P < OSLogVisibilityFlagsEnd && (isalnum(*P) || *P == '_'))
+ P++;
+ const char *WordEnd = P;
+ StringRef Word(WordStart, WordEnd - WordStart);
+ if (Word == "private") {
+ FS.setIsPrivate(WordStart);
+ } else if (Word == "public") {
+ FS.setIsPublic(WordStart);
+ }
+ }
+
// Look for flags (if any).
bool hasMore = true;
for ( ; I != E; ++I) {
@@ -253,6 +286,10 @@ static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H,
// POSIX specific.
case 'C': k = ConversionSpecifier::CArg; break;
case 'S': k = ConversionSpecifier::SArg; break;
+ // Apple extension for os_log
+ case 'P':
+ k = ConversionSpecifier::PArg;
+ break;
// Objective-C.
case '@': k = ConversionSpecifier::ObjCObjArg; break;
// Glibc specific.
@@ -301,7 +338,7 @@ static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H,
conversionPosition);
return true;
}
-
+
PrintfConversionSpecifier CS(conversionPosition, k);
FS.setConversionSpecifier(CS);
if (CS.consumesDataArgument() && !FS.usesPositionalArg())
@@ -541,6 +578,7 @@ ArgType PrintfSpecifier::getArgType(ASTContext &Ctx,
return Ctx.IntTy;
return ArgType(Ctx.WideCharTy, "wchar_t");
case ConversionSpecifier::pArg:
+ case ConversionSpecifier::PArg:
return ArgType::CPointerTy;
case ConversionSpecifier::ObjCObjArg:
return ArgType::ObjCPointerTy;
@@ -900,7 +938,7 @@ bool PrintfSpecifier::hasValidPrecision() const {
if (Precision.getHowSpecified() == OptionalAmount::NotSpecified)
return true;
- // Precision is only valid with the diouxXaAeEfFgGs conversions
+ // Precision is only valid with the diouxXaAeEfFgGsP conversions
switch (CS.getKind()) {
case ConversionSpecifier::dArg:
case ConversionSpecifier::DArg:
@@ -922,6 +960,7 @@ bool PrintfSpecifier::hasValidPrecision() const {
case ConversionSpecifier::sArg:
case ConversionSpecifier::FreeBSDrArg:
case ConversionSpecifier::FreeBSDyArg:
+ case ConversionSpecifier::PArg:
return true;
default:
diff --git a/lib/Analysis/ReachableCode.cpp b/lib/Analysis/ReachableCode.cpp
index 8165b09f4080..69d000c03bac 100644
--- a/lib/Analysis/ReachableCode.cpp
+++ b/lib/Analysis/ReachableCode.cpp
@@ -164,6 +164,8 @@ static bool isConfigurationValue(const Stmt *S,
if (!S)
return false;
+ S = S->IgnoreImplicit();
+
if (const Expr *Ex = dyn_cast<Expr>(S))
S = Ex->IgnoreCasts();
diff --git a/lib/Analysis/ScanfFormatString.cpp b/lib/Analysis/ScanfFormatString.cpp
index 82b038864c23..3b93f1a57f1f 100644
--- a/lib/Analysis/ScanfFormatString.cpp
+++ b/lib/Analysis/ScanfFormatString.cpp
@@ -418,8 +418,12 @@ bool ScanfSpecifier::fixType(QualType QT, QualType RawQT,
QualType PT = QT->getPointeeType();
// If it's an enum, get its underlying type.
- if (const EnumType *ETy = PT->getAs<EnumType>())
+ if (const EnumType *ETy = PT->getAs<EnumType>()) {
+ // Don't try to fix incomplete enums.
+ if (!ETy->getDecl()->isComplete())
+ return false;
PT = ETy->getDecl()->getIntegerType();
+ }
const BuiltinType *BT = PT->getAs<BuiltinType>();
if (!BT)
diff --git a/lib/Analysis/ThreadSafety.cpp b/lib/Analysis/ThreadSafety.cpp
index b282a5bbd8d8..879a15c9c2a8 100644
--- a/lib/Analysis/ThreadSafety.cpp
+++ b/lib/Analysis/ThreadSafety.cpp
@@ -15,13 +15,13 @@
//
//===----------------------------------------------------------------------===//
+#include "clang/Analysis/Analyses/ThreadSafety.h"
#include "clang/AST/Attr.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Analysis/Analyses/PostOrderCFGView.h"
-#include "clang/Analysis/Analyses/ThreadSafety.h"
#include "clang/Analysis/Analyses/ThreadSafetyCommon.h"
#include "clang/Analysis/Analyses/ThreadSafetyLogical.h"
#include "clang/Analysis/Analyses/ThreadSafetyTIL.h"
@@ -32,8 +32,6 @@
#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
-#include "llvm/ADT/BitVector.h"
-#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/ImmutableMap.h"
#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/ADT/SmallVector.h"
@@ -259,7 +257,7 @@ private:
struct BeforeInfo {
BeforeInfo() : Visited(0) {}
- BeforeInfo(BeforeInfo &&O) : Vect(std::move(O.Vect)), Visited(O.Visited) {}
+ BeforeInfo(BeforeInfo &&) = default;
BeforeVect Vect;
int Visited;
@@ -1585,7 +1583,7 @@ void BuildLockset::warnIfMutexHeld(const NamedDecl *D, const Expr *Exp,
/// a pointer marked with pt_guarded_by.
void BuildLockset::checkAccess(const Expr *Exp, AccessKind AK,
ProtectedOperationKind POK) {
- Exp = Exp->IgnoreParenCasts();
+ Exp = Exp->IgnoreImplicit()->IgnoreParenCasts();
SourceLocation Loc = Exp->getExprLoc();
diff --git a/lib/Analysis/ThreadSafetyCommon.cpp b/lib/Analysis/ThreadSafetyCommon.cpp
index ffe95ea22a42..cbd5464c34d7 100644
--- a/lib/Analysis/ThreadSafetyCommon.cpp
+++ b/lib/Analysis/ThreadSafetyCommon.cpp
@@ -17,20 +17,14 @@
#include "clang/AST/DeclObjC.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/StmtCXX.h"
-#include "clang/Analysis/Analyses/PostOrderCFGView.h"
#include "clang/Analysis/Analyses/ThreadSafetyTIL.h"
#include "clang/Analysis/Analyses/ThreadSafetyTraverse.h"
#include "clang/Analysis/AnalysisContext.h"
#include "clang/Analysis/CFG.h"
#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/SourceLocation.h"
-#include "clang/Basic/SourceManager.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include <algorithm>
-#include <climits>
-#include <vector>
using namespace clang;
using namespace threadSafety;
@@ -239,6 +233,9 @@ til::SExpr *SExprBuilder::translate(const Stmt *S, CallingContext *Ctx) {
return translate(cast<ExprWithCleanups>(S)->getSubExpr(), Ctx);
case Stmt::CXXBindTemporaryExprClass:
return translate(cast<CXXBindTemporaryExpr>(S)->getSubExpr(), Ctx);
+ case Stmt::MaterializeTemporaryExprClass:
+ return translate(cast<MaterializeTemporaryExpr>(S)->GetTemporaryExpr(),
+ Ctx);
// Collect all literals
case Stmt::CharacterLiteralClass:
diff --git a/lib/Analysis/UninitializedValues.cpp b/lib/Analysis/UninitializedValues.cpp
index f2f791957aa3..d5289fb9d427 100644
--- a/lib/Analysis/UninitializedValues.cpp
+++ b/lib/Analysis/UninitializedValues.cpp
@@ -348,7 +348,8 @@ public:
}
static const DeclRefExpr *getSelfInitExpr(VarDecl *VD) {
- if (VD->getType()->isRecordType()) return nullptr;
+ if (VD->getType()->isRecordType())
+ return nullptr;
if (Expr *Init = VD->getInit()) {
const DeclRefExpr *DRE
= dyn_cast<DeclRefExpr>(stripCasts(VD->getASTContext(), Init));
diff --git a/lib/Basic/CMakeLists.txt b/lib/Basic/CMakeLists.txt
index ad460d496533..8929ec30ff7b 100644
--- a/lib/Basic/CMakeLists.txt
+++ b/lib/Basic/CMakeLists.txt
@@ -28,7 +28,7 @@ find_first_existing_vc_file(clang_vc "${CLANG_SOURCE_DIR}")
# The VC revision include that we want to generate.
set(version_inc "${CMAKE_CURRENT_BINARY_DIR}/SVNVersion.inc")
-set(get_svn_script "${LLVM_MAIN_SRC_DIR}/cmake/modules/GetSVN.cmake")
+set(get_svn_script "${LLVM_CMAKE_PATH}/GetSVN.cmake")
if(DEFINED llvm_vc AND DEFINED clang_vc)
# Create custom target to generate the VC revision include.
diff --git a/lib/Basic/Diagnostic.cpp b/lib/Basic/Diagnostic.cpp
index f10d156743b2..7529c475d6b9 100644
--- a/lib/Basic/Diagnostic.cpp
+++ b/lib/Basic/Diagnostic.cpp
@@ -55,10 +55,12 @@ static void DummyArgToStringFn(DiagnosticsEngine::ArgumentKind AK, intptr_t QT,
Output.append(Str.begin(), Str.end());
}
-DiagnosticsEngine::DiagnosticsEngine(
- const IntrusiveRefCntPtr<DiagnosticIDs> &diags, DiagnosticOptions *DiagOpts,
- DiagnosticConsumer *client, bool ShouldOwnClient)
- : Diags(diags), DiagOpts(DiagOpts), Client(nullptr), SourceMgr(nullptr) {
+DiagnosticsEngine::DiagnosticsEngine(IntrusiveRefCntPtr<DiagnosticIDs> diags,
+ DiagnosticOptions *DiagOpts,
+ DiagnosticConsumer *client,
+ bool ShouldOwnClient)
+ : Diags(std::move(diags)), DiagOpts(DiagOpts), Client(nullptr),
+ SourceMgr(nullptr) {
setClient(client, ShouldOwnClient);
ArgToStringFn = DummyArgToStringFn;
ArgToStringCookie = nullptr;
@@ -740,7 +742,10 @@ FormatDiagnostic(const char *DiagStr, const char *DiagEnd,
// "%diff{compare $ to $|other text}1,2"
// treat it as:
// "compare %1 to %2"
- const char *Pipe = ScanFormat(Argument, Argument + ArgumentLen, '|');
+ const char *ArgumentEnd = Argument + ArgumentLen;
+ const char *Pipe = ScanFormat(Argument, ArgumentEnd, '|');
+ assert(ScanFormat(Pipe + 1, ArgumentEnd, '|') == ArgumentEnd &&
+ "Found too many '|'s in a %diff modifier!");
const char *FirstDollar = ScanFormat(Argument, Pipe, '$');
const char *SecondDollar = ScanFormat(FirstDollar + 1, Pipe, '$');
const char ArgStr1[] = { '%', static_cast<char>('0' + ArgNo) };
@@ -1008,7 +1013,7 @@ PartialDiagnostic::StorageAllocator::StorageAllocator() {
PartialDiagnostic::StorageAllocator::~StorageAllocator() {
// Don't assert if we are in a CrashRecovery context, as this invariant may
// be invalidated during a crash.
- assert((NumFreeListEntries == NumCached ||
- llvm::CrashRecoveryContext::isRecoveringFromCrash()) &&
- "A partial is on the lamb");
+ assert((NumFreeListEntries == NumCached ||
+ llvm::CrashRecoveryContext::isRecoveringFromCrash()) &&
+ "A partial is on the lam");
}
diff --git a/lib/Basic/DiagnosticOptions.cpp b/lib/Basic/DiagnosticOptions.cpp
index f54a0ef4edb2..93c2196ca979 100644
--- a/lib/Basic/DiagnosticOptions.cpp
+++ b/lib/Basic/DiagnosticOptions.cpp
@@ -16,7 +16,7 @@
namespace clang {
-raw_ostream& operator<<(raw_ostream& Out, DiagnosticLevelMask M) {
+raw_ostream &operator<<(raw_ostream &Out, DiagnosticLevelMask M) {
using UT = std::underlying_type<DiagnosticLevelMask>::type;
return Out << static_cast<UT>(M);
}
diff --git a/lib/Basic/FileManager.cpp b/lib/Basic/FileManager.cpp
index ce9b7e1bb48c..50050d0a519b 100644
--- a/lib/Basic/FileManager.cpp
+++ b/lib/Basic/FileManager.cpp
@@ -26,10 +26,13 @@
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
-#include <map>
-#include <set>
+#include <algorithm>
+#include <cassert>
+#include <climits>
+#include <cstdint>
+#include <cstdlib>
#include <string>
-#include <system_error>
+#include <utility>
using namespace clang;
@@ -137,7 +140,7 @@ void FileManager::addAncestorsAsVirtualDirs(StringRef Path) {
// Add the virtual directory to the cache.
auto UDE = llvm::make_unique<DirectoryEntry>();
- UDE->Name = NamedDirEnt.first().data();
+ UDE->Name = NamedDirEnt.first();
NamedDirEnt.second = UDE.get();
VirtualDirectoryEntries.push_back(std::move(UDE));
@@ -182,7 +185,7 @@ const DirectoryEntry *FileManager::getDirectory(StringRef DirName,
// Get the null-terminated directory name as stored as the key of the
// SeenDirEntries map.
- const char *InterndDirName = NamedDirEnt.first().data();
+ StringRef InterndDirName = NamedDirEnt.first();
// Check to see if the directory exists.
FileData Data;
@@ -200,7 +203,7 @@ const DirectoryEntry *FileManager::getDirectory(StringRef DirName,
DirectoryEntry &UDE = UniqueRealDirs[Data.UniqueID];
NamedDirEnt.second = &UDE;
- if (!UDE.getName()) {
+ if (UDE.getName().empty()) {
// We don't have this directory yet, add it. We use the string
// key from the SeenDirEntries map as the string.
UDE.Name = InterndDirName;
@@ -229,7 +232,7 @@ const FileEntry *FileManager::getFile(StringRef Filename, bool openFile,
// Get the null-terminated file name as stored as the key of the
// SeenFileEntries map.
- const char *InterndFileName = NamedFileEnt.first().data();
+ StringRef InterndFileName = NamedFileEnt.first();
// Look up the directory for the file. When looking up something like
// sys/foo.h we'll discover all of the search directories that have a 'sys'
@@ -420,7 +423,7 @@ FileManager::getBufferForFile(const FileEntry *Entry, bool isVolatile,
if (isVolatile)
FileSize = -1;
- const char *Filename = Entry->getName();
+ StringRef Filename = Entry->getName();
// If the file is already open, use the open file descriptor.
if (Entry->File) {
auto Result =
@@ -460,7 +463,7 @@ FileManager::getBufferForFile(StringRef Filename) {
/// if the path points to a virtual file or does not exist, or returns
/// false if it's an existent real file. If FileDescriptor is NULL,
/// do directory look-up instead of file look-up.
-bool FileManager::getStatValue(const char *Path, FileData &Data, bool isFile,
+bool FileManager::getStatValue(StringRef Path, FileData &Data, bool isFile,
std::unique_ptr<vfs::File> *F) {
// FIXME: FileSystemOpts shouldn't be passed in here, all paths should be
// absolute!
@@ -497,7 +500,6 @@ void FileManager::invalidateCache(const FileEntry *Entry) {
UniqueRealFiles.erase(Entry->getUniqueID());
}
-
void FileManager::GetUniqueIDMapping(
SmallVectorImpl<const FileEntry *> &UIDToFiles) const {
UIDToFiles.clear();
@@ -533,7 +535,7 @@ StringRef FileManager::getCanonicalName(const DirectoryEntry *Dir) {
#ifdef LLVM_ON_UNIX
char CanonicalNameBuf[PATH_MAX];
- if (realpath(Dir->getName(), CanonicalNameBuf))
+ if (realpath(Dir->getName().str().c_str(), CanonicalNameBuf))
CanonicalName = StringRef(CanonicalNameBuf).copy(CanonicalNameStorage);
#else
SmallString<256> CanonicalNameBuf(CanonicalName);
diff --git a/lib/Basic/FileSystemStatCache.cpp b/lib/Basic/FileSystemStatCache.cpp
index 187ea37e0c28..799df1d3c3a6 100644
--- a/lib/Basic/FileSystemStatCache.cpp
+++ b/lib/Basic/FileSystemStatCache.cpp
@@ -23,7 +23,7 @@ static void copyStatusToFileData(const vfs::Status &Status,
FileData &Data) {
Data.Name = Status.getName();
Data.Size = Status.getSize();
- Data.ModTime = Status.getLastModificationTime().toEpochTime();
+ Data.ModTime = llvm::sys::toTimeT(Status.getLastModificationTime());
Data.UniqueID = Status.getUniqueID();
Data.IsDirectory = Status.isDirectory();
Data.IsNamedPipe = Status.getType() == llvm::sys::fs::file_type::fifo_file;
@@ -40,7 +40,7 @@ static void copyStatusToFileData(const vfs::Status &Status,
/// success for directories (not files). On a successful file lookup, the
/// implementation can optionally fill in FileDescriptor with a valid
/// descriptor and the client guarantees that it will close it.
-bool FileSystemStatCache::get(const char *Path, FileData &Data, bool isFile,
+bool FileSystemStatCache::get(StringRef Path, FileData &Data, bool isFile,
std::unique_ptr<vfs::File> *F,
FileSystemStatCache *Cache, vfs::FileSystem &FS) {
LookupResult R;
@@ -107,7 +107,7 @@ bool FileSystemStatCache::get(const char *Path, FileData &Data, bool isFile,
}
MemorizeStatCalls::LookupResult
-MemorizeStatCalls::getStat(const char *Path, FileData &Data, bool isFile,
+MemorizeStatCalls::getStat(StringRef Path, FileData &Data, bool isFile,
std::unique_ptr<vfs::File> *F, vfs::FileSystem &FS) {
LookupResult Result = statChained(Path, Data, isFile, F, FS);
diff --git a/lib/Basic/IdentifierTable.cpp b/lib/Basic/IdentifierTable.cpp
index d6ad0f5c9158..af424cd92390 100644
--- a/lib/Basic/IdentifierTable.cpp
+++ b/lib/Basic/IdentifierTable.cpp
@@ -113,7 +113,8 @@ namespace {
KEYOBJC2 = 0x20000,
KEYZVECTOR = 0x40000,
KEYCOROUTINES = 0x80000,
- KEYALL = (0xfffff & ~KEYNOMS18 &
+ KEYMODULES = 0x100000,
+ KEYALL = (0x1fffff & ~KEYNOMS18 &
~KEYNOOPENCL) // KEYNOMS18 and KEYNOOPENCL are used to exclude.
};
@@ -147,9 +148,10 @@ 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.Coroutines && (Flags & KEYCOROUTINES)) return KS_Enabled;
+ if (LangOpts.ConceptsTS && (Flags & KEYCONCEPTS)) return KS_Enabled;
+ if (LangOpts.CoroutinesTS && (Flags & KEYCOROUTINES)) return KS_Enabled;
+ if (LangOpts.ModulesTS && (Flags & KEYMODULES)) return KS_Enabled;
if (LangOpts.CPlusPlus && (Flags & KEYCXX11)) return KS_Future;
return KS_Disabled;
}
@@ -441,9 +443,11 @@ std::string Selector::getAsString() const {
if (getIdentifierInfoFlag() < MultiArg) {
IdentifierInfo *II = getAsIdentifierInfo();
- // If the number of arguments is 0 then II is guaranteed to not be null.
- if (getNumArgs() == 0)
+ if (getNumArgs() == 0) {
+ assert(II && "If the number of arguments is 0 then II is guaranteed to "
+ "not be null.");
return II->getName();
+ }
if (!II)
return ":";
@@ -619,8 +623,8 @@ Selector SelectorTable::getSelector(unsigned nKeys, IdentifierInfo **IIV) {
// variable size array (for parameter types) at the end of them.
unsigned Size = sizeof(MultiKeywordSelector) + nKeys*sizeof(IdentifierInfo *);
MultiKeywordSelector *SI =
- (MultiKeywordSelector*)SelTabImpl.Allocator.Allocate(Size,
- llvm::alignOf<MultiKeywordSelector>());
+ (MultiKeywordSelector *)SelTabImpl.Allocator.Allocate(
+ Size, alignof(MultiKeywordSelector));
new (SI) MultiKeywordSelector(nKeys, IIV);
SelTabImpl.Table.InsertNode(SI, InsertPos);
return Selector(SI);
diff --git a/lib/Basic/LangOptions.cpp b/lib/Basic/LangOptions.cpp
index 8c0ecd46ad55..ff10a773a97c 100644
--- a/lib/Basic/LangOptions.cpp
+++ b/lib/Basic/LangOptions.cpp
@@ -15,7 +15,8 @@
using namespace clang;
-LangOptions::LangOptions() {
+LangOptions::LangOptions()
+ : IsHeaderFile(false) {
#define LANGOPT(Name, Bits, Default, Description) Name = Default;
#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) set##Name(Default);
#include "clang/Basic/LangOptions.def"
@@ -34,10 +35,10 @@ void LangOptions::resetNonModularOptions() {
SanitizerBlacklistFiles.clear();
CurrentModule.clear();
+ IsHeaderFile = false;
}
-bool LangOptions::isNoBuiltinFunc(const char *Name) const {
- StringRef FuncName(Name);
+bool LangOptions::isNoBuiltinFunc(StringRef FuncName) const {
for (unsigned i = 0, e = NoBuiltinFuncs.size(); i != e; ++i)
if (FuncName.equals(NoBuiltinFuncs[i]))
return true;
diff --git a/lib/Basic/Module.cpp b/lib/Basic/Module.cpp
index 3d1a40db5ea2..80bbc24f3db3 100644
--- a/lib/Basic/Module.cpp
+++ b/lib/Basic/Module.cpp
@@ -33,7 +33,7 @@ Module::Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent,
IsExplicit(IsExplicit), IsSystem(false), IsExternC(false),
IsInferred(false), InferSubmodules(false), InferExplicitSubmodules(false),
InferExportWildcard(false), ConfigMacrosExhaustive(false),
- NameVisibility(Hidden) {
+ NoUndeclaredIncludes(false), NameVisibility(Hidden) {
if (Parent) {
if (!Parent->isAvailable())
IsAvailable = false;
@@ -41,6 +41,8 @@ Module::Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent,
IsSystem = true;
if (Parent->IsExternC)
IsExternC = true;
+ if (Parent->NoUndeclaredIncludes)
+ NoUndeclaredIncludes = true;
IsMissingRequirement = Parent->IsMissingRequirement;
Parent->SubModuleIndex[Name] = Parent->SubModules.size();
@@ -64,6 +66,8 @@ static bool hasFeature(StringRef Feature, const LangOptions &LangOpts,
.Case("blocks", LangOpts.Blocks)
.Case("cplusplus", LangOpts.CPlusPlus)
.Case("cplusplus11", LangOpts.CPlusPlus11)
+ .Case("freestanding", LangOpts.Freestanding)
+ .Case("gnuinlineasm", LangOpts.GNUAsm)
.Case("objc", LangOpts.ObjC1)
.Case("objc_arc", LangOpts.ObjCAutoRefCount)
.Case("opencl", LangOpts.OpenCL)
@@ -179,6 +183,11 @@ bool Module::directlyUses(const Module *Requested) const {
for (auto *Use : Top->DirectUses)
if (Requested->isSubModuleOf(Use))
return true;
+
+ // Anyone is allowed to use our builtin stddef.h and its accompanying module.
+ if (!Requested->Parent && Requested->Name == "_Builtin_stddef_max_align_t")
+ return true;
+
return false;
}
diff --git a/lib/Basic/OpenMPKinds.cpp b/lib/Basic/OpenMPKinds.cpp
index d1e4779e2c72..4675995ea722 100644
--- a/lib/Basic/OpenMPKinds.cpp
+++ b/lib/Basic/OpenMPKinds.cpp
@@ -610,6 +610,86 @@ bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind,
break;
}
break;
+ case OMPD_target_simd:
+ switch (CKind) {
+#define OPENMP_TARGET_SIMD_CLAUSE(Name)