From b60736ec1405bb0a8dd40989f67ef4c93da068ab Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Tue, 16 Feb 2021 21:13:02 +0100 Subject: Vendor import of llvm-project main 8e464dd76bef, the last commit before the upstream release/12.x branch was created. --- clang/lib/APINotes/APINotesFormat.h | 255 + clang/lib/APINotes/APINotesTypes.cpp | 107 + clang/lib/APINotes/APINotesYAMLCompiler.cpp | 598 +++ clang/lib/ARCMigrate/ARCMT.cpp | 8 +- clang/lib/ARCMigrate/FileRemapper.cpp | 15 + clang/lib/ARCMigrate/ObjCMT.cpp | 39 +- clang/lib/ARCMigrate/TransGCAttrs.cpp | 22 +- clang/lib/ARCMigrate/TransProperties.cpp | 17 +- clang/lib/ARCMigrate/Transforms.h | 6 +- clang/lib/AST/APValue.cpp | 538 +- clang/lib/AST/ASTContext.cpp | 585 ++- clang/lib/AST/ASTDiagnostic.cpp | 15 +- clang/lib/AST/ASTDumper.cpp | 8 +- clang/lib/AST/ASTImporter.cpp | 564 ++- clang/lib/AST/ASTImporterLookupTable.cpp | 14 + clang/lib/AST/ASTStructuralEquivalence.cpp | 496 +- clang/lib/AST/ASTTypeTraits.cpp | 58 +- clang/lib/AST/AttrImpl.cpp | 53 +- clang/lib/AST/CXXInheritance.cpp | 150 +- clang/lib/AST/CommentLexer.cpp | 9 +- clang/lib/AST/ComparisonCategories.cpp | 2 +- clang/lib/AST/ComputeDependence.cpp | 138 +- clang/lib/AST/Decl.cpp | 357 +- clang/lib/AST/DeclBase.cpp | 65 +- clang/lib/AST/DeclCXX.cpp | 131 +- clang/lib/AST/DeclObjC.cpp | 45 +- clang/lib/AST/DeclOpenMP.cpp | 112 +- clang/lib/AST/DeclPrinter.cpp | 28 +- clang/lib/AST/DeclTemplate.cpp | 77 +- clang/lib/AST/Expr.cpp | 482 +- clang/lib/AST/ExprCXX.cpp | 207 +- clang/lib/AST/ExprClassification.cpp | 4 +- clang/lib/AST/ExprConstant.cpp | 1547 ++++-- clang/lib/AST/Interp/Disasm.cpp | 4 +- clang/lib/AST/Interp/State.cpp | 2 +- clang/lib/AST/ItaniumMangle.cpp | 1048 +++- clang/lib/AST/JSONNodeDumper.cpp | 8 +- clang/lib/AST/Linkage.h | 2 + clang/lib/AST/Mangle.cpp | 72 +- clang/lib/AST/MicrosoftMangle.cpp | 424 +- clang/lib/AST/NSAPI.cpp | 3 + clang/lib/AST/OpenMPClause.cpp | 178 +- clang/lib/AST/ParentMapContext.cpp | 117 +- clang/lib/AST/PrintfFormatString.cpp | 3 + clang/lib/AST/RecordLayout.cpp | 41 +- clang/lib/AST/RecordLayoutBuilder.cpp | 380 +- clang/lib/AST/Stmt.cpp | 110 +- clang/lib/AST/StmtOpenMP.cpp | 1135 ++--- clang/lib/AST/StmtPrinter.cpp | 25 +- clang/lib/AST/StmtProfile.cpp | 9 +- clang/lib/AST/TemplateBase.cpp | 35 +- clang/lib/AST/TemplateName.cpp | 18 +- clang/lib/AST/TextNodeDumper.cpp | 51 +- clang/lib/AST/Type.cpp | 113 +- clang/lib/AST/TypeLoc.cpp | 5 +- clang/lib/AST/TypePrinter.cpp | 314 +- clang/lib/ASTMatchers/ASTMatchFinder.cpp | 447 +- clang/lib/ASTMatchers/ASTMatchersInternal.cpp | 152 +- clang/lib/ASTMatchers/Dynamic/Marshallers.cpp | 11 +- clang/lib/ASTMatchers/Dynamic/Marshallers.h | 208 +- clang/lib/ASTMatchers/Dynamic/Registry.cpp | 11 +- clang/lib/ASTMatchers/Dynamic/VariantValue.cpp | 30 + clang/lib/ASTMatchers/GtestMatchers.cpp | 4 +- clang/lib/Analysis/BodyFarm.cpp | 40 +- clang/lib/Analysis/CFG.cpp | 35 +- clang/lib/Analysis/CalledOnceCheck.cpp | 1525 ++++++ clang/lib/Analysis/ExprMutationAnalyzer.cpp | 300 +- clang/lib/Analysis/IssueHash.cpp | 207 + clang/lib/Analysis/LiveVariables.cpp | 102 +- clang/lib/Analysis/PathDiagnostic.cpp | 46 +- clang/lib/Analysis/ThreadSafety.cpp | 29 +- clang/lib/Analysis/ThreadSafetyCommon.cpp | 4 +- clang/lib/Basic/Cuda.cpp | 43 +- clang/lib/Basic/Diagnostic.cpp | 35 +- clang/lib/Basic/DiagnosticIDs.cpp | 109 +- clang/lib/Basic/FileEntry.cpp | 24 + clang/lib/Basic/FileManager.cpp | 181 +- clang/lib/Basic/FixedPoint.cpp | 394 -- clang/lib/Basic/IdentifierTable.cpp | 5 + clang/lib/Basic/LangOptions.cpp | 2 +- clang/lib/Basic/Module.cpp | 21 +- clang/lib/Basic/OpenCLOptions.cpp | 106 + clang/lib/Basic/OpenMPKinds.cpp | 50 +- clang/lib/Basic/ProfileList.cpp | 113 + clang/lib/Basic/SourceLocation.cpp | 21 +- clang/lib/Basic/SourceManager.cpp | 506 +- clang/lib/Basic/TargetID.cpp | 169 + clang/lib/Basic/TargetInfo.cpp | 1 + clang/lib/Basic/Targets.cpp | 68 +- clang/lib/Basic/Targets/AArch64.cpp | 48 +- clang/lib/Basic/Targets/AArch64.h | 6 + clang/lib/Basic/Targets/AMDGPU.cpp | 36 +- clang/lib/Basic/Targets/AMDGPU.h | 77 +- clang/lib/Basic/Targets/ARM.cpp | 2 + clang/lib/Basic/Targets/AVR.cpp | 7 + clang/lib/Basic/Targets/Hexagon.cpp | 3 +- clang/lib/Basic/Targets/MSP430.cpp | 1 + clang/lib/Basic/Targets/Mips.cpp | 1 - clang/lib/Basic/Targets/NVPTX.cpp | 8 + clang/lib/Basic/Targets/NVPTX.h | 22 +- clang/lib/Basic/Targets/OSTargets.h | 81 +- clang/lib/Basic/Targets/PPC.cpp | 87 +- clang/lib/Basic/Targets/PPC.h | 34 +- clang/lib/Basic/Targets/RISCV.cpp | 160 +- clang/lib/Basic/Targets/RISCV.h | 49 +- clang/lib/Basic/Targets/SPIR.h | 6 +- clang/lib/Basic/Targets/Sparc.cpp | 28 +- clang/lib/Basic/Targets/Sparc.h | 11 +- clang/lib/Basic/Targets/SystemZ.h | 4 + clang/lib/Basic/Targets/TCE.h | 2 + clang/lib/Basic/Targets/VE.h | 16 +- clang/lib/Basic/Targets/WebAssembly.cpp | 60 +- clang/lib/Basic/Targets/WebAssembly.h | 6 +- clang/lib/Basic/Targets/X86.cpp | 59 +- clang/lib/Basic/Targets/X86.h | 36 +- clang/lib/Basic/Version.cpp | 2 - clang/lib/Basic/Warnings.cpp | 7 +- clang/lib/CodeGen/ABIInfo.h | 2 +- clang/lib/CodeGen/BackendUtil.cpp | 560 +-- clang/lib/CodeGen/CGAtomic.cpp | 60 +- clang/lib/CodeGen/CGBlocks.cpp | 17 +- clang/lib/CodeGen/CGBuiltin.cpp | 2363 ++++++--- clang/lib/CodeGen/CGCUDANV.cpp | 109 +- clang/lib/CodeGen/CGCUDARuntime.h | 7 +- clang/lib/CodeGen/CGCXXABI.cpp | 26 +- clang/lib/CodeGen/CGCXXABI.h | 13 +- clang/lib/CodeGen/CGCall.cpp | 339 +- clang/lib/CodeGen/CGCall.h | 6 +- clang/lib/CodeGen/CGClass.cpp | 103 +- clang/lib/CodeGen/CGCleanup.h | 1 + clang/lib/CodeGen/CGDebugInfo.cpp | 312 +- clang/lib/CodeGen/CGDebugInfo.h | 14 +- clang/lib/CodeGen/CGDecl.cpp | 158 +- clang/lib/CodeGen/CGDeclCXX.cpp | 113 +- clang/lib/CodeGen/CGException.cpp | 28 +- clang/lib/CodeGen/CGExpr.cpp | 244 +- clang/lib/CodeGen/CGExprAgg.cpp | 131 +- clang/lib/CodeGen/CGExprCXX.cpp | 28 +- clang/lib/CodeGen/CGExprComplex.cpp | 11 +- clang/lib/CodeGen/CGExprConstant.cpp | 34 +- clang/lib/CodeGen/CGExprScalar.cpp | 440 +- clang/lib/CodeGen/CGLoopInfo.cpp | 93 +- clang/lib/CodeGen/CGLoopInfo.h | 15 +- clang/lib/CodeGen/CGObjC.cpp | 243 +- clang/lib/CodeGen/CGObjCGNU.cpp | 67 +- clang/lib/CodeGen/CGObjCMac.cpp | 98 +- clang/lib/CodeGen/CGObjCRuntime.cpp | 10 + clang/lib/CodeGen/CGObjCRuntime.h | 14 + clang/lib/CodeGen/CGOpenMPRuntime.cpp | 2002 +++++--- clang/lib/CodeGen/CGOpenMPRuntime.h | 81 +- clang/lib/CodeGen/CGOpenMPRuntimeAMDGCN.cpp | 60 + clang/lib/CodeGen/CGOpenMPRuntimeAMDGCN.h | 43 + clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp | 4864 ++++++++++++++++++ clang/lib/CodeGen/CGOpenMPRuntimeGPU.h | 504 ++ clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp | 5225 +------------------- clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.h | 465 +- clang/lib/CodeGen/CGRecordLayout.h | 17 +- clang/lib/CodeGen/CGRecordLayoutBuilder.cpp | 187 +- clang/lib/CodeGen/CGStmt.cpp | 301 +- clang/lib/CodeGen/CGStmtOpenMP.cpp | 205 +- clang/lib/CodeGen/CGVTT.cpp | 13 +- clang/lib/CodeGen/CGVTables.cpp | 96 +- clang/lib/CodeGen/CGValue.h | 2 +- clang/lib/CodeGen/CodeGenAction.cpp | 220 +- clang/lib/CodeGen/CodeGenFunction.cpp | 315 +- clang/lib/CodeGen/CodeGenFunction.h | 257 +- clang/lib/CodeGen/CodeGenModule.cpp | 398 +- clang/lib/CodeGen/CodeGenModule.h | 58 +- clang/lib/CodeGen/CodeGenPGO.cpp | 55 +- clang/lib/CodeGen/CodeGenPGO.h | 2 +- clang/lib/CodeGen/CodeGenTypeCache.h | 3 + clang/lib/CodeGen/CodeGenTypes.cpp | 71 +- clang/lib/CodeGen/CoverageMappingGen.cpp | 350 +- clang/lib/CodeGen/CoverageMappingGen.h | 50 +- clang/lib/CodeGen/ItaniumCXXABI.cpp | 183 +- clang/lib/CodeGen/MicrosoftCXXABI.cpp | 103 +- .../CodeGen/ObjectFilePCHContainerOperations.cpp | 10 +- clang/lib/CodeGen/SwiftCallingConv.cpp | 33 +- clang/lib/CodeGen/TargetInfo.cpp | 624 +-- clang/lib/CodeGen/TargetInfo.h | 8 +- clang/lib/CrossTU/CrossTranslationUnit.cpp | 12 +- clang/lib/Driver/Compilation.cpp | 2 + clang/lib/Driver/Distro.cpp | 180 +- clang/lib/Driver/Driver.cpp | 347 +- clang/lib/Driver/Job.cpp | 22 +- clang/lib/Driver/SanitizerArgs.cpp | 42 +- clang/lib/Driver/ToolChain.cpp | 139 +- clang/lib/Driver/ToolChains/AIX.cpp | 62 +- clang/lib/Driver/ToolChains/AIX.h | 7 + clang/lib/Driver/ToolChains/AMDGPU.cpp | 136 +- clang/lib/Driver/ToolChains/AMDGPU.h | 14 +- clang/lib/Driver/ToolChains/AVR.cpp | 306 +- clang/lib/Driver/ToolChains/Ananas.cpp | 10 +- clang/lib/Driver/ToolChains/Arch/AArch64.cpp | 24 +- clang/lib/Driver/ToolChains/Arch/ARM.cpp | 261 +- clang/lib/Driver/ToolChains/Arch/ARM.h | 2 + clang/lib/Driver/ToolChains/Arch/Mips.cpp | 2 - clang/lib/Driver/ToolChains/Arch/PPC.cpp | 1 - clang/lib/Driver/ToolChains/Arch/RISCV.cpp | 125 +- clang/lib/Driver/ToolChains/Arch/Sparc.cpp | 9 +- clang/lib/Driver/ToolChains/Arch/VE.cpp | 4 - clang/lib/Driver/ToolChains/Arch/VE.h | 2 - clang/lib/Driver/ToolChains/Arch/X86.cpp | 35 +- clang/lib/Driver/ToolChains/Arch/X86.h | 2 +- clang/lib/Driver/ToolChains/BareMetal.cpp | 146 +- clang/lib/Driver/ToolChains/BareMetal.h | 15 +- clang/lib/Driver/ToolChains/Clang.cpp | 681 ++- clang/lib/Driver/ToolChains/CloudABI.cpp | 5 +- clang/lib/Driver/ToolChains/CommonArgs.cpp | 267 +- clang/lib/Driver/ToolChains/CommonArgs.h | 14 +- clang/lib/Driver/ToolChains/CrossWindows.cpp | 15 +- clang/lib/Driver/ToolChains/CrossWindows.h | 6 +- clang/lib/Driver/ToolChains/Cuda.cpp | 215 +- clang/lib/Driver/ToolChains/Cuda.h | 9 +- clang/lib/Driver/ToolChains/Darwin.cpp | 132 +- clang/lib/Driver/ToolChains/Darwin.h | 21 +- clang/lib/Driver/ToolChains/DragonFly.cpp | 16 +- clang/lib/Driver/ToolChains/Flang.cpp | 44 +- clang/lib/Driver/ToolChains/Flang.h | 9 + clang/lib/Driver/ToolChains/FreeBSD.cpp | 18 +- clang/lib/Driver/ToolChains/Fuchsia.cpp | 29 +- clang/lib/Driver/ToolChains/Fuchsia.h | 6 +- clang/lib/Driver/ToolChains/Gnu.cpp | 155 +- clang/lib/Driver/ToolChains/Gnu.h | 6 +- clang/lib/Driver/ToolChains/HIP.cpp | 58 +- clang/lib/Driver/ToolChains/Hexagon.cpp | 10 +- clang/lib/Driver/ToolChains/InterfaceStubs.cpp | 2 +- clang/lib/Driver/ToolChains/Linux.cpp | 36 +- clang/lib/Driver/ToolChains/MSP430.cpp | 159 +- clang/lib/Driver/ToolChains/MSP430.h | 13 + clang/lib/Driver/ToolChains/MSVC.cpp | 65 +- clang/lib/Driver/ToolChains/MinGW.cpp | 25 +- clang/lib/Driver/ToolChains/Minix.cpp | 10 +- clang/lib/Driver/ToolChains/Myriad.cpp | 10 +- clang/lib/Driver/ToolChains/NaCl.cpp | 5 +- clang/lib/Driver/ToolChains/NetBSD.cpp | 10 +- clang/lib/Driver/ToolChains/OpenBSD.cpp | 77 +- clang/lib/Driver/ToolChains/OpenBSD.h | 22 +- clang/lib/Driver/ToolChains/PS4CPU.cpp | 47 +- clang/lib/Driver/ToolChains/PS4CPU.h | 6 +- clang/lib/Driver/ToolChains/RISCVToolchain.cpp | 21 +- clang/lib/Driver/ToolChains/RISCVToolchain.h | 1 + clang/lib/Driver/ToolChains/ROCm.h | 13 +- clang/lib/Driver/ToolChains/Solaris.cpp | 4 +- clang/lib/Driver/ToolChains/Solaris.h | 5 + clang/lib/Driver/ToolChains/VEToolchain.cpp | 31 +- clang/lib/Driver/ToolChains/VEToolchain.h | 1 + clang/lib/Driver/ToolChains/WebAssembly.cpp | 28 +- clang/lib/Driver/ToolChains/XCore.cpp | 4 +- clang/lib/Driver/ToolChains/ZOS.cpp | 33 + clang/lib/Driver/ToolChains/ZOS.h | 40 + clang/lib/Driver/Types.cpp | 6 +- clang/lib/Driver/XRayArgs.cpp | 26 + clang/lib/Edit/EditedSource.cpp | 4 +- clang/lib/Edit/RewriteObjCFoundationAPI.cpp | 2 + clang/lib/Format/BreakableToken.cpp | 92 +- clang/lib/Format/BreakableToken.h | 1 - clang/lib/Format/ContinuationIndenter.cpp | 59 +- clang/lib/Format/Format.cpp | 167 +- clang/lib/Format/FormatInternal.h | 1 - clang/lib/Format/FormatToken.cpp | 5 +- clang/lib/Format/FormatToken.h | 281 +- clang/lib/Format/FormatTokenLexer.cpp | 23 +- clang/lib/Format/MacroExpander.cpp | 224 + clang/lib/Format/Macros.h | 141 + clang/lib/Format/TokenAnnotator.cpp | 263 +- clang/lib/Format/UnwrappedLineFormatter.cpp | 71 +- clang/lib/Format/UnwrappedLineParser.cpp | 252 +- clang/lib/Format/UnwrappedLineParser.h | 5 + clang/lib/Format/WhitespaceManager.cpp | 90 +- clang/lib/Frontend/ASTUnit.cpp | 103 +- clang/lib/Frontend/ChainedIncludesSource.cpp | 11 +- clang/lib/Frontend/CompilerInstance.cpp | 280 +- clang/lib/Frontend/CompilerInvocation.cpp | 2178 +++----- .../Frontend/CreateInvocationFromCommandLine.cpp | 4 +- clang/lib/Frontend/DependencyFile.cpp | 17 +- clang/lib/Frontend/FrontendAction.cpp | 19 +- clang/lib/Frontend/FrontendActions.cpp | 58 +- clang/lib/Frontend/FrontendOptions.cpp | 2 +- clang/lib/Frontend/FrontendTiming.cpp | 19 - clang/lib/Frontend/InitHeaderSearch.cpp | 2 + clang/lib/Frontend/InitPreprocessor.cpp | 32 +- clang/lib/Frontend/ModuleDependencyCollector.cpp | 52 +- clang/lib/Frontend/PrecompiledPreamble.cpp | 51 +- clang/lib/Frontend/Rewrite/HTMLPrint.cpp | 2 +- clang/lib/Frontend/Rewrite/InclusionRewriter.cpp | 78 +- clang/lib/Frontend/Rewrite/RewriteMacros.cpp | 2 +- clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp | 57 +- clang/lib/Frontend/Rewrite/RewriteObjC.cpp | 47 +- clang/lib/Frontend/TextDiagnostic.cpp | 5 +- clang/lib/Frontend/TextDiagnosticPrinter.cpp | 8 +- clang/lib/Frontend/VerifyDiagnosticConsumer.cpp | 12 +- clang/lib/Headers/__clang_cuda_builtin_vars.h | 9 + clang/lib/Headers/__clang_cuda_cmath.h | 50 +- clang/lib/Headers/__clang_cuda_complex_builtins.h | 36 +- clang/lib/Headers/__clang_cuda_math.h | 9 +- .../Headers/__clang_cuda_math_forward_declares.h | 3 + clang/lib/Headers/__clang_cuda_runtime_wrapper.h | 28 +- clang/lib/Headers/__clang_hip_cmath.h | 664 +++ clang/lib/Headers/__clang_hip_libdevice_declares.h | 26 +- clang/lib/Headers/__clang_hip_math.h | 1148 +++-- clang/lib/Headers/__clang_hip_runtime_wrapper.h | 5 + clang/lib/Headers/altivec.h | 1215 ++++- clang/lib/Headers/amxintrin.h | 97 +- clang/lib/Headers/arm_acle.h | 26 + clang/lib/Headers/avx512fintrin.h | 157 +- clang/lib/Headers/avx512vlvnniintrin.h | 205 +- clang/lib/Headers/avxintrin.h | 6 +- clang/lib/Headers/avxvnniintrin.h | 225 + clang/lib/Headers/cpuid.h | 8 + clang/lib/Headers/cuda_wrappers/algorithm | 2 +- clang/lib/Headers/cuda_wrappers/new | 10 +- clang/lib/Headers/emmintrin.h | 2 +- clang/lib/Headers/gfniintrin.h | 181 +- clang/lib/Headers/hresetintrin.h | 49 + clang/lib/Headers/ia32intrin.h | 97 +- clang/lib/Headers/immintrin.h | 12 + clang/lib/Headers/intrin.h | 169 +- clang/lib/Headers/keylockerintrin.h | 506 ++ clang/lib/Headers/mm_malloc.h | 6 + clang/lib/Headers/opencl-c-base.h | 18 + clang/lib/Headers/opencl-c.h | 2 + clang/lib/Headers/openmp_wrappers/cmath | 5 +- clang/lib/Headers/openmp_wrappers/complex | 27 + clang/lib/Headers/openmp_wrappers/complex.h | 2 + clang/lib/Headers/openmp_wrappers/complex_cmath.h | 388 ++ clang/lib/Headers/popcntintrin.h | 11 +- clang/lib/Headers/ppc_wrappers/smmintrin.h | 24 + clang/lib/Headers/uintrintrin.h | 150 + clang/lib/Headers/wasm_simd128.h | 112 +- clang/lib/Headers/x86gprintrin.h | 23 + clang/lib/Index/FileIndexRecord.cpp | 2 +- clang/lib/Index/IndexBody.cpp | 4 +- clang/lib/Index/IndexTypeSourceInfo.cpp | 21 + clang/lib/Index/IndexingAction.cpp | 11 +- clang/lib/Index/SimpleFormatContext.h | 72 - clang/lib/Index/USRGeneration.cpp | 3 + .../SerializablePathCollection.cpp | 91 + clang/lib/Lex/HeaderSearch.cpp | 58 +- clang/lib/Lex/Lexer.cpp | 49 +- clang/lib/Lex/LiteralSupport.cpp | 4 +- clang/lib/Lex/ModuleMap.cpp | 76 +- clang/lib/Lex/PPDirectives.cpp | 12 +- clang/lib/Lex/PPLexerChange.cpp | 27 +- clang/lib/Lex/PPMacroExpansion.cpp | 31 +- clang/lib/Lex/Pragma.cpp | 2 +- clang/lib/Lex/Preprocessor.cpp | 16 +- clang/lib/Lex/ScratchBuffer.cpp | 8 +- clang/lib/Lex/TokenLexer.cpp | 10 +- clang/lib/Parse/ParseCXXInlineMethods.cpp | 23 +- clang/lib/Parse/ParseDecl.cpp | 300 +- clang/lib/Parse/ParseDeclCXX.cpp | 107 +- clang/lib/Parse/ParseExpr.cpp | 96 +- clang/lib/Parse/ParseExprCXX.cpp | 71 +- clang/lib/Parse/ParseObjc.cpp | 37 +- clang/lib/Parse/ParseOpenMP.cpp | 456 +- clang/lib/Parse/ParsePragma.cpp | 311 +- clang/lib/Parse/ParseStmt.cpp | 57 +- clang/lib/Parse/ParseStmtAsm.cpp | 2 +- clang/lib/Parse/ParseTemplate.cpp | 21 +- clang/lib/Parse/ParseTentative.cpp | 13 +- clang/lib/Parse/Parser.cpp | 66 +- clang/lib/Rewrite/HTMLRewrite.cpp | 22 +- clang/lib/Rewrite/Rewriter.cpp | 8 +- clang/lib/Rewrite/TokenRewriter.cpp | 2 +- clang/lib/Sema/AnalysisBasedWarnings.cpp | 102 +- clang/lib/Sema/CodeCompleteConsumer.cpp | 6 +- clang/lib/Sema/DeclSpec.cpp | 167 +- clang/lib/Sema/JumpDiagnostics.cpp | 17 + clang/lib/Sema/MultiplexExternalSemaSource.cpp | 7 - clang/lib/Sema/ScopeInfo.cpp | 1 + clang/lib/Sema/Sema.cpp | 163 +- clang/lib/Sema/SemaAccess.cpp | 3 +- clang/lib/Sema/SemaAttr.cpp | 345 +- clang/lib/Sema/SemaCUDA.cpp | 103 +- clang/lib/Sema/SemaCast.cpp | 81 +- clang/lib/Sema/SemaChecking.cpp | 1029 +++- clang/lib/Sema/SemaCodeComplete.cpp | 90 +- clang/lib/Sema/SemaConcept.cpp | 23 +- clang/lib/Sema/SemaCoroutine.cpp | 100 +- clang/lib/Sema/SemaDecl.cpp | 1181 +++-- clang/lib/Sema/SemaDeclAttr.cpp | 1060 +++- clang/lib/Sema/SemaDeclCXX.cpp | 225 +- clang/lib/Sema/SemaDeclObjC.cpp | 76 +- clang/lib/Sema/SemaExceptionSpec.cpp | 4 +- clang/lib/Sema/SemaExpr.cpp | 1006 ++-- clang/lib/Sema/SemaExprCXX.cpp | 201 +- clang/lib/Sema/SemaExprMember.cpp | 119 +- clang/lib/Sema/SemaExprObjC.cpp | 88 +- clang/lib/Sema/SemaInit.cpp | 356 +- clang/lib/Sema/SemaLambda.cpp | 145 +- clang/lib/Sema/SemaLookup.cpp | 378 +- clang/lib/Sema/SemaModule.cpp | 2 +- clang/lib/Sema/SemaObjCProperty.cpp | 14 +- clang/lib/Sema/SemaOpenMP.cpp | 1065 ++-- clang/lib/Sema/SemaOverload.cpp | 978 ++-- clang/lib/Sema/SemaSYCL.cpp | 20 +- clang/lib/Sema/SemaStmt.cpp | 217 +- clang/lib/Sema/SemaStmtAsm.cpp | 6 +- clang/lib/Sema/SemaStmtAttr.cpp | 78 +- clang/lib/Sema/SemaTemplate.cpp | 637 ++- clang/lib/Sema/SemaTemplateDeduction.cpp | 379 +- clang/lib/Sema/SemaTemplateInstantiate.cpp | 187 +- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 421 +- clang/lib/Sema/SemaTemplateVariadic.cpp | 63 +- clang/lib/Sema/SemaType.cpp | 1220 ++--- clang/lib/Sema/TreeTransform.h | 205 +- clang/lib/Sema/UsedDeclVisitor.h | 11 +- clang/lib/Serialization/ASTCommon.cpp | 6 + clang/lib/Serialization/ASTReader.cpp | 434 +- clang/lib/Serialization/ASTReaderDecl.cpp | 166 +- clang/lib/Serialization/ASTReaderStmt.cpp | 365 +- clang/lib/Serialization/ASTWriter.cpp | 183 +- clang/lib/Serialization/ASTWriterDecl.cpp | 59 +- clang/lib/Serialization/ASTWriterStmt.cpp | 158 +- clang/lib/Serialization/GlobalModuleIndex.cpp | 7 +- clang/lib/Serialization/ModuleManager.cpp | 61 +- .../Checkers/BasicObjCFoundationChecks.cpp | 3 +- .../StaticAnalyzer/Checkers/CastValueChecker.cpp | 142 +- .../StaticAnalyzer/Checkers/CheckObjCDealloc.cpp | 2 +- .../lib/StaticAnalyzer/Checkers/DebugCheckers.cpp | 10 +- .../StaticAnalyzer/Checkers/DereferenceChecker.cpp | 69 +- .../Checkers/ExprInspectionChecker.cpp | 4 +- .../Checkers/FuchsiaHandleChecker.cpp | 312 +- .../Checkers/GenericTaintChecker.cpp | 5 +- .../StaticAnalyzer/Checkers/IteratorModeling.cpp | 103 +- .../Checkers/IteratorRangeChecker.cpp | 2 + .../Checkers/LocalizationChecker.cpp | 7 +- .../Checkers/MacOSKeychainAPIChecker.cpp | 2 +- .../lib/StaticAnalyzer/Checkers/MallocChecker.cpp | 15 +- clang/lib/StaticAnalyzer/Checkers/MoveChecker.cpp | 4 +- .../StaticAnalyzer/Checkers/OSObjectCStyleCast.cpp | 21 +- .../Checkers/ObjCMissingSuperCallChecker.cpp | 7 +- .../lib/StaticAnalyzer/Checkers/PaddingChecker.cpp | 5 +- .../StaticAnalyzer/Checkers/PthreadLockChecker.cpp | 271 +- .../RetainCountChecker/RetainCountDiagnostics.cpp | 4 +- .../Checkers/ReturnPointerRangeChecker.cpp | 7 +- clang/lib/StaticAnalyzer/Checkers/SmartPtr.h | 2 + .../StaticAnalyzer/Checkers/SmartPtrChecker.cpp | 48 +- .../StaticAnalyzer/Checkers/SmartPtrModeling.cpp | 514 +- .../Checkers/StdLibraryFunctionsChecker.cpp | 2058 +++++--- .../lib/StaticAnalyzer/Checkers/StreamChecker.cpp | 70 +- clang/lib/StaticAnalyzer/Checkers/Taint.cpp | 2 +- .../StaticAnalyzer/Checkers/UndefBranchChecker.cpp | 7 +- .../StaticAnalyzer/Checkers/VirtualCallChecker.cpp | 4 +- .../StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp | 4 +- .../Checkers/WebKit/NoUncountedMembersChecker.cpp | 7 +- .../Checkers/WebKit/PtrTypesSemantics.cpp | 58 +- .../Checkers/WebKit/PtrTypesSemantics.h | 23 +- .../WebKit/RefCntblBaseVirtualDtorChecker.cpp | 12 +- .../Checkers/WebKit/UncountedCallArgsChecker.cpp | 3 +- .../WebKit/UncountedLambdaCapturesChecker.cpp | 107 + .../Checkers/WebKit/UncountedLocalVarsChecker.cpp | 251 + clang/lib/StaticAnalyzer/Checkers/Yaml.h | 0 clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp | 2 +- .../lib/StaticAnalyzer/Core/BasicValueFactory.cpp | 25 +- clang/lib/StaticAnalyzer/Core/BugReporter.cpp | 13 +- .../StaticAnalyzer/Core/BugReporterVisitors.cpp | 7 +- clang/lib/StaticAnalyzer/Core/CallEvent.cpp | 2 +- clang/lib/StaticAnalyzer/Core/CheckerContext.cpp | 2 +- clang/lib/StaticAnalyzer/Core/DynamicType.cpp | 13 + clang/lib/StaticAnalyzer/Core/Environment.cpp | 21 +- clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | 153 +- clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp | 7 +- clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp | 26 +- .../Core/ExprEngineCallAndReturn.cpp | 14 +- clang/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp | 13 +- clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp | 47 +- clang/lib/StaticAnalyzer/Core/IssueHash.cpp | 204 - clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp | 400 +- clang/lib/StaticAnalyzer/Core/ProgramState.cpp | 3 - .../StaticAnalyzer/Core/RangeConstraintManager.cpp | 1114 ++++- .../Core/RangedConstraintManager.cpp | 41 +- clang/lib/StaticAnalyzer/Core/SValBuilder.cpp | 23 +- clang/lib/StaticAnalyzer/Core/SVals.cpp | 48 +- clang/lib/StaticAnalyzer/Core/SarifDiagnostics.cpp | 16 +- .../Core/SimpleConstraintManager.cpp | 4 +- .../lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp | 19 +- clang/lib/StaticAnalyzer/Core/SymbolManager.cpp | 28 +- clang/lib/StaticAnalyzer/Core/TextDiagnostics.cpp | 49 +- .../StaticAnalyzer/Frontend/AnalysisConsumer.cpp | 4 +- clang/lib/Tooling/AllTUsExecution.cpp | 2 +- clang/lib/Tooling/ArgumentsAdjusters.cpp | 34 +- clang/lib/Tooling/CompilationDatabase.cpp | 58 +- clang/lib/Tooling/Core/Lookup.cpp | 224 - clang/lib/Tooling/Core/Replacement.cpp | 2 +- .../DependencyScanningFilesystem.cpp | 20 +- .../DependencyScanningWorker.cpp | 24 +- .../DependencyScanning/ModuleDepCollector.cpp | 13 +- clang/lib/Tooling/FileMatchTrie.cpp | 14 +- clang/lib/Tooling/Inclusions/HeaderIncludes.cpp | 52 +- clang/lib/Tooling/Inclusions/IncludeStyle.cpp | 1 + clang/lib/Tooling/JSONCompilationDatabase.cpp | 48 +- clang/lib/Tooling/Refactoring/ASTSelection.cpp | 2 +- clang/lib/Tooling/Refactoring/Lookup.cpp | 224 + .../lib/Tooling/Refactoring/RefactoringActions.cpp | 4 +- .../Refactoring/Rename/SymbolOccurrences.cpp | 5 +- clang/lib/Tooling/Refactoring/Rename/USRFinder.cpp | 4 +- .../Refactoring/Rename/USRFindingAction.cpp | 52 +- .../Tooling/Refactoring/Rename/USRLocFinder.cpp | 2 +- clang/lib/Tooling/Syntax/BuildTree.cpp | 819 ++- clang/lib/Tooling/Syntax/ComputeReplacements.cpp | 15 +- clang/lib/Tooling/Syntax/Mutations.cpp | 36 +- clang/lib/Tooling/Syntax/Nodes.cpp | 604 +-- clang/lib/Tooling/Syntax/Synthesis.cpp | 224 +- clang/lib/Tooling/Syntax/Tokens.cpp | 89 +- clang/lib/Tooling/Syntax/Tree.cpp | 412 +- clang/lib/Tooling/Tooling.cpp | 71 +- clang/lib/Tooling/Transformer/Parsing.cpp | 8 +- clang/lib/Tooling/Transformer/RangeSelector.cpp | 26 +- clang/lib/Tooling/Transformer/RewriteRule.cpp | 262 +- clang/lib/Tooling/Transformer/Stencil.cpp | 77 +- clang/lib/Tooling/Transformer/Transformer.cpp | 42 +- 513 files changed, 52402 insertions(+), 27565 deletions(-) create mode 100644 clang/lib/APINotes/APINotesFormat.h create mode 100644 clang/lib/APINotes/APINotesTypes.cpp create mode 100644 clang/lib/APINotes/APINotesYAMLCompiler.cpp create mode 100644 clang/lib/Analysis/CalledOnceCheck.cpp create mode 100644 clang/lib/Analysis/IssueHash.cpp create mode 100644 clang/lib/Basic/FileEntry.cpp delete mode 100644 clang/lib/Basic/FixedPoint.cpp create mode 100644 clang/lib/Basic/OpenCLOptions.cpp create mode 100644 clang/lib/Basic/ProfileList.cpp create mode 100644 clang/lib/Basic/TargetID.cpp create mode 100644 clang/lib/CodeGen/CGOpenMPRuntimeAMDGCN.cpp create mode 100644 clang/lib/CodeGen/CGOpenMPRuntimeAMDGCN.h create mode 100644 clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp create mode 100644 clang/lib/CodeGen/CGOpenMPRuntimeGPU.h create mode 100644 clang/lib/Driver/ToolChains/ZOS.cpp create mode 100644 clang/lib/Driver/ToolChains/ZOS.h create mode 100644 clang/lib/Format/MacroExpander.cpp create mode 100644 clang/lib/Format/Macros.h mode change 100644 => 100755 clang/lib/Format/TokenAnnotator.cpp delete mode 100644 clang/lib/Frontend/FrontendTiming.cpp create mode 100644 clang/lib/Headers/__clang_hip_cmath.h create mode 100644 clang/lib/Headers/avxvnniintrin.h create mode 100644 clang/lib/Headers/hresetintrin.h create mode 100644 clang/lib/Headers/keylockerintrin.h create mode 100644 clang/lib/Headers/openmp_wrappers/complex_cmath.h create mode 100644 clang/lib/Headers/uintrintrin.h create mode 100644 clang/lib/Headers/x86gprintrin.h delete mode 100644 clang/lib/Index/SimpleFormatContext.h create mode 100644 clang/lib/IndexSerialization/SerializablePathCollection.cpp create mode 100644 clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedLambdaCapturesChecker.cpp create mode 100644 clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedLocalVarsChecker.cpp mode change 100755 => 100644 clang/lib/StaticAnalyzer/Checkers/Yaml.h delete mode 100644 clang/lib/StaticAnalyzer/Core/IssueHash.cpp delete mode 100644 clang/lib/Tooling/Core/Lookup.cpp create mode 100644 clang/lib/Tooling/Refactoring/Lookup.cpp (limited to 'clang/lib') diff --git a/clang/lib/APINotes/APINotesFormat.h b/clang/lib/APINotes/APINotesFormat.h new file mode 100644 index 000000000000..6b76ecfc2567 --- /dev/null +++ b/clang/lib/APINotes/APINotesFormat.h @@ -0,0 +1,255 @@ +//===-- APINotesWriter.h - API Notes Writer ---------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LIB_APINOTES_APINOTESFORMAT_H +#define LLVM_CLANG_LIB_APINOTES_APINOTESFORMAT_H + +#include "llvm/ADT/PointerEmbeddedInt.h" +#include "llvm/Bitcode/BitcodeConvenience.h" + +namespace clang { +namespace api_notes { +/// Magic number for API notes files. +const unsigned char API_NOTES_SIGNATURE[] = {0xE2, 0x9C, 0xA8, 0x01}; + +/// API notes file major version number. +const uint16_t VERSION_MAJOR = 0; + +/// API notes file minor version number. +/// +/// When the format changes IN ANY WAY, this number should be incremented. +const uint16_t VERSION_MINOR = 24; // EnumExtensibility + FlagEnum + +using IdentifierID = llvm::PointerEmbeddedInt; +using IdentifierIDField = llvm::BCVBR<16>; + +using SelectorID = llvm::PointerEmbeddedInt; +using SelectorIDField = llvm::BCVBR<16>; + +/// The various types of blocks that can occur within a API notes file. +/// +/// These IDs must \em not be renumbered or reordered without incrementing +/// VERSION_MAJOR. +enum BlockID { + /// The control block, which contains all of the information that needs to + /// be validated prior to committing to loading the API notes file. + /// + /// \sa control_block + CONTROL_BLOCK_ID = llvm::bitc::FIRST_APPLICATION_BLOCKID, + + /// The identifier data block, which maps identifier strings to IDs. + IDENTIFIER_BLOCK_ID, + + /// The Objective-C context data block, which contains information about + /// Objective-C classes and protocols. + OBJC_CONTEXT_BLOCK_ID, + + /// The Objective-C property data block, which maps Objective-C + /// (class name, property name) pairs to information about the + /// property. + OBJC_PROPERTY_BLOCK_ID, + + /// The Objective-C property data block, which maps Objective-C + /// (class name, selector, is_instance_method) tuples to information + /// about the method. + OBJC_METHOD_BLOCK_ID, + + /// The Objective-C selector data block, which maps Objective-C + /// selector names (# of pieces, identifier IDs) to the selector ID + /// used in other tables. + OBJC_SELECTOR_BLOCK_ID, + + /// The global variables data block, which maps global variable names to + /// information about the global variable. + GLOBAL_VARIABLE_BLOCK_ID, + + /// The (global) functions data block, which maps global function names to + /// information about the global function. + GLOBAL_FUNCTION_BLOCK_ID, + + /// The tag data block, which maps tag names to information about + /// the tags. + TAG_BLOCK_ID, + + /// The typedef data block, which maps typedef names to information about + /// the typedefs. + TYPEDEF_BLOCK_ID, + + /// The enum constant data block, which maps enumerator names to + /// information about the enumerators. + ENUM_CONSTANT_BLOCK_ID, +}; + +namespace control_block { +// These IDs must \em not be renumbered or reordered without incrementing +// VERSION_MAJOR. +enum { + METADATA = 1, + MODULE_NAME = 2, + MODULE_OPTIONS = 3, + SOURCE_FILE = 4, +}; + +using MetadataLayout = + llvm::BCRecordLayout, // Module format major version + llvm::BCFixed<16> // Module format minor version + >; + +using ModuleNameLayout = llvm::BCRecordLayout; + +using ModuleOptionsLayout = + llvm::BCRecordLayout // SwiftInferImportAsMember + >; + +using SourceFileLayout = llvm::BCRecordLayout, // file size + llvm::BCVBR<16> // creation time + >; +} // namespace control_block + +namespace identifier_block { +enum { + IDENTIFIER_DATA = 1, +}; + +using IdentifierDataLayout = llvm::BCRecordLayout< + IDENTIFIER_DATA, // record ID + llvm::BCVBR<16>, // table offset within the blob (see below) + llvm::BCBlob // map from identifier strings to decl kinds / decl IDs + >; +} // namespace identifier_block + +namespace objc_context_block { +enum { + OBJC_CONTEXT_ID_DATA = 1, + OBJC_CONTEXT_INFO_DATA = 2, +}; + +using ObjCContextIDLayout = + llvm::BCRecordLayout, // table offset within the blob (see + // below) + llvm::BCBlob // map from ObjC class names/protocol (as + // IDs) to context IDs + >; + +using ObjCContextInfoLayout = llvm::BCRecordLayout< + OBJC_CONTEXT_INFO_DATA, // record ID + llvm::BCVBR<16>, // table offset within the blob (see below) + llvm::BCBlob // map from ObjC context IDs to context information. + >; +} // namespace objc_context_block + +namespace objc_property_block { +enum { + OBJC_PROPERTY_DATA = 1, +}; + +using ObjCPropertyDataLayout = llvm::BCRecordLayout< + OBJC_PROPERTY_DATA, // record ID + llvm::BCVBR<16>, // table offset within the blob (see below) + llvm::BCBlob // map from ObjC (class name, property name) pairs to + // ObjC property information + >; +} // namespace objc_property_block + +namespace objc_method_block { +enum { + OBJC_METHOD_DATA = 1, +}; + +using ObjCMethodDataLayout = + llvm::BCRecordLayout, // table offset within the blob (see + // below) + llvm::BCBlob // map from ObjC (class names, selector, + // is-instance-method) tuples to ObjC + // method information + >; +} // namespace objc_method_block + +namespace objc_selector_block { +enum { + OBJC_SELECTOR_DATA = 1, +}; + +using ObjCSelectorDataLayout = + llvm::BCRecordLayout, // table offset within the blob (see + // below) + llvm::BCBlob // map from (# pieces, identifier IDs) to + // Objective-C selector ID. + >; +} // namespace objc_selector_block + +namespace global_variable_block { +enum { GLOBAL_VARIABLE_DATA = 1 }; + +using GlobalVariableDataLayout = llvm::BCRecordLayout< + GLOBAL_VARIABLE_DATA, // record ID + llvm::BCVBR<16>, // table offset within the blob (see below) + llvm::BCBlob // map from name to global variable information + >; +} // namespace global_variable_block + +namespace global_function_block { +enum { GLOBAL_FUNCTION_DATA = 1 }; + +using GlobalFunctionDataLayout = llvm::BCRecordLayout< + GLOBAL_FUNCTION_DATA, // record ID + llvm::BCVBR<16>, // table offset within the blob (see below) + llvm::BCBlob // map from name to global function information + >; +} // namespace global_function_block + +namespace tag_block { +enum { TAG_DATA = 1 }; + +using TagDataLayout = + llvm::BCRecordLayout, // table offset within the blob (see + // below) + llvm::BCBlob // map from name to tag information + >; +}; // namespace tag_block + +namespace typedef_block { +enum { TYPEDEF_DATA = 1 }; + +using TypedefDataLayout = + llvm::BCRecordLayout, // table offset within the blob (see + // below) + llvm::BCBlob // map from name to typedef information + >; +}; // namespace typedef_block + +namespace enum_constant_block { +enum { ENUM_CONSTANT_DATA = 1 }; + +using EnumConstantDataLayout = + llvm::BCRecordLayout, // table offset within the blob (see + // below) + llvm::BCBlob // map from name to enumerator information + >; +} // namespace enum_constant_block + +/// A stored Objective-C selector. +struct StoredObjCSelector { + unsigned NumPieces; + llvm::SmallVector Identifiers; +}; +} // namespace api_notes +} // namespace clang + +#endif diff --git a/clang/lib/APINotes/APINotesTypes.cpp b/clang/lib/APINotes/APINotesTypes.cpp new file mode 100644 index 000000000000..c0bb726ea72b --- /dev/null +++ b/clang/lib/APINotes/APINotesTypes.cpp @@ -0,0 +1,107 @@ +//===-- APINotesTypes.cpp - API Notes Data Types ----------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "clang/APINotes/Types.h" +#include "llvm/Support/raw_ostream.h" + +namespace clang { +namespace api_notes { +LLVM_DUMP_METHOD void CommonEntityInfo::dump(llvm::raw_ostream &OS) const { + if (Unavailable) + OS << "[Unavailable] (" << UnavailableMsg << ")" << ' '; + if (UnavailableInSwift) + OS << "[UnavailableInSwift] "; + if (SwiftPrivateSpecified) + OS << (SwiftPrivate ? "[SwiftPrivate] " : ""); + if (!SwiftName.empty()) + OS << "Swift Name: " << SwiftName << ' '; + OS << '\n'; +} + +LLVM_DUMP_METHOD void CommonTypeInfo::dump(llvm::raw_ostream &OS) const { + static_cast(*this).dump(OS); + if (SwiftBridge) + OS << "Swift Briged Type: " << *SwiftBridge << ' '; + if (NSErrorDomain) + OS << "NSError Domain: " << *NSErrorDomain << ' '; + OS << '\n'; +} + +LLVM_DUMP_METHOD void ObjCContextInfo::dump(llvm::raw_ostream &OS) { + static_cast(*this).dump(OS); + if (HasDefaultNullability) + OS << "DefaultNullability: " << DefaultNullability << ' '; + if (HasDesignatedInits) + OS << "[HasDesignatedInits] "; + if (SwiftImportAsNonGenericSpecified) + OS << (SwiftImportAsNonGeneric ? "[SwiftImportAsNonGeneric] " : ""); + if (SwiftObjCMembersSpecified) + OS << (SwiftObjCMembers ? "[SwiftObjCMembers] " : ""); + OS << '\n'; +} + +LLVM_DUMP_METHOD void VariableInfo::dump(llvm::raw_ostream &OS) const { + static_cast(*this).dump(OS); + if (NullabilityAudited) + OS << "Audited Nullability: " << Nullable << ' '; + if (!Type.empty()) + OS << "C Type: " << Type << ' '; + OS << '\n'; +} + +LLVM_DUMP_METHOD void ObjCPropertyInfo::dump(llvm::raw_ostream &OS) const { + static_cast(*this).dump(OS); + if (SwiftImportAsAccessorsSpecified) + OS << (SwiftImportAsAccessors ? "[SwiftImportAsAccessors] " : ""); + OS << '\n'; +} + +LLVM_DUMP_METHOD void ParamInfo::dump(llvm::raw_ostream &OS) const { + static_cast(*this).dump(OS); + if (NoEscapeSpecified) + OS << (NoEscape ? "[NoEscape] " : ""); + OS << "RawRetainCountConvention: " << RawRetainCountConvention << ' '; + OS << '\n'; +} + +LLVM_DUMP_METHOD void FunctionInfo::dump(llvm::raw_ostream &OS) const { + static_cast(*this).dump(OS); + OS << (NullabilityAudited ? "[NullabilityAudited] " : "") + << "RawRetainCountConvention: " << RawRetainCountConvention << ' '; + if (!ResultType.empty()) + OS << "Result Type: " << ResultType << ' '; + if (!Params.empty()) + OS << '\n'; + for (auto &PI : Params) + PI.dump(OS); +} + +LLVM_DUMP_METHOD void ObjCMethodInfo::dump(llvm::raw_ostream &OS) { + static_cast(*this).dump(OS); + OS << (DesignatedInit ? "[DesignatedInit] " : "") + << (RequiredInit ? "[RequiredInit] " : "") << '\n'; +} + +LLVM_DUMP_METHOD void TagInfo::dump(llvm::raw_ostream &OS) { + static_cast(*this).dump(OS); + if (HasFlagEnum) + OS << (IsFlagEnum ? "[FlagEnum] " : ""); + if (EnumExtensibility) + OS << "Enum Extensibility: " << static_cast(*EnumExtensibility) + << ' '; + OS << '\n'; +} + +LLVM_DUMP_METHOD void TypedefInfo::dump(llvm::raw_ostream &OS) const { + static_cast(*this).dump(OS); + if (SwiftWrapper) + OS << "Swift Type: " << static_cast(*SwiftWrapper) << ' '; + OS << '\n'; +} +} // namespace api_notes +} // namespace clang diff --git a/clang/lib/APINotes/APINotesYAMLCompiler.cpp b/clang/lib/APINotes/APINotesYAMLCompiler.cpp new file mode 100644 index 000000000000..a4120120a01c --- /dev/null +++ b/clang/lib/APINotes/APINotesYAMLCompiler.cpp @@ -0,0 +1,598 @@ +//===-- APINotesYAMLCompiler.cpp - API Notes YAML Format Reader -*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// The types defined locally are designed to represent the YAML state, which +// adds an additional bit of state: e.g. a tri-state boolean attribute (yes, no, +// not applied) becomes a tri-state boolean + present. As a result, while these +// enumerations appear to be redefining constants from the attributes table +// data, they are distinct. +// + +#include "clang/APINotes/APINotesYAMLCompiler.h" +#include "clang/APINotes/Types.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/Specifiers.h" +#include "llvm/ADT/Optional.h" +#include "llvm/Support/VersionTuple.h" +#include "llvm/Support/YAMLParser.h" +#include "llvm/Support/YAMLTraits.h" +#include +using namespace clang; +using namespace api_notes; + +namespace { +enum class APIAvailability { + Available = 0, + OSX, + IOS, + None, + NonSwift, +}; +} // namespace + +namespace llvm { +namespace yaml { +template <> struct ScalarEnumerationTraits { + static void enumeration(IO &IO, APIAvailability &AA) { + IO.enumCase(AA, "OSX", APIAvailability::OSX); + IO.enumCase(AA, "iOS", APIAvailability::IOS); + IO.enumCase(AA, "none", APIAvailability::None); + IO.enumCase(AA, "nonswift", APIAvailability::NonSwift); + IO.enumCase(AA, "available", APIAvailability::Available); + } +}; +} // namespace yaml +} // namespace llvm + +namespace { +enum class MethodKind { + Class, + Instance, +}; +} // namespace + +namespace llvm { +namespace yaml { +template <> struct ScalarEnumerationTraits { + static void enumeration(IO &IO, MethodKind &MK) { + IO.enumCase(MK, "Class", MethodKind::Class); + IO.enumCase(MK, "Instance", MethodKind::Instance); + } +}; +} // namespace yaml +} // namespace llvm + +namespace { +struct Param { + unsigned Position; + Optional NoEscape = false; + Optional Nullability; + Optional RetainCountConvention; + StringRef Type; +}; + +typedef std::vector ParamsSeq; +} // namespace + +LLVM_YAML_IS_SEQUENCE_VECTOR(Param) +LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(NullabilityKind) + +namespace llvm { +namespace yaml { +template <> struct ScalarEnumerationTraits { + static void enumeration(IO &IO, NullabilityKind &NK) { + IO.enumCase(NK, "Nonnull", NullabilityKind::NonNull); + IO.enumCase(NK, "Optional", NullabilityKind::Nullable); + IO.enumCase(NK, "Unspecified", NullabilityKind::Unspecified); + IO.enumCase(NK, "NullableResult", NullabilityKind::NullableResult); + // TODO: Mapping this to it's own value would allow for better cross + // checking. Also the default should be Unknown. + IO.enumCase(NK, "Scalar", NullabilityKind::Unspecified); + + // Aliases for compatibility with existing APINotes. + IO.enumCase(NK, "N", NullabilityKind::NonNull); + IO.enumCase(NK, "O", NullabilityKind::Nullable); + IO.enumCase(NK, "U", NullabilityKind::Unspecified); + IO.enumCase(NK, "S", NullabilityKind::Unspecified); + } +}; + +template <> struct ScalarEnumerationTraits { + static void enumeration(IO &IO, RetainCountConventionKind &RCCK) { + IO.enumCase(RCCK, "none", RetainCountConventionKind::None); + IO.enumCase(RCCK, "CFReturnsRetained", + RetainCountConventionKind::CFReturnsRetained); + IO.enumCase(RCCK, "CFReturnsNotRetained", + RetainCountConventionKind::CFReturnsNotRetained); + IO.enumCase(RCCK, "NSReturnsRetained", + RetainCountConventionKind::NSReturnsRetained); + IO.enumCase(RCCK, "NSReturnsNotRetained", + RetainCountConventionKind::NSReturnsNotRetained); + } +}; + +template <> struct MappingTraits { + static void mapping(IO &IO, Param &P) { + IO.mapRequired("Position", P.Position); + IO.mapOptional("Nullability", P.Nullability, llvm::None); + IO.mapOptional("RetainCountConvention", P.RetainCountConvention); + IO.mapOptional("NoEscape", P.NoEscape); + IO.mapOptional("Type", P.Type, StringRef("")); + } +}; +} // namespace yaml +} // namespace llvm + +namespace { +typedef std::vector NullabilitySeq; + +struct AvailabilityItem { + APIAvailability Mode = APIAvailability::Available; + StringRef Msg; +}; + +/// Old attribute deprecated in favor of SwiftName. +enum class FactoryAsInitKind { + /// Infer based on name and type (the default). + Infer, + /// Treat as a class method. + AsClassMethod, + /// Treat as an initializer. + AsInitializer, +}; + +struct Method { + StringRef Selector; + MethodKind Kind; + ParamsSeq Params; + NullabilitySeq Nullability; + Optional NullabilityOfRet; + Optional RetainCountConvention; + AvailabilityItem Availability; + Optional SwiftPrivate; + StringRef SwiftName; + FactoryAsInitKind FactoryAsInit = FactoryAsInitKind::Infer; + bool DesignatedInit = false; + bool Required = false; + StringRef ResultType; +}; + +typedef std::vector MethodsSeq; +} // namespace + +LLVM_YAML_IS_SEQUENCE_VECTOR(Method) + +namespace llvm { +namespace yaml { +template <> struct ScalarEnumerationTraits { + static void enumeration(IO &IO, FactoryAsInitKind &FIK) { + IO.enumCase(FIK, "A", FactoryAsInitKind::Infer); + IO.enumCase(FIK, "C", FactoryAsInitKind::AsClassMethod); + IO.enumCase(FIK, "I", FactoryAsInitKind::AsInitializer); + } +}; + +template <> struct MappingTraits { + static void mapping(IO &IO, Method &M) { + IO.mapRequired("Selector", M.Selector); + IO.mapRequired("MethodKind", M.Kind); + IO.mapOptional("Parameters", M.Params); + IO.mapOptional("Nullability", M.Nullability); + IO.mapOptional("NullabilityOfRet", M.NullabilityOfRet, llvm::None); + IO.mapOptional("RetainCountConvention", M.RetainCountConvention); + IO.mapOptional("Availability", M.Availability.Mode, + APIAvailability::Available); + IO.mapOptional("AvailabilityMsg", M.Availability.Msg, StringRef("")); + IO.mapOptional("SwiftPrivate", M.SwiftPrivate); + IO.mapOptional("SwiftName", M.SwiftName, StringRef("")); + IO.mapOptional("FactoryAsInit", M.FactoryAsInit, FactoryAsInitKind::Infer); + IO.mapOptional("DesignatedInit", M.DesignatedInit, false); + IO.mapOptional("Required", M.Required, false); + IO.mapOptional("ResultType", M.ResultType, StringRef("")); + } +}; +} // namespace yaml +} // namespace llvm + +namespace { +struct Property { + StringRef Name; + llvm::Optional Kind; + llvm::Optional Nullability; + AvailabilityItem Availability; + Optional SwiftPrivate; + StringRef SwiftName; + Optional SwiftImportAsAccessors; + StringRef Type; +}; + +typedef std::vector PropertiesSeq; +} // namespace + +LLVM_YAML_IS_SEQUENCE_VECTOR(Property) + +namespace llvm { +namespace yaml { +template <> struct MappingTraits { + static void mapping(IO &IO, Property &P) { + IO.mapRequired("Name", P.Name); + IO.mapOptional("PropertyKind", P.Kind); + IO.mapOptional("Nullability", P.Nullability, llvm::None); + IO.mapOptional("Availability", P.Availability.Mode, + APIAvailability::Available); + IO.mapOptional("AvailabilityMsg", P.Availability.Msg, StringRef("")); + IO.mapOptional("SwiftPrivate", P.SwiftPrivate); + IO.mapOptional("SwiftName", P.SwiftName, StringRef("")); + IO.mapOptional("SwiftImportAsAccessors", P.SwiftImportAsAccessors); + IO.mapOptional("Type", P.Type, StringRef("")); + } +}; +} // namespace yaml +} // namespace llvm + +namespace { +struct Class { + StringRef Name; + bool AuditedForNullability = false; + AvailabilityItem Availability; + Optional SwiftPrivate; + StringRef SwiftName; + Optional SwiftBridge; + Optional NSErrorDomain; + Optional SwiftImportAsNonGeneric; + Optional SwiftObjCMembers; + MethodsSeq Methods; + PropertiesSeq Properties; +}; + +typedef std::vector ClassesSeq; +} // namespace + +LLVM_YAML_IS_SEQUENCE_VECTOR(Class) + +namespace llvm { +namespace yaml { +template <> struct MappingTraits { + static void mapping(IO &IO, Class &C) { + IO.mapRequired("Name", C.Name); + IO.mapOptional("AuditedForNullability", C.AuditedForNullability, false); + IO.mapOptional("Availability", C.Availability.Mode, + APIAvailability::Available); + IO.mapOptional("AvailabilityMsg", C.Availability.Msg, StringRef("")); + IO.mapOptional("SwiftPrivate", C.SwiftPrivate); + IO.mapOptional("SwiftName", C.SwiftName, StringRef("")); + IO.mapOptional("SwiftBridge", C.SwiftBridge); + IO.mapOptional("NSErrorDomain", C.NSErrorDomain); + IO.mapOptional("SwiftImportAsNonGeneric", C.SwiftImportAsNonGeneric); + IO.mapOptional("SwiftObjCMembers", C.SwiftObjCMembers); + IO.mapOptional("Methods", C.Methods); + IO.mapOptional("Properties", C.Properties); + } +}; +} // namespace yaml +} // namespace llvm + +namespace { +struct Function { + StringRef Name; + ParamsSeq Params; + NullabilitySeq Nullability; + Optional NullabilityOfRet; + Optional RetainCountConvention; + AvailabilityItem Availability; + Optional SwiftPrivate; + StringRef SwiftName; + StringRef Type; + StringRef ResultType; +}; + +typedef std::vector FunctionsSeq; +} // namespace + +LLVM_YAML_IS_SEQUENCE_VECTOR(Function) + +namespace llvm { +namespace yaml { +template <> struct MappingTraits { + static void mapping(IO &IO, Function &F) { + IO.mapRequired("Name", F.Name); + IO.mapOptional("Parameters", F.Params); + IO.mapOptional("Nullability", F.Nullability); + IO.mapOptional("NullabilityOfRet", F.NullabilityOfRet, llvm::None); + IO.mapOptional("RetainCountConvention", F.RetainCountConvention); + IO.mapOptional("Availability", F.Availability.Mode, + APIAvailability::Available); + IO.mapOptional("AvailabilityMsg", F.Availability.Msg, StringRef("")); + IO.mapOptional("SwiftPrivate", F.SwiftPrivate); + IO.mapOptional("SwiftName", F.SwiftName, StringRef("")); + IO.mapOptional("ResultType", F.ResultType, StringRef("")); + } +}; +} // namespace yaml +} // namespace llvm + +namespace { +struct GlobalVariable { + StringRef Name; + llvm::Optional Nullability; + AvailabilityItem Availability; + Optional SwiftPrivate; + StringRef SwiftName; + StringRef Type; +}; + +typedef std::vector GlobalVariablesSeq; +} // namespace + +LLVM_YAML_IS_SEQUENCE_VECTOR(GlobalVariable) + +namespace llvm { +namespace yaml { +template <> struct MappingTraits { + static void mapping(IO &IO, GlobalVariable &GV) { + IO.mapRequired("Name", GV.Name); + IO.mapOptional("Nullability", GV.Nullability, llvm::None); + IO.mapOptional("Availability", GV.Availability.Mode, + APIAvailability::Available); + IO.mapOptional("AvailabilityMsg", GV.Availability.Msg, StringRef("")); + IO.mapOptional("SwiftPrivate", GV.SwiftPrivate); + IO.mapOptional("SwiftName", GV.SwiftName, StringRef("")); + IO.mapOptional("Type", GV.Type, StringRef("")); + } +}; +} // namespace yaml +} // namespace llvm + +namespace { +struct EnumConstant { + StringRef Name; + AvailabilityItem Availability; + Optional SwiftPrivate; + StringRef SwiftName; +}; + +typedef std::vector EnumConstantsSeq; +} // namespace + +LLVM_YAML_IS_SEQUENCE_VECTOR(EnumConstant) + +namespace llvm { +namespace yaml { +template <> struct MappingTraits { + static void mapping(IO &IO, EnumConstant &EC) { + IO.mapRequired("Name", EC.Name); + IO.mapOptional("Availability", EC.Availability.Mode, + APIAvailability::Available); + IO.mapOptional("AvailabilityMsg", EC.Availability.Msg, StringRef("")); + IO.mapOptional("SwiftPrivate", EC.SwiftPrivate); + IO.mapOptional("SwiftName", EC.SwiftName, StringRef("")); + } +}; +} // namespace yaml +} // namespace llvm + +namespace { +/// Syntactic sugar for EnumExtensibility and FlagEnum +enum class EnumConvenienceAliasKind { + /// EnumExtensibility: none, FlagEnum: false + None, + /// EnumExtensibility: open, FlagEnum: false + CFEnum, + /// EnumExtensibility: open, FlagEnum: true + CFOptions, + /// EnumExtensibility: closed, FlagEnum: false + CFClosedEnum +}; +} // namespace + +namespace llvm { +namespace yaml { +template <> struct ScalarEnumerationTraits { + static void enumeration(IO &IO, EnumConvenienceAliasKind &ECAK) { + IO.enumCase(ECAK, "none", EnumConvenienceAliasKind::None); + IO.enumCase(ECAK, "CFEnum", EnumConvenienceAliasKind::CFEnum); + IO.enumCase(ECAK, "NSEnum", EnumConvenienceAliasKind::CFEnum); + IO.enumCase(ECAK, "CFOptions", EnumConvenienceAliasKind::CFOptions); + IO.enumCase(ECAK, "NSOptions", EnumConvenienceAliasKind::CFOptions); + IO.enumCase(ECAK, "CFClosedEnum", EnumConvenienceAliasKind::CFClosedEnum); + IO.enumCase(ECAK, "NSClosedEnum", EnumConvenienceAliasKind::CFClosedEnum); + } +}; +} // namespace yaml +} // namespace llvm + +namespace { +struct Tag { + StringRef Name; + AvailabilityItem Availability; + StringRef SwiftName; + Optional SwiftPrivate; + Optional SwiftBridge; + Optional NSErrorDomain; + Optional EnumExtensibility; + Optional FlagEnum; + Optional EnumConvenienceKind; +}; + +typedef std::vector TagsSeq; +} // namespace + +LLVM_YAML_IS_SEQUENCE_VECTOR(Tag) + +namespace llvm { +namespace yaml { +template <> struct ScalarEnumerationTraits { + static void enumeration(IO &IO, EnumExtensibilityKind &EEK) { + IO.enumCase(EEK, "none", EnumExtensibilityKind::None); + IO.enumCase(EEK, "open", EnumExtensibilityKind::Open); + IO.enumCase(EEK, "closed", EnumExtensibilityKind::Closed); + } +}; + +template <> struct MappingTraits { + static void mapping(IO &IO, Tag &T) { + IO.mapRequired("Name", T.Name); + IO.mapOptional("Availability", T.Availability.Mode, + APIAvailability::Available); + IO.mapOptional("AvailabilityMsg", T.Availability.Msg, StringRef("")); + IO.mapOptional("SwiftPrivate", T.SwiftPrivate); + IO.mapOptional("SwiftName", T.SwiftName, StringRef("")); + IO.mapOptional("SwiftBridge", T.SwiftBridge); + IO.mapOptional("NSErrorDomain", T.NSErrorDomain); + IO.mapOptional("EnumExtensibility", T.EnumExtensibility); + IO.mapOptional("FlagEnum", T.FlagEnum); + IO.mapOptional("EnumKind", T.EnumConvenienceKind); + } +}; +} // namespace yaml +} // namespace llvm + +namespace { +struct Typedef { + StringRef Name; + AvailabilityItem Availability; + StringRef SwiftName; + Optional SwiftPrivate; + Optional SwiftBridge; + Optional NSErrorDomain; + Optional SwiftType; +}; + +typedef std::vector TypedefsSeq; +} // namespace + +LLVM_YAML_IS_SEQUENCE_VECTOR(Typedef) + +namespace llvm { +namespace yaml { +template <> struct ScalarEnumerationTraits { + static void enumeration(IO &IO, SwiftNewTypeKind &SWK) { + IO.enumCase(SWK, "none", SwiftNewTypeKind::None); + IO.enumCase(SWK, "struct", SwiftNewTypeKind::Struct); + IO.enumCase(SWK, "enum", SwiftNewTypeKind::Enum); + } +}; + +template <> struct MappingTraits { + static void mapping(IO &IO, Typedef &T) { + IO.mapRequired("Name", T.Name); + IO.mapOptional("Availability", T.Availability.Mode, + APIAvailability::Available); + IO.mapOptional("AvailabilityMsg", T.Availability.Msg, StringRef("")); + IO.mapOptional("SwiftPrivate", T.SwiftPrivate); + IO.mapOptional("SwiftName", T.SwiftName, StringRef("")); + IO.mapOptional("SwiftBridge", T.SwiftBridge); + IO.mapOptional("NSErrorDomain", T.NSErrorDomain); + IO.mapOptional("SwiftWrapper", T.SwiftType); + } +}; +} // namespace yaml +} // namespace llvm + +namespace { +struct TopLevelItems { + ClassesSeq Classes; + ClassesSeq Protocols; + FunctionsSeq Functions; + GlobalVariablesSeq Globals; + EnumConstantsSeq EnumConstants; + TagsSeq Tags; + TypedefsSeq Typedefs; +}; +} // namespace + +namespace llvm { +namespace yaml { +static void mapTopLevelItems(IO &IO, TopLevelItems &TLI) { + IO.mapOptional("Classes", TLI.Classes); + IO.mapOptional("Protocols", TLI.Protocols); + IO.mapOptional("Functions", TLI.Functions); + IO.mapOptional("Globals", TLI.Globals); + IO.mapOptional("Enumerators", TLI.EnumConstants); + IO.mapOptional("Tags", TLI.Tags); + IO.mapOptional("Typedefs", TLI.Typedefs); +} +} // namespace yaml +} // namespace llvm + +namespace { +struct Versioned { + VersionTuple Version; + TopLevelItems Items; +}; + +typedef std::vector VersionedSeq; +} // namespace + +LLVM_YAML_IS_SEQUENCE_VECTOR(Versioned) + +namespace llvm { +namespace yaml { +template <> struct MappingTraits { + static void mapping(IO &IO, Versioned &V) { + IO.mapRequired("Version", V.Version); + mapTopLevelItems(IO, V.Items); + } +}; +} // namespace yaml +} // namespace llvm + +namespace { +struct Module { + StringRef Name; + AvailabilityItem Availability; + TopLevelItems TopLevel; + VersionedSeq SwiftVersions; + + llvm::Optional SwiftInferImportAsMember = {llvm::None}; + + LLVM_DUMP_METHOD void dump() /*const*/; +}; +} // namespace + +namespace llvm { +namespace yaml { +template <> struct MappingTraits { + static void mapping(IO &IO, Module &M) { + IO.mapRequired("Name", M.Name); + IO.mapOptional("Availability", M.Availability.Mode, + APIAvailability::Available); + IO.mapOptional("AvailabilityMsg", M.Availability.Msg, StringRef("")); + IO.mapOptional("SwiftInferImportAsMember", M.SwiftInferImportAsMember); + mapTopLevelItems(IO, M.TopLevel); + IO.mapOptional("SwiftVersions", M.SwiftVersions); + } +}; +} // namespace yaml +} // namespace llvm + +void Module::dump() { + llvm::yaml::Output OS(llvm::errs()); + OS << *this; +} + +namespace { +bool parseAPINotes(StringRef YI, Module &M, llvm::SourceMgr::DiagHandlerTy Diag, + void *DiagContext) { + llvm::yaml::Input IS(YI, nullptr, Diag, DiagContext); + IS >> M; + return static_cast(IS.error()); +} +} // namespace + +bool clang::api_notes::parseAndDumpAPINotes(StringRef YI, + llvm::raw_ostream &OS) { + Module M; + if (parseAPINotes(YI, M, nullptr, nullptr)) + return true; + + llvm::yaml::Output YOS(OS); + YOS << M; + + return false; +} diff --git a/clang/lib/ARCMigrate/ARCMT.cpp b/clang/lib/ARCMigrate/ARCMT.cpp index e18def8a0b19..36fbe90e1e3a 100644 --- a/clang/lib/ARCMigrate/ARCMT.cpp +++ b/clang/lib/ARCMigrate/ARCMT.cpp @@ -416,9 +416,11 @@ bool arcmt::getFileRemappings(std::vector > & if (err) return true; - PreprocessorOptions PPOpts; - remapper.applyMappings(PPOpts); - remap = PPOpts.RemappedFiles; + remapper.forEachMapping( + [&](StringRef From, StringRef To) { + remap.push_back(std::make_pair(From.str(), To.str())); + }, + [](StringRef, const llvm::MemoryBufferRef &) {}); return false; } diff --git a/clang/lib/ARCMigrate/FileRemapper.cpp b/clang/lib/ARCMigrate/FileRemapper.cpp index 0222583c015b..f536af1795ed 100644 --- a/clang/lib/ARCMigrate/FileRemapper.cpp +++ b/clang/lib/ARCMigrate/FileRemapper.cpp @@ -190,6 +190,21 @@ bool FileRemapper::overwriteOriginal(DiagnosticsEngine &Diag, return false; } +void FileRemapper::forEachMapping( + llvm::function_ref CaptureFile, + llvm::function_ref + CaptureBuffer) const { + for (auto &Mapping : FromToMappings) { + if (const FileEntry *FE = Mapping.second.dyn_cast()) { + CaptureFile(Mapping.first->getName(), FE->getName()); + continue; + } + CaptureBuffer( + Mapping.first->getName(), + Mapping.second.get()->getMemBufferRef()); + } +} + void FileRemapper::applyMappings(PreprocessorOptions &PPOpts) const { for (MappingsTy::const_iterator I = FromToMappings.begin(), E = FromToMappings.end(); I != E; ++I) { diff --git a/clang/lib/ARCMigrate/ObjCMT.cpp b/clang/lib/ARCMigrate/ObjCMT.cpp index 51c4a460cc25..68a51a49c718 100644 --- a/clang/lib/ARCMigrate/ObjCMT.cpp +++ b/clang/lib/ARCMigrate/ObjCMT.cpp @@ -156,7 +156,7 @@ protected: return WhiteListFilenames.find(llvm::sys::path::filename(Path)) != WhiteListFilenames.end(); } - bool canModifyFile(const FileEntry *FE) { + bool canModifyFile(Optional FE) { if (!FE) return false; return canModifyFile(FE->getName()); @@ -164,7 +164,7 @@ protected: bool canModifyFile(FileID FID) { if (FID.isInvalid()) return false; - return canModifyFile(PP.getSourceManager().getFileEntryForID(FID)); + return canModifyFile(PP.getSourceManager().getFileEntryRefForID(FID)); } bool canModify(const Decl *D) { @@ -1964,7 +1964,7 @@ void ObjCMigrateASTConsumer::HandleTranslationUnit(ASTContext &Ctx) { I = rewriter.buffer_begin(), E = rewriter.buffer_end(); I != E; ++I) { FileID FID = I->first; RewriteBuffer &buf = I->second; - const FileEntry *file = Ctx.getSourceManager().getFileEntryForID(FID); + Optional file = Ctx.getSourceManager().getFileEntryRefForID(FID); assert(file); SmallString<512> newText; llvm::raw_svector_ostream vecOS(newText); @@ -2034,12 +2034,10 @@ MigrateSourceAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { namespace { struct EditEntry { - const FileEntry *File; - unsigned Offset; - unsigned RemoveLen; + Optional File; + unsigned Offset = 0; + unsigned RemoveLen = 0; std::string Text; - - EditEntry() : File(), Offset(), RemoveLen() {} }; } // end anonymous namespace @@ -2056,12 +2054,8 @@ template<> struct DenseMapInfo { return Entry; } static unsigned getHashValue(const EditEntry& Val) { - llvm::FoldingSetNodeID ID; - ID.AddPointer(Val.File); - ID.AddInteger(Val.Offset); - ID.AddInteger(Val.RemoveLen); - ID.AddString(Val.Text); - return ID.ComputeHash(); + return (unsigned)llvm::hash_combine(Val.File, Val.Offset, Val.RemoveLen, + Val.Text); } static bool isEqual(const EditEntry &LHS, const EditEntry &RHS) { return LHS.File == RHS.File && @@ -2133,9 +2127,8 @@ private: StringRef Val = ValueString->getValue(ValueStorage); if (Key == "file") { - auto FE = FileMgr.getFile(Val); - if (FE) - Entry.File = *FE; + if (auto File = FileMgr.getOptionalFileRef(Val)) + Entry.File = File; else Ignore = true; } else if (Key == "offset") { @@ -2161,7 +2154,7 @@ static bool reportDiag(const Twine &Err, DiagnosticsEngine &Diag) { return true; } -static std::string applyEditsToTemp(const FileEntry *FE, +static std::string applyEditsToTemp(FileEntryRef FE, ArrayRef Edits, FileManager &FileMgr, DiagnosticsEngine &Diag) { @@ -2205,8 +2198,8 @@ static std::string applyEditsToTemp(const FileEntry *FE, SmallString<64> TempPath; int FD; - if (fs::createTemporaryFile(path::filename(FE->getName()), - path::extension(FE->getName()).drop_front(), FD, + if (fs::createTemporaryFile(path::filename(FE.getName()), + path::extension(FE.getName()).drop_front(), FD, TempPath)) { reportDiag("Could not create file: " + TempPath.str(), Diag); return std::string(); @@ -2234,7 +2227,7 @@ bool arcmt::getFileRemappingsFromFileList( new DiagnosticsEngine(DiagID, new DiagnosticOptions, DiagClient, /*ShouldOwnClient=*/false)); - typedef llvm::DenseMap > + typedef llvm::DenseMap > FileEditEntriesTy; FileEditEntriesTy FileEditEntries; @@ -2256,7 +2249,7 @@ bool arcmt::getFileRemappingsFromFileList( if (!Insert.second) continue; - FileEditEntries[Entry.File].push_back(Entry); + FileEditEntries[*Entry.File].push_back(Entry); } } @@ -2269,7 +2262,7 @@ bool arcmt::getFileRemappingsFromFileList( continue; } - remap.emplace_back(std::string(I->first->getName()), TempFile); + remap.emplace_back(std::string(I->first.getName()), TempFile); } return hasErrorOccurred; diff --git a/clang/lib/ARCMigrate/TransGCAttrs.cpp b/clang/lib/ARCMigrate/TransGCAttrs.cpp index 8f5f3cff17cb..99a61e0842a7 100644 --- a/clang/lib/ARCMigrate/TransGCAttrs.cpp +++ b/clang/lib/ARCMigrate/TransGCAttrs.cpp @@ -88,8 +88,8 @@ public: return false; SourceLocation Loc = OwnershipAttr->getLocation(); - unsigned RawLoc = Loc.getRawEncoding(); - if (MigrateCtx.AttrSet.count(RawLoc)) + SourceLocation OrigLoc = Loc; + if (MigrateCtx.AttrSet.count(OrigLoc)) return true; ASTContext &Ctx = MigrateCtx.Pass.Ctx; @@ -105,7 +105,7 @@ public: else return false; - MigrateCtx.AttrSet.insert(RawLoc); + MigrateCtx.AttrSet.insert(OrigLoc); MigrateCtx.GCAttrs.push_back(MigrationContext::GCAttrOccurrence()); MigrationContext::GCAttrOccurrence &Attr = MigrateCtx.GCAttrs.back(); @@ -204,7 +204,7 @@ static void checkWeakGCAttrs(MigrationContext &MigrateCtx) { if (!canApplyWeak(MigrateCtx.Pass.Ctx, Attr.ModifiedType, /*AllowOnUnknownClass=*/true)) { Transaction Trans(TA); - if (!MigrateCtx.RemovedAttrSet.count(Attr.Loc.getRawEncoding())) + if (!MigrateCtx.RemovedAttrSet.count(Attr.Loc)) TA.replaceText(Attr.Loc, "__weak", "__unsafe_unretained"); TA.clearDiagnostic(diag::err_arc_weak_no_runtime, diag::err_arc_unsupported_weak_class, @@ -262,7 +262,7 @@ static void checkAllAtProps(MigrationContext &MigrateCtx, if (GCAttrsCollector::hasObjCImpl( cast(IndProps.front()->getDeclContext()))) { if (hasWeak) - MigrateCtx.AtPropsWeak.insert(AtLoc.getRawEncoding()); + MigrateCtx.AtPropsWeak.insert(AtLoc); } else { StringRef toAttr = "strong"; @@ -289,14 +289,14 @@ static void checkAllAtProps(MigrationContext &MigrateCtx, TA.clearDiagnostic(diag::err_objc_property_attr_mutually_exclusive, AtLoc); TA.clearDiagnostic(diag::err_arc_inconsistent_property_ownership, ATLs[i].second->getLocation()); - MigrateCtx.RemovedAttrSet.insert(Loc.getRawEncoding()); + MigrateCtx.RemovedAttrSet.insert(Loc); } } static void checkAllProps(MigrationContext &MigrateCtx, std::vector &AllProps) { typedef llvm::TinyPtrVector IndivPropsTy; - llvm::DenseMap AtProps; + llvm::DenseMap AtProps; for (unsigned i = 0, e = AllProps.size(); i != e; ++i) { ObjCPropertyDecl *PD = AllProps[i]; @@ -306,14 +306,12 @@ static void checkAllProps(MigrationContext &MigrateCtx, SourceLocation AtLoc = PD->getAtLoc(); if (AtLoc.isInvalid()) continue; - unsigned RawAt = AtLoc.getRawEncoding(); - AtProps[RawAt].push_back(PD); + AtProps[AtLoc].push_back(PD); } } - for (llvm::DenseMap::iterator - I = AtProps.begin(), E = AtProps.end(); I != E; ++I) { - SourceLocation AtLoc = SourceLocation::getFromRawEncoding(I->first); + for (auto I = AtProps.begin(), E = AtProps.end(); I != E; ++I) { + SourceLocation AtLoc = I->first; IndivPropsTy &IndProps = I->second; checkAllAtProps(MigrateCtx, AtLoc, IndProps); } diff --git a/clang/lib/ARCMigrate/TransProperties.cpp b/clang/lib/ARCMigrate/TransProperties.cpp index cba2256ef97b..e5ccf1cf79b1 100644 --- a/clang/lib/ARCMigrate/TransProperties.cpp +++ b/clang/lib/ARCMigrate/TransProperties.cpp @@ -65,7 +65,7 @@ class PropertiesRewriter { }; typedef SmallVector PropsTy; - typedef std::map AtPropDeclsTy; + typedef std::map AtPropDeclsTy; AtPropDeclsTy AtProps; llvm::DenseMap ActionOnProp; @@ -76,13 +76,13 @@ public: static void collectProperties(ObjCContainerDecl *D, AtPropDeclsTy &AtProps, AtPropDeclsTy *PrevAtProps = nullptr) { for (auto *Prop : D->instance_properties()) { - if (Prop->getAtLoc().isInvalid()) + SourceLocation Loc = Prop->getAtLoc(); + if (Loc.isInvalid()) continue; - unsigned RawLoc = Prop->getAtLoc().getRawEncoding(); if (PrevAtProps) - if (PrevAtProps->find(RawLoc) != PrevAtProps->end()) + if (PrevAtProps->find(Loc) != PrevAtProps->end()) continue; - PropsTy &props = AtProps[RawLoc]; + PropsTy &props = AtProps[Loc]; props.push_back(Prop); } } @@ -113,8 +113,7 @@ public: ObjCIvarDecl *ivarD = implD->getPropertyIvarDecl(); if (!ivarD || ivarD->isInvalidDecl()) continue; - unsigned rawAtLoc = propD->getAtLoc().getRawEncoding(); - AtPropDeclsTy::iterator findAtLoc = AtProps.find(rawAtLoc); + AtPropDeclsTy::iterator findAtLoc = AtProps.find(propD->getAtLoc()); if (findAtLoc == AtProps.end()) continue; @@ -130,7 +129,7 @@ public: for (AtPropDeclsTy::iterator I = AtProps.begin(), E = AtProps.end(); I != E; ++I) { - SourceLocation atLoc = SourceLocation::getFromRawEncoding(I->first); + SourceLocation atLoc = I->first; PropsTy &props = I->second; if (!getPropertyType(props)->isObjCRetainableType()) continue; @@ -338,7 +337,7 @@ private: return false; if (props.empty()) return false; - return MigrateCtx.AtPropsWeak.count(atLoc.getRawEncoding()); + return MigrateCtx.AtPropsWeak.count(atLoc); } bool isUserDeclared(ObjCIvarDecl *ivarD) const { diff --git a/clang/lib/ARCMigrate/Transforms.h b/clang/lib/ARCMigrate/Transforms.h index e087136f0e2c..37e2d6b2a7e1 100644 --- a/clang/lib/ARCMigrate/Transforms.h +++ b/clang/lib/ARCMigrate/Transforms.h @@ -93,12 +93,12 @@ public: bool FullyMigratable; }; std::vector GCAttrs; - llvm::DenseSet AttrSet; - llvm::DenseSet RemovedAttrSet; + llvm::DenseSet AttrSet; + llvm::DenseSet RemovedAttrSet; /// Set of raw '@' locations for 'assign' properties group that contain /// GC __weak. - llvm::DenseSet AtPropsWeak; + llvm::DenseSet AtPropsWeak; explicit MigrationContext(MigrationPass &pass) : Pass(pass) {} ~MigrationContext(); diff --git a/clang/lib/AST/APValue.cpp b/clang/lib/AST/APValue.cpp index f3828bb54c1d..9a9233bc1ea7 100644 --- a/clang/lib/AST/APValue.cpp +++ b/clang/lib/AST/APValue.cpp @@ -11,10 +11,12 @@ //===----------------------------------------------------------------------===// #include "clang/AST/APValue.h" +#include "Linkage.h" #include "clang/AST/ASTContext.h" #include "clang/AST/CharUnits.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" #include "clang/AST/Type.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" @@ -38,7 +40,7 @@ static_assert( "Type is insufficiently aligned"); APValue::LValueBase::LValueBase(const ValueDecl *P, unsigned I, unsigned V) - : Ptr(P), Local{I, V} {} + : Ptr(P ? cast(P->getCanonicalDecl()) : nullptr), Local{I, V} {} APValue::LValueBase::LValueBase(const Expr *P, unsigned I, unsigned V) : Ptr(P), Local{I, V} {} @@ -58,6 +60,51 @@ APValue::LValueBase APValue::LValueBase::getTypeInfo(TypeInfoLValue LV, return Base; } +QualType APValue::LValueBase::getType() const { + if (!*this) return QualType(); + if (const ValueDecl *D = dyn_cast()) { + // FIXME: It's unclear where we're supposed to take the type from, and + // this actually matters for arrays of unknown bound. Eg: + // + // extern int arr[]; void f() { extern int arr[3]; }; + // constexpr int *p = &arr[1]; // valid? + // + // For now, we take the most complete type we can find. + for (auto *Redecl = cast(D->getMostRecentDecl()); Redecl; + Redecl = cast_or_null(Redecl->getPreviousDecl())) { + QualType T = Redecl->getType(); + if (!T->isIncompleteArrayType()) + return T; + } + return D->getType(); + } + + if (is()) + return getTypeInfoType(); + + if (is()) + return getDynamicAllocType(); + + const Expr *Base = get(); + + // For a materialized temporary, the type of the temporary we materialized + // may not be the type of the expression. + if (const MaterializeTemporaryExpr *MTE = + clang::dyn_cast(Base)) { + SmallVector CommaLHSs; + SmallVector Adjustments; + const Expr *Temp = MTE->getSubExpr(); + const Expr *Inner = Temp->skipRValueSubobjectAdjustments(CommaLHSs, + Adjustments); + // Keep any cv-qualifiers from the reference if we generated a temporary + // for it directly. Otherwise use the type after adjustment. + if (!Adjustments.empty()) + return Inner->getType(); + } + + return Base->getType(); +} + unsigned APValue::LValueBase::getCallIndex() const { return (is() || is()) ? 0 : Local.CallIndex; @@ -77,18 +124,44 @@ QualType APValue::LValueBase::getDynamicAllocType() const { return QualType::getFromOpaquePtr(DynamicAllocType); } +void APValue::LValueBase::Profile(llvm::FoldingSetNodeID &ID) const { + ID.AddPointer(Ptr.getOpaqueValue()); + if (is() || is()) + return; + ID.AddInteger(Local.CallIndex); + ID.AddInteger(Local.Version); +} + namespace clang { bool operator==(const APValue::LValueBase &LHS, const APValue::LValueBase &RHS) { if (LHS.Ptr != RHS.Ptr) return false; - if (LHS.is()) + if (LHS.is() || LHS.is()) return true; return LHS.Local.CallIndex == RHS.Local.CallIndex && LHS.Local.Version == RHS.Local.Version; } } +APValue::LValuePathEntry::LValuePathEntry(BaseOrMemberType BaseOrMember) { + if (const Decl *D = BaseOrMember.getPointer()) + BaseOrMember.setPointer(D->getCanonicalDecl()); + Value = reinterpret_cast(BaseOrMember.getOpaqueValue()); +} + +void APValue::LValuePathEntry::Profile(llvm::FoldingSetNodeID &ID) const { + ID.AddInteger(Value); +} + +APValue::LValuePathSerializationHelper::LValuePathSerializationHelper( + ArrayRef Path, QualType ElemTy) + : ElemTy((const void *)ElemTy.getTypePtrOrNull()), Path(Path) {} + +QualType APValue::LValuePathSerializationHelper::getType() { + return QualType::getFromOpaquePtr(ElemTy); +} + namespace { struct LVBase { APValue::LValueBase Base; @@ -113,14 +186,16 @@ APValue::LValueBase::operator bool () const { clang::APValue::LValueBase llvm::DenseMapInfo::getEmptyKey() { - return clang::APValue::LValueBase( - DenseMapInfo::getEmptyKey()); + clang::APValue::LValueBase B; + B.Ptr = DenseMapInfo::getEmptyKey(); + return B; } clang::APValue::LValueBase llvm::DenseMapInfo::getTombstoneKey() { - return clang::APValue::LValueBase( - DenseMapInfo::getTombstoneKey()); + clang::APValue::LValueBase B; + B.Ptr = DenseMapInfo::getTombstoneKey(); + return B; } namespace clang { @@ -254,7 +329,7 @@ APValue::APValue(const APValue &RHS) : Kind(None) { } case Vector: MakeVector(); - setVector(((const Vec *)(const char *)RHS.Data.buffer)->Elts, + setVector(((const Vec *)(const char *)&RHS.Data)->Elts, RHS.getVectorLength()); break; case ComplexInt: @@ -304,31 +379,50 @@ APValue::APValue(const APValue &RHS) : Kind(None) { } } +APValue::APValue(APValue &&RHS) : Kind(RHS.Kind), Data(RHS.Data) { + RHS.Kind = None; +} + +APValue &APValue::operator=(const APValue &RHS) { + if (this != &RHS) + *this = APValue(RHS); + return *this; +} + +APValue &APValue::operator=(APValue &&RHS) { + if (Kind != None && Kind != Indeterminate) + DestroyDataAndMakeUninit(); + Kind = RHS.Kind; + Data = RHS.Data; + RHS.Kind = None; + return *this; +} + void APValue::DestroyDataAndMakeUninit() { if (Kind == Int) - ((APSInt*)(char*)Data.buffer)->~APSInt(); + ((APSInt *)(char *)&Data)->~APSInt(); else if (Kind == Float) - ((APFloat*)(char*)Data.buffer)->~APFloat(); + ((APFloat *)(char *)&Data)->~APFloat(); else if (Kind == FixedPoint) - ((APFixedPoint *)(char *)Data.buffer)->~APFixedPoint(); + ((APFixedPoint *)(char *)&Data)->~APFixedPoint(); else if (Kind == Vector) - ((Vec*)(char*)Data.buffer)->~Vec(); + ((Vec *)(char *)&Data)->~Vec(); else if (Kind == ComplexInt) - ((ComplexAPSInt*)(char*)Data.buffer)->~ComplexAPSInt(); + ((ComplexAPSInt *)(char *)&Data)->~ComplexAPSInt(); else if (Kind == ComplexFloat) - ((ComplexAPFloat*)(char*)Data.buffer)->~ComplexAPFloat(); + ((ComplexAPFloat *)(char *)&Data)->~ComplexAPFloat(); else if (Kind == LValue) - ((LV*)(char*)Data.buffer)->~LV(); + ((LV *)(char *)&Data)->~LV(); else if (Kind == Array) - ((Arr*)(char*)Data.buffer)->~Arr(); + ((Arr *)(char *)&Data)->~Arr(); else if (Kind == Struct) - ((StructData*)(char*)Data.buffer)->~StructData(); + ((StructData *)(char *)&Data)->~StructData(); else if (Kind == Union) - ((UnionData*)(char*)Data.buffer)->~UnionData(); + ((UnionData *)(char *)&Data)->~UnionData(); else if (Kind == MemberPointer) - ((MemberPointerData*)(char*)Data.buffer)->~MemberPointerData(); + ((MemberPointerData *)(char *)&Data)->~MemberPointerData(); else if (Kind == AddrLabelDiff) - ((AddrLabelDiffData*)(char*)Data.buffer)->~AddrLabelDiffData(); + ((AddrLabelDiffData *)(char *)&Data)->~AddrLabelDiffData(); Kind = None; } @@ -362,20 +456,165 @@ bool APValue::needsCleanup() const { "same size."); return getComplexIntReal().needsCleanup(); case LValue: - return reinterpret_cast(Data.buffer)->hasPathPtr(); + return reinterpret_cast(&Data)->hasPathPtr(); case MemberPointer: - return reinterpret_cast(Data.buffer) - ->hasPathPtr(); + return reinterpret_cast(&Data)->hasPathPtr(); } llvm_unreachable("Unknown APValue kind!"); } void APValue::swap(APValue &RHS) { std::swap(Kind, RHS.Kind); - char TmpData[DataSize]; - memcpy(TmpData, Data.buffer, DataSize); - memcpy(Data.buffer, RHS.Data.buffer, DataSize); - memcpy(RHS.Data.buffer, TmpData, DataSize); + std::swap(Data, RHS.Data); +} + +/// Profile the value of an APInt, excluding its bit-width. +static void profileIntValue(llvm::FoldingSetNodeID &ID, const llvm::APInt &V) { + for (unsigned I = 0, N = V.getBitWidth(); I < N; I += 32) + ID.AddInteger((uint32_t)V.extractBitsAsZExtValue(std::min(32u, N - I), I)); +} + +void APValue::Profile(llvm::FoldingSetNodeID &ID) const { + // Note that our profiling assumes that only APValues of the same type are + // ever compared. As a result, we don't consider collisions that could only + // happen if the types are different. (For example, structs with different + // numbers of members could profile the same.) + + ID.AddInteger(Kind); + + switch (Kind) { + case None: + case Indeterminate: + return; + + case AddrLabelDiff: + ID.AddPointer(getAddrLabelDiffLHS()->getLabel()->getCanonicalDecl()); + ID.AddPointer(getAddrLabelDiffRHS()->getLabel()->getCanonicalDecl()); + return; + + case Struct: + for (unsigned I = 0, N = getStructNumBases(); I != N; ++I) + getStructBase(I).Profile(ID); + for (unsigned I = 0, N = getStructNumFields(); I != N; ++I) + getStructField(I).Profile(ID); + return; + + case Union: + if (!getUnionField()) { + ID.AddInteger(0); + return; + } + ID.AddInteger(getUnionField()->getFieldIndex() + 1); + getUnionValue().Profile(ID); + return; + + case Array: { + if (getArraySize() == 0) + return; + + // The profile should not depend on whether the array is expanded or + // not, but we don't want to profile the array filler many times for + // a large array. So treat all equal trailing elements as the filler. + // Elements are profiled in reverse order to support this, and the + // first profiled element is followed by a count. For example: + // + // ['a', 'c', 'x', 'x', 'x'] is profiled as + // [5, 'x', 3, 'c', 'a'] + llvm::FoldingSetNodeID FillerID; + (hasArrayFiller() ? getArrayFiller() + : getArrayInitializedElt(getArrayInitializedElts() - 1)) + .Profile(FillerID); + ID.AddNodeID(FillerID); + unsigned NumFillers = getArraySize() - getArrayInitializedElts(); + unsigned N = getArrayInitializedElts(); + + // Count the number of elements equal to the last one. This loop ends + // by adding an integer indicating the number of such elements, with + // N set to the number of elements left to profile. + while (true) { + if (N == 0) { + // All elements are fillers. + assert(NumFillers == getArraySize()); + ID.AddInteger(NumFillers); + break; + } + + // No need to check if the last element is equal to the last + // element. + if (N != getArraySize()) { + llvm::FoldingSetNodeID ElemID; + getArrayInitializedElt(N - 1).Profile(ElemID); + if (ElemID != FillerID) { + ID.AddInteger(NumFillers); + ID.AddNodeID(ElemID); + --N; + break; + } + } + + // This is a filler. + ++NumFillers; + --N; + } + + // Emit the remaining elements. + for (; N != 0; --N) + getArrayInitializedElt(N - 1).Profile(ID); + return; + } + + case Vector: + for (unsigned I = 0, N = getVectorLength(); I != N; ++I) + getVectorElt(I).Profile(ID); + return; + + case Int: + profileIntValue(ID, getInt()); + return; + + case Float: + profileIntValue(ID, getFloat().bitcastToAPInt()); + return; + + case FixedPoint: + profileIntValue(ID, getFixedPoint().getValue()); + return; + + case ComplexFloat: + profileIntValue(ID, getComplexFloatReal().bitcastToAPInt()); + profileIntValue(ID, getComplexFloatImag().bitcastToAPInt()); + return; + + case ComplexInt: + profileIntValue(ID, getComplexIntReal()); + profileIntValue(ID, getComplexIntImag()); + return; + + case LValue: + getLValueBase().Profile(ID); + ID.AddInteger(getLValueOffset().getQuantity()); + ID.AddInteger((isNullPointer() ? 1 : 0) | + (isLValueOnePastTheEnd() ? 2 : 0) | + (hasLValuePath() ? 4 : 0)); + if (hasLValuePath()) { + ID.AddInteger(getLValuePath().size()); + // For uniqueness, we only need to profile the entries corresponding + // to union members, but we don't have the type here so we don't know + // how to interpret the entries. + for (LValuePathEntry E : getLValuePath()) + E.Profile(ID); + } + return; + + case MemberPointer: + ID.AddPointer(getMemberPointerDecl()); + ID.AddInteger(isMemberPointerToDerivedMember()); + for (const CXXRecordDecl *D : getMemberPointerPath()) + ID.AddPointer(D); + return; + } + + llvm_unreachable("Unknown APValue kind!"); } static double GetApproxValue(const llvm::APFloat &F) { @@ -388,6 +627,18 @@ static double GetApproxValue(const llvm::APFloat &F) { void APValue::printPretty(raw_ostream &Out, const ASTContext &Ctx, QualType Ty) const { + printPretty(Out, Ctx.getPrintingPolicy(), Ty, &Ctx); +} + +void APValue::printPretty(raw_ostream &Out, const PrintingPolicy &Policy, + QualType Ty, const ASTContext *Ctx) const { + // There are no objects of type 'void', but values of this type can be + // returned from functions. + if (Ty->isVoidType()) { + Out << "void()"; + return; + } + switch (getKind()) { case APValue::None: Out << ""; @@ -410,10 +661,10 @@ void APValue::printPretty(raw_ostream &Out, const ASTContext &Ctx, case APValue::Vector: { Out << '{'; QualType ElemTy = Ty->castAs()->getElementType(); - getVectorElt(0).printPretty(Out, Ctx, ElemTy); + getVectorElt(0).printPretty(Out, Policy, ElemTy, Ctx); for (unsigned i = 1; i != getVectorLength(); ++i) { Out << ", "; - getVectorElt(i).printPretty(Out, Ctx, ElemTy); + getVectorElt(i).printPretty(Out, Policy, ElemTy, Ctx); } Out << '}'; return; @@ -435,12 +686,12 @@ void APValue::printPretty(raw_ostream &Out, const ASTContext &Ctx, LValueBase Base = getLValueBase(); if (!Base) { if (isNullPointer()) { - Out << (Ctx.getLangOpts().CPlusPlus11 ? "nullptr" : "0"); + Out << (Policy.Nullptr ? "nullptr" : "0"); } else if (IsReference) { - Out << "*(" << InnerTy.stream(Ctx.getPrintingPolicy()) << "*)" + Out << "*(" << InnerTy.stream(Policy) << "*)" << getLValueOffset().getQuantity(); } else { - Out << "(" << Ty.stream(Ctx.getPrintingPolicy()) << ")" + Out << "(" << Ty.stream(Policy) << ")" << getLValueOffset().getQuantity(); } return; @@ -449,11 +700,11 @@ void APValue::printPretty(raw_ostream &Out, const ASTContext &Ctx, if (!hasLValuePath()) { // No lvalue path: just print the offset. CharUnits O = getLValueOffset(); - CharUnits S = Ctx.getTypeSizeInChars(InnerTy); + CharUnits S = Ctx ? Ctx->getTypeSizeInChars(InnerTy) : CharUnits::Zero(); if (!O.isZero()) { if (IsReference) Out << "*("; - if (O % S) { + if (S.isZero() || O % S) { Out << "(char*)"; S = CharUnits::One(); } @@ -465,16 +716,15 @@ void APValue::printPretty(raw_ostream &Out, const ASTContext &Ctx, if (const ValueDecl *VD = Base.dyn_cast()) Out << *VD; else if (TypeInfoLValue TI = Base.dyn_cast()) { - TI.print(Out, Ctx.getPrintingPolicy()); + TI.print(Out, Policy); } else if (DynamicAllocLValue DA = Base.dyn_cast()) { Out << "{*new " - << Base.getDynamicAllocType().stream(Ctx.getPrintingPolicy()) << "#" + << Base.getDynamicAllocType().stream(Policy) << "#" << DA.getIndex() << "}"; } else { assert(Base.get() != nullptr && "Expecting non-null Expr"); - Base.get()->printPretty(Out, nullptr, - Ctx.getPrintingPolicy()); + Base.get()->printPretty(Out, nullptr, Policy); } if (!O.isZero()) { @@ -491,37 +741,31 @@ void APValue::printPretty(raw_ostream &Out, const ASTContext &Ctx, else if (isLValueOnePastTheEnd()) Out << "*(&"; - QualType ElemTy; + QualType ElemTy = Base.getType(); if (const ValueDecl *VD = Base.dyn_cast()) { Out << *VD; - ElemTy = VD->getType(); } else if (TypeInfoLValue TI = Base.dyn_cast()) { - TI.print(Out, Ctx.getPrintingPolicy()); - ElemTy = Base.getTypeInfoType(); + TI.print(Out, Policy); } else if (DynamicAllocLValue DA = Base.dyn_cast()) { - Out << "{*new " - << Base.getDynamicAllocType().stream(Ctx.getPrintingPolicy()) << "#" + Out << "{*new " << Base.getDynamicAllocType().stream(Policy) << "#" << DA.getIndex() << "}"; - ElemTy = Base.getDynamicAllocType(); } else { const Expr *E = Base.get(); assert(E != nullptr && "Expecting non-null Expr"); - E->printPretty(Out, nullptr, Ctx.getPrintingPolicy()); - // FIXME: This is wrong if E is a MaterializeTemporaryExpr with an lvalue - // adjustment. - ElemTy = E->getType(); + E->printPretty(Out, nullptr, Policy); } ArrayRef Path = getLValuePath(); const CXXRecordDecl *CastToBase = nullptr; for (unsigned I = 0, N = Path.size(); I != N; ++I) { - if (ElemTy->getAs()) { + if (ElemTy->isRecordType()) { // The lvalue refers to a class type, so the next path entry is a base // or member. const Decl *BaseOrMember = Path[I].getAsBaseOrMember().getPointer(); if (const CXXRecordDecl *RD = dyn_cast(BaseOrMember)) { CastToBase = RD; - ElemTy = Ctx.getRecordType(RD); + // Leave ElemTy referring to the most-derived class. The actual type + // doesn't matter except for array types. } else { const ValueDecl *VD = cast(BaseOrMember); Out << "."; @@ -533,7 +777,7 @@ void APValue::printPretty(raw_ostream &Out, const ASTContext &Ctx, } else { // The lvalue must refer to an array. Out << '[' << Path[I].getAsArrayIndex() << ']'; - ElemTy = Ctx.getAsArrayType(ElemTy)->getElementType(); + ElemTy = ElemTy->castAsArrayTypeUnsafe()->getElementType(); } } @@ -548,11 +792,11 @@ void APValue::printPretty(raw_ostream &Out, const ASTContext &Ctx, return; } case APValue::Array: { - const ArrayType *AT = Ctx.getAsArrayType(Ty); + const ArrayType *AT = Ty->castAsArrayTypeUnsafe(); QualType ElemTy = AT->getElementType(); Out << '{'; if (unsigned N = getArrayInitializedElts()) { - getArrayInitializedElt(0).printPretty(Out, Ctx, ElemTy); + getArrayInitializedElt(0).printPretty(Out, Policy, ElemTy, Ctx); for (unsigned I = 1; I != N; ++I) { Out << ", "; if (I == 10) { @@ -560,7 +804,7 @@ void APValue::printPretty(raw_ostream &Out, const ASTContext &Ctx, Out << "..."; break; } - getArrayInitializedElt(I).printPretty(Out, Ctx, ElemTy); + getArrayInitializedElt(I).printPretty(Out, Policy, ElemTy, Ctx); } } Out << '}'; @@ -577,7 +821,7 @@ void APValue::printPretty(raw_ostream &Out, const ASTContext &Ctx, assert(BI != CD->bases_end()); if (!First) Out << ", "; - getStructBase(I).printPretty(Out, Ctx, BI->getType()); + getStructBase(I).printPretty(Out, Policy, BI->getType(), Ctx); First = false; } } @@ -586,7 +830,7 @@ void APValue::printPretty(raw_ostream &Out, const ASTContext &Ctx, Out << ", "; if (FI->isUnnamedBitfield()) continue; getStructField(FI->getFieldIndex()). - printPretty(Out, Ctx, FI->getType()); + printPretty(Out, Policy, FI->getType(), Ctx); First = false; } Out << '}'; @@ -596,7 +840,7 @@ void APValue::printPretty(raw_ostream &Out, const ASTContext &Ctx, Out << '{'; if (const FieldDecl *FD = getUnionField()) { Out << "." << *FD << " = "; - getUnionValue().printPretty(Out, Ctx, FD->getType()); + getUnionValue().printPretty(Out, Policy, FD->getType(), Ctx); } Out << '}'; return; @@ -648,49 +892,49 @@ bool APValue::toIntegralConstant(APSInt &Result, QualType SrcTy, const APValue::LValueBase APValue::getLValueBase() const { assert(isLValue() && "Invalid accessor"); - return ((const LV*)(const void*)Data.buffer)->Base; + return ((const LV *)(const void *)&Data)->Base; } bool APValue::isLValueOnePastTheEnd() const { assert(isLValue() && "Invalid accessor"); - return ((const LV*)(const void*)Data.buffer)->IsOnePastTheEnd; + return ((const LV *)(const void *)&Data)->IsOnePastTheEnd; } CharUnits &APValue::getLValueOffset() { assert(isLValue() && "Invalid accessor"); - return ((LV*)(void*)Data.buffer)->Offset; + return ((LV *)(void *)&Data)->Offset; } bool APValue::hasLValuePath() const { assert(isLValue() && "Invalid accessor"); - return ((const LV*)(const char*)Data.buffer)->hasPath(); + return ((const LV *)(const char *)&Data)->hasPath(); } ArrayRef APValue::getLValuePath() const { assert(isLValue() && hasLValuePath() && "Invalid accessor"); - const LV &LVal = *((const LV*)(const char*)Data.buffer); + const LV &LVal = *((const LV *)(const char *)&Data); return llvm::makeArrayRef(LVal.getPath(), LVal.PathLength); } unsigned APValue::getLValueCallIndex() const { assert(isLValue() && "Invalid accessor"); - return ((const LV*)(const char*)Data.buffer)->Base.getCallIndex(); + return ((const LV *)(const char *)&Data)->Base.getCallIndex(); } unsigned APValue::getLValueVersion() const { assert(isLValue() && "Invalid accessor"); - return ((const LV*)(const char*)Data.buffer)->Base.getVersion(); + return ((const LV *)(const char *)&Data)->Base.getVersion(); } bool APValue::isNullPointer() const { assert(isLValue() && "Invalid usage"); - return ((const LV*)(const char*)Data.buffer)->IsNullPtr; + return ((const LV *)(const char *)&Data)->IsNullPtr; } void APValue::setLValue(LValueBase B, const CharUnits &O, NoLValuePath, bool IsNullPtr) { assert(isLValue() && "Invalid accessor"); - LV &LVal = *((LV*)(char*)Data.buffer); + LV &LVal = *((LV *)(char *)&Data); LVal.Base = B; LVal.IsOnePastTheEnd = false; LVal.Offset = O; @@ -698,60 +942,188 @@ void APValue::setLValue(LValueBase B, const CharUnits &O, NoLValuePath, LVal.IsNullPtr = IsNullPtr; } -void APValue::setLValue(LValueBase B, const CharUnits &O, - ArrayRef Path, bool IsOnePastTheEnd, - bool IsNullPtr) { +MutableArrayRef +APValue::setLValueUninit(LValueBase B, const CharUnits &O, unsigned Size, + bool IsOnePastTheEnd, bool IsNullPtr) { assert(isLValue() && "Invalid accessor"); - LV &LVal = *((LV*)(char*)Data.buffer); + LV &LVal = *((LV *)(char *)&Data); LVal.Base = B; LVal.IsOnePastTheEnd = IsOnePastTheEnd; LVal.Offset = O; - LVal.resizePath(Path.size()); - memcpy(LVal.getPath(), Path.data(), Path.size() * sizeof(LValuePathEntry)); LVal.IsNullPtr = IsNullPtr; + LVal.resizePath(Size); + return {LVal.getPath(), Size}; +} + +void APValue::setLValue(LValueBase B, const CharUnits &O, + ArrayRef Path, bool IsOnePastTheEnd, + bool IsNullPtr) { + MutableArrayRef InternalPath = + setLValueUninit(B, O, Path.size(), IsOnePastTheEnd, IsNullPtr); + if (Path.size()) { + memcpy(InternalPath.data(), Path.data(), + Path.size() * sizeof(LValuePathEntry)); + } +} + +void APValue::setUnion(const FieldDecl *Field, const APValue &Value) { + assert(isUnion() && "Invalid accessor"); + ((UnionData *)(char *)&Data)->Field = + Field ? Field->getCanonicalDecl() : nullptr; + *((UnionData *)(char *)&Data)->Value = Value; } const ValueDecl *APValue::getMemberPointerDecl() const { assert(isMemberPointer() && "Invalid accessor"); const MemberPointerData &MPD = - *((const MemberPointerData *)(const char *)Data.buffer); + *((const MemberPointerData *)(const char *)&Data); return MPD.MemberAndIsDerivedMember.getPointer(); } bool APValue::isMemberPointerToDerivedMember() const { assert(isMemberPointer() && "Invalid accessor"); const MemberPointerData &MPD = - *((const MemberPointerData *)(const char *)Data.buffer); + *((const MemberPointerData *)(const char *)&Data); return MPD.MemberAndIsDerivedMember.getInt(); } ArrayRef APValue::getMemberPointerPath() const { assert(isMemberPointer() && "Invalid accessor"); const MemberPointerData &MPD = - *((const MemberPointerData *)(const char *)Data.buffer); + *((const MemberPointerData *)(const char *)&Data); return llvm::makeArrayRef(MPD.getPath(), MPD.PathLength); } void APValue::MakeLValue() { assert(isAbsent() && "Bad state change"); static_assert(sizeof(LV) <= DataSize, "LV too big"); - new ((void*)(char*)Data.buffer) LV(); + new ((void *)(char *)&Data) LV(); Kind = LValue; } void APValue::MakeArray(unsigned InitElts, unsigned Size) { assert(isAbsent() && "Bad state change"); - new ((void*)(char*)Data.buffer) Arr(InitElts, Size); + new ((void *)(char *)&Data) Arr(InitElts, Size); Kind = Array; } -void APValue::MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember, - ArrayRef Path) { +MutableArrayRef +setLValueUninit(APValue::LValueBase B, const CharUnits &O, unsigned Size, + bool OnePastTheEnd, bool IsNullPtr); + +MutableArrayRef +APValue::setMemberPointerUninit(const ValueDecl *Member, bool IsDerivedMember, + unsigned Size) { assert(isAbsent() && "Bad state change"); - MemberPointerData *MPD = new ((void*)(char*)Data.buffer) MemberPointerData; + MemberPointerData *MPD = new ((void *)(char *)&Data) MemberPointerData; Kind = MemberPointer; - MPD->MemberAndIsDerivedMember.setPointer(Member); + MPD->MemberAndIsDerivedMember.setPointer( + Member ? cast(Member->getCanonicalDecl()) : nullptr); MPD->MemberAndIsDerivedMember.setInt(IsDerivedMember); - MPD->resizePath(Path.size()); - memcpy(MPD->getPath(), Path.data(), Path.size()*sizeof(const CXXRecordDecl*)); + MPD->resizePath(Size); + return {MPD->getPath(), MPD->PathLength}; +} + +void APValue::MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember, + ArrayRef Path) { + MutableArrayRef InternalPath = + setMemberPointerUninit(Member, IsDerivedMember, Path.size()); + for (unsigned I = 0; I != Path.size(); ++I) + InternalPath[I] = Path[I]->getCanonicalDecl(); +} + +LinkageInfo LinkageComputer::getLVForValue(const APValue &V, + LVComputationKind computation) { + LinkageInfo LV = LinkageInfo::external(); + + auto MergeLV = [&](LinkageInfo MergeLV) { + LV.merge(MergeLV); + return LV.getLinkage() == InternalLinkage; + }; + auto Merge = [&](const APValue &V) { + return MergeLV(getLVForValue(V, computation)); + }; + + switch (V.getKind()) { + case APValue::None: + case APValue::Indeterminate: + case APValue::Int: + case APValue::Float: + case APValue::FixedPoint: + case APValue::ComplexInt: + case APValue::ComplexFloat: + case APValue::Vector: + break; + + case APValue::AddrLabelDiff: + // Even for an inline function, it's not reasonable to treat a difference + // between the addresses of labels as an external value. + return LinkageInfo::internal(); + + case APValue::Struct: { + for (unsigned I = 0, N = V.getStructNumBases(); I != N; ++I) + if (Merge(V.getStructBase(I))) + break; + for (unsigned I = 0, N = V.getStructNumFields(); I != N; ++I) + if (Merge(V.getStructField(I))) + break; + break; + } + + case APValue::Union: + if (V.getUnionField()) + Merge(V.getUnionValue()); + break; + + case APValue::Array: { + for (unsigned I = 0, N = V.getArrayInitializedElts(); I != N; ++I) + if (Merge(V.getArrayInitializedElt(I))) + break; + if (V.hasArrayFiller()) + Merge(V.getArrayFiller()); + break; + } + + case APValue::LValue: { + if (!V.getLValueBase()) { + // Null or absolute address: this is external. + } else if (const auto *VD = + V.getLValueBase().dyn_cast()) { + if (VD && MergeLV(getLVForDecl(VD, computation))) + break; + } else if (const auto TI = V.getLValueBase().dyn_cast()) { + if (MergeLV(getLVForType(*TI.getType(), computation))) + break; + } else if (const Expr *E = V.getLValueBase().dyn_cast()) { + // Almost all expression bases are internal. The exception is + // lifetime-extended temporaries. + // FIXME: These should be modeled as having the + // LifetimeExtendedTemporaryDecl itself as the base. + // FIXME: If we permit Objective-C object literals in template arguments, + // they should not imply internal linkage. + auto *MTE = dyn_cast(E); + if (!MTE || MTE->getStorageDuration() == SD_FullExpression) + return LinkageInfo::internal(); + if (MergeLV(getLVForDecl(MTE->getExtendingDecl(), computation))) + break; + } else { + assert(V.getLValueBase().is() && + "unexpected LValueBase kind"); + return LinkageInfo::internal(); + } + // The lvalue path doesn't matter: pointers to all subobjects always have + // the same visibility as pointers to the complete object. + break; + } + + case APValue::MemberPointer: + if (const NamedDecl *D = V.getMemberPointerDecl()) + MergeLV(getLVForDecl(D, computation)); + // Note that we could have a base-to-derived conversion here to a member of + // a derived class with less linkage/visibility. That's covered by the + // linkage and visibility of the value's type. + break; + } + + return LV; } diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 2ba643f12a82..cb7f00abf9e9 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -51,7 +51,6 @@ #include "clang/Basic/Builtins.h" #include "clang/Basic/CommentOptions.h" #include "clang/Basic/ExceptionSpecificationType.h" -#include "clang/Basic/FixedPoint.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/LangOptions.h" @@ -65,6 +64,7 @@ #include "clang/Basic/TargetCXXABI.h" #include "clang/Basic/TargetInfo.h" #include "clang/Basic/XRayLists.h" +#include "llvm/ADT/APFixedPoint.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/ArrayRef.h" @@ -753,10 +753,10 @@ canonicalizeImmediatelyDeclaredConstraint(const ASTContext &C, Expr *IDC, CSE->isInstantiationDependent(), CSE->containsUnexpandedParameterPack()); if (auto *OrigFold = dyn_cast(IDC)) - NewIDC = new (C) CXXFoldExpr(OrigFold->getType(), SourceLocation(), NewIDC, - BinaryOperatorKind::BO_LAnd, - SourceLocation(), /*RHS=*/nullptr, - SourceLocation(), /*NumExpansions=*/None); + NewIDC = new (C) CXXFoldExpr( + OrigFold->getType(), /*Callee*/nullptr, SourceLocation(), NewIDC, + BinaryOperatorKind::BO_LAnd, SourceLocation(), /*RHS=*/nullptr, + SourceLocation(), /*NumExpansions=*/None); return NewIDC; } @@ -883,10 +883,10 @@ CXXABI *ASTContext::createCXXABI(const TargetInfo &T) { if (!LangOpts.CPlusPlus) return nullptr; switch (T.getCXXABI().getKind()) { + case TargetCXXABI::AppleARM64: case TargetCXXABI::Fuchsia: case TargetCXXABI::GenericARM: // Same as Itanium at this level case TargetCXXABI::iOS: - case TargetCXXABI::iOS64: case TargetCXXABI::WatchOS: case TargetCXXABI::GenericAArch64: case TargetCXXABI::GenericMIPS: @@ -919,18 +919,20 @@ static const LangASMap *getAddressSpaceMap(const TargetInfo &T, // The fake address space map must have a distinct entry for each // language-specific address space. static const unsigned FakeAddrSpaceMap[] = { - 0, // Default - 1, // opencl_global - 3, // opencl_local - 2, // opencl_constant - 0, // opencl_private - 4, // opencl_generic - 5, // cuda_device - 6, // cuda_constant - 7, // cuda_shared - 8, // ptr32_sptr - 9, // ptr32_uptr - 10 // ptr64 + 0, // Default + 1, // opencl_global + 3, // opencl_local + 2, // opencl_constant + 0, // opencl_private + 4, // opencl_generic + 5, // opencl_global_device + 6, // opencl_global_host + 7, // cuda_device + 8, // cuda_constant + 9, // cuda_shared + 10, // ptr32_sptr + 11, // ptr32_uptr + 12 // ptr64 }; return &FakeAddrSpaceMap; } else { @@ -963,6 +965,7 @@ ASTContext::ASTContext(LangOptions &LOpts, SourceManager &SM, XRayFilter(new XRayFunctionFilter(LangOpts.XRayAlwaysInstrumentFiles, LangOpts.XRayNeverInstrumentFiles, LangOpts.XRayAttrListFiles, SM)), + ProfList(new ProfileList(LangOpts.ProfileListFiles, SM)), PrintingPolicy(LOpts), Idents(idents), Selectors(sels), BuiltinInfo(builtins), DeclarationNames(*this), Comments(SM), CommentCommandTraits(BumpAlloc, LOpts.CommentOpts), @@ -1003,9 +1006,6 @@ ASTContext::~ASTContext() { for (const auto &Value : ModuleInitializers) Value.second->~PerModuleInitializers(); - - for (APValue *Value : APValueCleanups) - Value->~APValue(); } void ASTContext::setTraversalScope(const std::vector &TopLevelDecls) { @@ -1424,6 +1424,18 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target, #include "clang/Basic/AArch64SVEACLETypes.def" } + if (Target.getTriple().isPPC64() && + Target.hasFeature("paired-vector-memops")) { + if (Target.hasFeature("mma")) { +#define PPC_VECTOR_MMA_TYPE(Name, Id, Size) \ + InitBuiltinType(Id##Ty, BuiltinType::Id); +#include "clang/Basic/PPCTypes.def" + } +#define PPC_VECTOR_VSX_TYPE(Name, Id, Size) \ + InitBuiltinType(Id##Ty, BuiltinType::Id); +#include "clang/Basic/PPCTypes.def" + } + // Builtin type for __objc_yes and __objc_no ObjCBuiltinBoolTy = (Target.useSignedCharForObjCBool() ? SignedCharTy : BoolTy); @@ -1775,9 +1787,8 @@ CharUnits ASTContext::getExnObjectAlignment() const { // chars. If the type is a record, its data size is returned. This is // the size of the memcpy that's performed when assigning this type // using a trivial copy/move assignment operator. -std::pair -ASTContext::getTypeInfoDataSizeInChars(QualType T) const { - std::pair sizeAndAlign = getTypeInfoInChars(T); +TypeInfoChars ASTContext::getTypeInfoDataSizeInChars(QualType T) const { + TypeInfoChars Info = getTypeInfoInChars(T); // In C++, objects can sometimes be allocated into the tail padding // of a base-class subobject. We decide whether that's possible @@ -1785,44 +1796,43 @@ ASTContext::getTypeInfoDataSizeInChars(QualType T) const { if (getLangOpts().CPlusPlus) { if (const auto *RT = T->getAs()) { const ASTRecordLayout &layout = getASTRecordLayout(RT->getDecl()); - sizeAndAlign.first = layout.getDataSize(); + Info.Width = layout.getDataSize(); } } - return sizeAndAlign; + return Info; } /// getConstantArrayInfoInChars - Performing the computation in CharUnits /// instead of in bits prevents overflowing the uint64_t for some large arrays. -std::pair +TypeInfoChars static getConstantArrayInfoInChars(const ASTContext &Context, const ConstantArrayType *CAT) { - std::pair EltInfo = - Context.getTypeInfoInChars(CAT->getElementType()); + TypeInfoChars EltInfo = Context.getTypeInfoInChars(CAT->getElementType()); uint64_t Size = CAT->getSize().getZExtValue(); - assert((Size == 0 || static_cast(EltInfo.first.getQuantity()) <= + assert((Size == 0 || static_cast(EltInfo.Width.getQuantity()) <= (uint64_t)(-1)/Size) && "Overflow in array type char size evaluation"); - uint64_t Width = EltInfo.first.getQuantity() * Size; - unsigned Align = EltInfo.second.getQuantity(); + uint64_t Width = EltInfo.Width.getQuantity() * Size; + unsigned Align = EltInfo.Align.getQuantity(); if (!Context.getTargetInfo().getCXXABI().isMicrosoft() || Context.getTargetInfo().getPointerWidth(0) == 64) Width = llvm::alignTo(Width, Align); - return std::make_pair(CharUnits::fromQuantity(Width), - CharUnits::fromQuantity(Align)); + return TypeInfoChars(CharUnits::fromQuantity(Width), + CharUnits::fromQuantity(Align), + EltInfo.AlignIsRequired); } -std::pair -ASTContext::getTypeInfoInChars(const Type *T) const { +TypeInfoChars ASTContext::getTypeInfoInChars(const Type *T) const { if (const auto *CAT = dyn_cast(T)) return getConstantArrayInfoInChars(*this, CAT); TypeInfo Info = getTypeInfo(T); - return std::make_pair(toCharUnitsFromBits(Info.Width), - toCharUnitsFromBits(Info.Align)); + return TypeInfoChars(toCharUnitsFromBits(Info.Width), + toCharUnitsFromBits(Info.Align), + Info.AlignIsRequired); } -std::pair -ASTContext::getTypeInfoInChars(QualType T) const { +TypeInfoChars ASTContext::getTypeInfoInChars(QualType T) const { return getTypeInfoInChars(T.getTypePtr()); } @@ -1834,7 +1844,8 @@ bool ASTContext::isAlignmentRequired(QualType T) const { return isAlignmentRequired(T.getTypePtr()); } -unsigned ASTContext::getTypeAlignIfKnown(QualType T) const { +unsigned ASTContext::getTypeAlignIfKnown(QualType T, + bool NeedsPreferredAlignment) const { // An alignment on a typedef overrides anything else. if (const auto *TT = T->getAs()) if (unsigned Align = TT->getDecl()->getMaxAlignment()) @@ -1843,7 +1854,7 @@ unsigned ASTContext::getTypeAlignIfKnown(QualType T) const { // If we have an (array of) complete type, we're done. T = getBaseElementType(T); if (!T->isIncompleteType()) - return getTypeAlign(T); + return NeedsPreferredAlignment ? getPreferredTypeAlign(T) : getTypeAlign(T); // If we had an array type, its element type might be a typedef // type with an alignment attribute. @@ -1935,6 +1946,13 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { uint64_t TargetVectorAlign = Target->getMaxVectorAlign(); if (TargetVectorAlign && TargetVectorAlign < Align) Align = TargetVectorAlign; + if (VT->getVectorKind() == VectorType::SveFixedLengthDataVector) + // Adjust the alignment for fixed-length SVE vectors. This is important + // for non-power-of-2 vector lengths. + Align = 128; + else if (VT->getVectorKind() == VectorType::SveFixedLengthPredicateVector) + // Adjust the alignment for fixed-length SVE predicates. + Align = 16; break; } @@ -2143,6 +2161,12 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { Align = 16; \ break; #include "clang/Basic/AArch64SVEACLETypes.def" +#define PPC_VECTOR_TYPE(Name, Id, Size) \ + case BuiltinType::Id: \ + Width = Size; \ + Align = Size; \ + break; +#include "clang/Basic/PPCTypes.def" } break; case Type::ObjCObjectPointer: @@ -2343,12 +2367,6 @@ unsigned ASTContext::getTypeUnadjustedAlign(const Type *T) const { unsigned ASTContext::getOpenMPDefaultSimdAlign(QualType T) const { unsigned SimdAlign = getTargetInfo().getSimdDefaultAlign(); - // Target ppc64 with QPX: simd default alignment for pointer to double is 32. - if ((getTargetInfo().getTriple().getArch() == llvm::Triple::ppc64 || - getTargetInfo().getTriple().getArch() == llvm::Triple::ppc64le) && - getTargetInfo().getABI() == "elfv1-qpx" && - T->isSpecificBuiltinType(BuiltinType::Double)) - SimdAlign = 256; return SimdAlign; } @@ -2365,10 +2383,10 @@ int64_t ASTContext::toBits(CharUnits CharSize) const { /// getTypeSizeInChars - Return the size of the specified type, in characters. /// This method does not work on incomplete types. CharUnits ASTContext::getTypeSizeInChars(QualType T) const { - return getTypeInfoInChars(T).first; + return getTypeInfoInChars(T).Width; } CharUnits ASTContext::getTypeSizeInChars(const Type *T) const { - return getTypeInfoInChars(T).first; + return getTypeInfoInChars(T).Width; } /// getTypeAlignInChars - Return the ABI-specified alignment of a type, in @@ -2392,8 +2410,9 @@ CharUnits ASTContext::getTypeUnadjustedAlignInChars(const Type *T) const { /// getPreferredTypeAlign - Return the "preferred" alignment of the specified /// type for the current target in bits. This can be different than the ABI -/// alignment in cases where it is beneficial for performance to overalign -/// a data type. +/// alignment in cases where it is beneficial for performance or backwards +/// compatibility preserving to overalign a data type. (Note: despite the name, +/// the preferred alignment is ABI-impacting, and not an optimization.) unsigned ASTContext::getPreferredTypeAlign(const Type *T) const { TypeInfo TI = getTypeInfo(T); unsigned ABIAlign = TI.Align; @@ -2403,18 +2422,33 @@ unsigned ASTContext::getPreferredTypeAlign(const Type *T) const { // The preferred alignment of member pointers is that of a pointer. if (T->isMemberPointerType()) return getPreferredTypeAlign(getPointerDiffType().getTypePtr()); - + if (!Target->allowsLargerPreferedTypeAlignment()) return ABIAlign; - // Double and long long should be naturally aligned if possible. + if (const auto *RT = T->getAs()) { + if (TI.AlignIsRequired || RT->getDecl()->isInvalidDecl()) + return ABIAlign; + + unsigned PreferredAlign = static_cast( + toBits(getASTRecordLayout(RT->getDecl()).PreferredAlignment)); + assert(PreferredAlign >= ABIAlign && + "PreferredAlign should be at least as large as ABIAlign."); + return PreferredAlign; + } + + // Double (and, for targets supporting AIX `power` alignment, long double) and + // long long should be naturally aligned (despite requiring less alignment) if + // possible. if (const auto *CT = T->getAs()) T = CT->getElementType().getTypePtr(); if (const auto *ET = T->getAs()) T = ET->getDecl()->getIntegerType().getTypePtr(); if (T->isSpecificBuiltinType(BuiltinType::Double) || T->isSpecificBuiltinType(BuiltinType::LongLong) || - T->isSpecificBuiltinType(BuiltinType::ULongLong)) + T->isSpecificBuiltinType(BuiltinType::ULongLong) || + (T->isSpecificBuiltinType(BuiltinType::LongDouble) && + Target->defaultsToAIXPowerAlignment())) // Don't increase the alignment if an alignment attribute was specified on a // typedef declaration. if (!TI.AlignIsRequired) @@ -2434,7 +2468,8 @@ unsigned ASTContext::getTargetDefaultAlignForAttributeAligned() const { /// to a global variable of the specified type. unsigned ASTContext::getAlignOfGlobalVar(QualType T) const { uint64_t TypeSize = getTypeSize(T.getTypePtr()); - return std::max(getTypeAlign(T), getTargetInfo().getMinGlobalAlign(TypeSize)); + return std::max(getPreferredTypeAlign(T), + getTargetInfo().getMinGlobalAlign(TypeSize)); } /// getAlignOfGlobalVarInChars - Return the alignment in characters that @@ -2453,6 +2488,25 @@ CharUnits ASTContext::getOffsetOfBaseWithVBPtr(const CXXRecordDecl *RD) const { return Offset; } +CharUnits ASTContext::getMemberPointerPathAdjustment(const APValue &MP) const { + const ValueDecl *MPD = MP.getMemberPointerDecl(); + CharUnits ThisAdjustment = CharUnits::Zero(); + ArrayRef Path = MP.getMemberPointerPath(); + bool DerivedMember = MP.isMemberPointerToDerivedMember(); + const CXXRecordDecl *RD = cast(MPD->getDeclContext()); + for (unsigned I = 0, N = Path.size(); I != N; ++I) { + const CXXRecordDecl *Base = RD; + const CXXRecordDecl *Derived = Path[I]; + if (DerivedMember) + std::swap(Base, Derived); + ThisAdjustment += getASTRecordLayout(Derived).getBaseClassOffset(Base); + RD = Path[I]; + } + if (DerivedMember) + ThisAdjustment = -ThisAdjustment; + return ThisAdjustment; +} + /// DeepCollectObjCIvars - /// This routine first collects all declared, but not synthesized, ivars in /// super class and then collects all ivars, including those synthesized for @@ -2870,14 +2924,27 @@ QualType ASTContext::getAddrSpaceQualType(QualType T, } QualType ASTContext::removeAddrSpaceQualType(QualType T) const { + // If the type is not qualified with an address space, just return it + // immediately. + if (!T.hasAddressSpace()) + return T; + // If we are composing extended qualifiers together, merge together // into one ExtQuals node. QualifierCollector Quals; - const Type *TypeNode = Quals.strip(T); + const Type *TypeNode; - // If the qualifier doesn't have an address space just return it. - if (!Quals.hasAddressSpace()) - return T; + while (T.hasAddressSpace()) { + TypeNode = Quals.strip(T); + + // If the type no longer has an address space after stripping qualifiers, + // jump out. + if (!QualType(TypeNode, 0).hasAddressSpace()) + break; + + // There might be sugar in the way. Strip it and try again. + T = T.getSingleStepDesugaredType(*this); + } Quals.removeAddressSpace(); @@ -3634,6 +3701,119 @@ QualType ASTContext::getIncompleteArrayType(QualType elementType, return QualType(newType, 0); } +ASTContext::BuiltinVectorTypeInfo +ASTContext::getBuiltinVectorTypeInfo(const BuiltinType *Ty) const { +#define SVE_INT_ELTTY(BITS, ELTS, SIGNED, NUMVECTORS) \ + {getIntTypeForBitwidth(BITS, SIGNED), llvm::ElementCount::getScalable(ELTS), \ + NUMVECTORS}; + +#define SVE_ELTTY(ELTTY, ELTS, NUMVECTORS) \ + {ELTTY, llvm::ElementCount::getScalable(ELTS), NUMVECTORS}; + + switch (Ty->getKind()) { + default: + llvm_unreachable("Unsupported builtin vector type"); + case BuiltinType::SveInt8: + return SVE_INT_ELTTY(8, 16, true, 1); + case BuiltinType::SveUint8: + return SVE_INT_ELTTY(8, 16, false, 1); + case BuiltinType::SveInt8x2: + return SVE_INT_ELTTY(8, 16, true, 2); + case BuiltinType::SveUint8x2: + return SVE_INT_ELTTY(8, 16, false, 2); + case BuiltinType::SveInt8x3: + return SVE_INT_ELTTY(8, 16, true, 3); + case BuiltinType::SveUint8x3: + return SVE_INT_ELTTY(8, 16, false, 3); + case BuiltinType::SveInt8x4: + return SVE_INT_ELTTY(8, 16, true, 4); + case BuiltinType::SveUint8x4: + return SVE_INT_ELTTY(8, 16, false, 4); + case BuiltinType::SveInt16: + return SVE_INT_ELTTY(16, 8, true, 1); + case BuiltinType::SveUint16: + return SVE_INT_ELTTY(16, 8, false, 1); + case BuiltinType::SveInt16x2: + return SVE_INT_ELTTY(16, 8, true, 2); + case BuiltinType::SveUint16x2: + return SVE_INT_ELTTY(16, 8, false, 2); + case BuiltinType::SveInt16x3: + return SVE_INT_ELTTY(16, 8, true, 3); + case BuiltinType::SveUint16x3: + return SVE_INT_ELTTY(16, 8, false, 3); + case BuiltinType::SveInt16x4: + return SVE_INT_ELTTY(16, 8, true, 4); + case BuiltinType::SveUint16x4: + return SVE_INT_ELTTY(16, 8, false, 4); + case BuiltinType::SveInt32: + return SVE_INT_ELTTY(32, 4, true, 1); + case BuiltinType::SveUint32: + return SVE_INT_ELTTY(32, 4, false, 1); + case BuiltinType::SveInt32x2: + return SVE_INT_ELTTY(32, 4, true, 2); + case BuiltinType::SveUint32x2: + return SVE_INT_ELTTY(32, 4, false, 2); + case BuiltinType::SveInt32x3: + return SVE_INT_ELTTY(32, 4, true, 3); + case BuiltinType::SveUint32x3: + return SVE_INT_ELTTY(32, 4, false, 3); + case BuiltinType::SveInt32x4: + return SVE_INT_ELTTY(32, 4, true, 4); + case BuiltinType::SveUint32x4: + return SVE_INT_ELTTY(32, 4, false, 4); + case BuiltinType::SveInt64: + return SVE_INT_ELTTY(64, 2, true, 1); + case BuiltinType::SveUint64: + return SVE_INT_ELTTY(64, 2, false, 1); + case BuiltinType::SveInt64x2: + return SVE_INT_ELTTY(64, 2, true, 2); + case BuiltinType::SveUint64x2: + return SVE_INT_ELTTY(64, 2, false, 2); + case BuiltinType::SveInt64x3: + return SVE_INT_ELTTY(64, 2, true, 3); + case BuiltinType::SveUint64x3: + return SVE_INT_ELTTY(64, 2, false, 3); + case BuiltinType::SveInt64x4: + return SVE_INT_ELTTY(64, 2, true, 4); + case BuiltinType::SveUint64x4: + return SVE_INT_ELTTY(64, 2, false, 4); + case BuiltinType::SveBool: + return SVE_ELTTY(BoolTy, 16, 1); + case BuiltinType::SveFloat16: + return SVE_ELTTY(HalfTy, 8, 1); + case BuiltinType::SveFloat16x2: + return SVE_ELTTY(HalfTy, 8, 2); + case BuiltinType::SveFloat16x3: + return SVE_ELTTY(HalfTy, 8, 3); + case BuiltinType::SveFloat16x4: + return SVE_ELTTY(HalfTy, 8, 4); + case BuiltinType::SveFloat32: + return SVE_ELTTY(FloatTy, 4, 1); + case BuiltinType::SveFloat32x2: + return SVE_ELTTY(FloatTy, 4, 2); + case BuiltinType::SveFloat32x3: + return SVE_ELTTY(FloatTy, 4, 3); + case BuiltinType::SveFloat32x4: + return SVE_ELTTY(FloatTy, 4, 4); + case BuiltinType::SveFloat64: + return SVE_ELTTY(DoubleTy, 2, 1); + case BuiltinType::SveFloat64x2: + return SVE_ELTTY(DoubleTy, 2, 2); + case BuiltinType::SveFloat64x3: + return SVE_ELTTY(DoubleTy, 2, 3); + case BuiltinType::SveFloat64x4: + return SVE_ELTTY(DoubleTy, 2, 4); + case BuiltinType::SveBFloat16: + return SVE_ELTTY(BFloat16Ty, 8, 1); + case BuiltinType::SveBFloat16x2: + return SVE_ELTTY(BFloat16Ty, 8, 2); + case BuiltinType::SveBFloat16x3: + return SVE_ELTTY(BFloat16Ty, 8, 3); + case BuiltinType::SveBFloat16x4: + return SVE_ELTTY(BFloat16Ty, 8, 4); + } +} + /// getScalableVectorType - Return the unique reference to a scalable vector /// type of the specified element type and size. VectorType must be a built-in /// type. @@ -4276,15 +4456,15 @@ QualType ASTContext::getTypeDeclTypeSlow(const TypeDecl *Decl) const { /// getTypedefType - Return the unique reference to the type for the /// specified typedef name decl. -QualType -ASTContext::getTypedefType(const TypedefNameDecl *Decl, - QualType Canonical) const { +QualType ASTContext::getTypedefType(const TypedefNameDecl *Decl, + QualType Underlying) const { if (Decl->TypeForDecl) return QualType(Decl->TypeForDecl, 0); - if (Canonical.isNull()) - Canonical = getCanonicalType(Decl->getUnderlyingType()); + if (Underlying.isNull()) + Underlying = Decl->getUnderlyingType(); + QualType Canonical = getCanonicalType(Underlying); auto *newType = new (*this, TypeAlignment) - TypedefType(Type::Typedef, Decl, Canonical); + TypedefType(Type::Typedef, Decl, Underlying, Canonical); Decl->TypeForDecl = newType; Types.push_back(newType); return QualType(newType, 0); @@ -4722,9 +4902,16 @@ TemplateArgument ASTContext::getInjectedTemplateArg(NamedDecl *Param) { Arg = TemplateArgument(ArgType); } else if (auto *NTTP = dyn_cast(Param)) { + QualType T = + NTTP->getType().getNonPackExpansionType().getNonLValueExprType(*this); + // For class NTTPs, ensure we include the 'const' so the type matches that + // of a real template argument. + // FIXME: It would be more faithful to model this as something like an + // lvalue-to-rvalue conversion applied to a const-qualified lvalue. + if (T->isRecordType()) + T.addConst(); Expr *E = new (*this) DeclRefExpr( - *this, NTTP, /*enclosing*/ false, - NTTP->getType().getNonPackExpansionType().getNonLValueExprType(*this), + *this, NTTP, /*enclosing*/ false, T, Expr::getValueKindForType(NTTP->getType()), NTTP->getLocation()); if (NTTP->isParameterPack()) @@ -4755,37 +4942,27 @@ ASTContext::getInjectedTemplateArgs(const TemplateParameterList *Params, } QualType ASTContext::getPackExpansionType(QualType Pattern, - Optional NumExpansions) { + Optional NumExpansions, + bool ExpectPackInType) { + assert((!ExpectPackInType || Pattern->containsUnexpandedParameterPack()) && + "Pack expansions must expand one or more parameter packs"); + llvm::FoldingSetNodeID ID; PackExpansionType::Profile(ID, Pattern, NumExpansions); - // A deduced type can deduce to a pack, eg - // auto ...x = some_pack; - // That declaration isn't (yet) valid, but is created as part of building an - // init-capture pack: - // [...x = some_pack] {} - assert((Pattern->containsUnexpandedParameterPack() || - Pattern->getContainedDeducedType()) && - "Pack expansions must expand one or more parameter packs"); void *InsertPos = nullptr; - PackExpansionType *T - = PackExpansionTypes.FindNodeOrInsertPos(ID, InsertPos); + PackExpansionType *T = PackExpansionTypes.FindNodeOrInsertPos(ID, InsertPos); if (T) return QualType(T, 0); QualType Canon; if (!Pattern.isCanonical()) { - Canon = getCanonicalType(Pattern); - // The canonical type might not contain an unexpanded parameter pack, if it - // contains an alias template specialization which ignores one of its - // parameters. - if (Canon->containsUnexpandedParameterPack()) { - Canon = getPackExpansionType(Canon, NumExpansions); + Canon = getPackExpansionType(getCanonicalType(Pattern), NumExpansions, + /*ExpectPackInType=*/false); - // Find the insert position again, in case we inserted an element into - // PackExpansionTypes and invalidated our insert position. - PackExpansionTypes.FindNodeOrInsertPos(ID, InsertPos); - } + // Find the insert position again, in case we inserted an element into + // PackExpansionTypes and invalidated our insert position. + PackExpansionTypes.FindNodeOrInsertPos(ID, InsertPos); } T = new (*this, TypeAlignment) @@ -7062,6 +7239,9 @@ static char getObjCEncodingForPrimitiveType(const ASTContext *C, case BuiltinType::OCLReserveID: case BuiltinType::OCLSampler: case BuiltinType::Dependent: +#define PPC_VECTOR_TYPE(Name, Id, Size) \ + case BuiltinType::Id: +#include "clang/Basic/PPCTypes.def" #define BUILTIN_TYPE(KIND, ID) #define PLACEHOLDER_TYPE(KIND, ID) \ case BuiltinType::KIND: @@ -7498,7 +7678,9 @@ void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl, } unsigned i = 0; - for (auto *Field : RDecl->fields()) { + for (FieldDecl *Field : RDecl->fields()) { + if (!Field->isZeroLengthBitField(*this) && Field->isZeroSize(*this)) + continue; uint64_t offs = layout.getFieldOffset(i); FieldOrBaseOffsets.insert(FieldOrBaseOffsets.upper_bound(offs), std::make_pair(offs, Field)); @@ -8354,12 +8536,90 @@ bool ASTContext::areCompatibleVectorTypes(QualType FirstVec, First->getVectorKind() != VectorType::AltiVecPixel && First->getVectorKind() != VectorType::AltiVecBool && Second->getVectorKind() != VectorType::AltiVecPixel && - Second->getVectorKind() != VectorType::AltiVecBool) + Second->getVectorKind() != VectorType::AltiVecBool && + First->getVectorKind() != VectorType::SveFixedLengthDataVector && + First->getVectorKind() != VectorType::SveFixedLengthPredicateVector && + Second->getVectorKind() != VectorType::SveFixedLengthDataVector && + Second->getVectorKind() != VectorType::SveFixedLengthPredicateVector) return true; return false; } +bool ASTContext::areCompatibleSveTypes(QualType FirstType, + QualType SecondType) { + assert(((FirstType->isSizelessBuiltinType() && SecondType->isVectorType()) || + (FirstType->isVectorType() && SecondType->isSizelessBuiltinType())) && + "Expected SVE builtin type and vector type!"); + + auto IsValidCast = [this](QualType FirstType, QualType SecondType) { + if (const auto *BT = FirstType->getAs()) { + if (const auto *VT = SecondType->getAs()) { + // Predicates have the same representation as uint8 so we also have to + // check the kind to make these types incompatible. + if (VT->getVectorKind() == VectorType::SveFixedLengthPredicateVector) + return BT->getKind() == BuiltinType::SveBool; + else if (VT->getVectorKind() == VectorType::SveFixedLengthDataVector) + return VT->getElementType().getCanonicalType() == + FirstType->getSveEltType(*this); + else if (VT->getVectorKind() == VectorType::GenericVector) + return getTypeSize(SecondType) == getLangOpts().ArmSveVectorBits && + hasSameType(VT->getElementType(), + getBuiltinVectorTypeInfo(BT).ElementType); + } + } + return false; + }; + + return IsValidCast(FirstType, SecondType) || + IsValidCast(SecondType, FirstType); +} + +bool ASTContext::areLaxCompatibleSveTypes(QualType FirstType, + QualType SecondType) { + assert(((FirstType->isSizelessBuiltinType() && SecondType->isVectorType()) || + (FirstType->isVectorType() && SecondType->isSizelessBuiltinType())) && + "Expected SVE builtin type and vector type!"); + + auto IsLaxCompatible = [this](QualType FirstType, QualType SecondType) { + if (!FirstType->getAs()) + return false; + + const auto *VecTy = SecondType->getAs(); + if (VecTy && + (VecTy->getVectorKind() == VectorType::SveFixedLengthDataVector || + VecTy->getVectorKind() == VectorType::GenericVector)) { + const LangOptions::LaxVectorConversionKind LVCKind = + getLangOpts().getLaxVectorConversions(); + + // If __ARM_FEATURE_SVE_BITS != N do not allow GNU vector lax conversion. + // "Whenever __ARM_FEATURE_SVE_BITS==N, GNUT implicitly + // converts to VLAT and VLAT implicitly converts to GNUT." + // ACLE Spec Version 00bet6, 3.7.3.2. Behavior common to vectors and + // predicates. + if (VecTy->getVectorKind() == VectorType::GenericVector && + getTypeSize(SecondType) != getLangOpts().ArmSveVectorBits) + return false; + + // If -flax-vector-conversions=all is specified, the types are + // certainly compatible. + if (LVCKind == LangOptions::LaxVectorConversionKind::All) + return true; + + // If -flax-vector-conversions=integer is specified, the types are + // compatible if the elements are integer types. + if (LVCKind == LangOptions::LaxVectorConversionKind::Integer) + return VecTy->getElementType().getCanonicalType()->isIntegerType() && + FirstType->getSveEltType(*this)->isIntegerType(); + } + + return false; + }; + + return IsLaxCompatible(FirstType, SecondType) || + IsLaxCompatible(SecondType, FirstType); +} + bool ASTContext::hasDirectOwnershipQualifier(QualType Ty) const { while (true) { // __strong id @@ -9255,8 +9515,8 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, // designates the object or function denoted by the reference, and the // expression is an lvalue unless the reference is an rvalue reference and // the expression is a function call (possibly inside parentheses). - assert(!LHS->getAs() && "LHS is a reference type?"); - assert(!RHS->getAs() && "RHS is a reference type?"); + if (LHS->getAs() || RHS->getAs()) + return {}; if (Unqualified) { LHS = LHS.getUnqualifiedType(); @@ -9471,17 +9731,15 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, const ConstantArrayType* CAT) -> std::pair { if (VAT) { - llvm::APSInt TheInt; + Optional TheInt; Expr *E = VAT->getSizeExpr(); - if (E && E->isIntegerConstantExpr(TheInt, *this)) - return std::make_pair(true, TheInt); - else - return std::make_pair(false, TheInt); - } else if (CAT) { - return std::make_pair(true, CAT->getSize()); - } else { - return std::make_pair(false, llvm::APInt()); + if (E && (TheInt = E->getIntegerConstantExpr(*this))) + return std::make_pair(true, *TheInt); + return std::make_pair(false, llvm::APSInt()); } + if (CAT) + return std::make_pair(true, CAT->getSize()); + return std::make_pair(false, llvm::APInt()); }; bool HaveLSize, HaveRSize; @@ -9760,6 +10018,11 @@ QualType ASTContext::getCorrespondingUnsignedType(QualType T) const { return UnsignedLongLongTy; case BuiltinType::Int128: return UnsignedInt128Ty; + // wchar_t is special. It is either signed or not, but when it's signed, + // there's no matching "unsigned wchar_t". Therefore we return the unsigned + // version of it's underlying type instead. + case BuiltinType::WChar_S: + return getUnsignedWCharType(); case BuiltinType::ShortAccum: return UnsignedShortAccumTy; @@ -10136,6 +10399,18 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context, return Type; } +// On some targets such as PowerPC, some of the builtins are defined with custom +// type decriptors for target-dependent types. These descriptors are decoded in +// other functions, but it may be useful to be able to fall back to default +// descriptor decoding to define builtins mixing target-dependent and target- +// independent types. This function allows decoding one type descriptor with +// default decoding. +QualType ASTContext::DecodeTypeStr(const char *&Str, const ASTContext &Context, + GetBuiltinTypeError &Error, bool &RequireICE, + bool AllowTypeModifiers) const { + return DecodeTypeFromStr(Str, Context, Error, RequireICE, AllowTypeModifiers); +} + /// GetBuiltinType - Return the type for the specified builtin. QualType ASTContext::GetBuiltinType(unsigned Id, GetBuiltinTypeError &Error, @@ -10273,12 +10548,17 @@ static GVALinkage adjustGVALinkageForAttributes(const ASTContext &Context, } else if (D->hasAttr()) { if (L == GVA_DiscardableODR) return GVA_StrongODR; - } else if (Context.getLangOpts().CUDA && Context.getLangOpts().CUDAIsDevice && - D->hasAttr()) { + } else if (Context.getLangOpts().CUDA && Context.getLangOpts().CUDAIsDevice) { // Device-side functions with __global__ attribute must always be // visible externally so they can be launched from host. - if (L == GVA_DiscardableODR || L == GVA_Internal) + if (D->hasAttr() && + (L == GVA_DiscardableODR || L == GVA_Internal)) return GVA_StrongODR; + // Single source offloading languages like CUDA/HIP need to be able to + // access static device variables from host code of the same compilation + // unit. This is done by externalizing the static variable. + if (Context.shouldExternalizeStaticVar(D)) + return GVA_StrongExternal; } return L; } @@ -10428,37 +10708,6 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { else return false; - if (D->isFromASTFile() && !LangOpts.BuildingPCHWithObjectFile) { - assert(getExternalSource() && "It's from an AST file; must have a source."); - // On Windows, PCH files are built together with an object file. If this - // declaration comes from such a PCH and DeclMustBeEmitted would return - // true, it would have returned true and the decl would have been emitted - // into that object file, so it doesn't need to be emitted here. - // Note that decls are still emitted if they're referenced, as usual; - // DeclMustBeEmitted is used to decide whether a decl must be emitted even - // if it's not referenced. - // - // Explicit template instantiation definitions are tricky. If there was an - // explicit template instantiation decl in the PCH before, it will look like - // the definition comes from there, even if that was just the declaration. - // (Explicit instantiation defs of variable templates always get emitted.) - bool IsExpInstDef = - isa(D) && - cast(D)->getTemplateSpecializationKind() == - TSK_ExplicitInstantiationDefinition; - - // Implicit member function definitions, such as operator= might not be - // marked as template specializations, since they're not coming from a - // template but synthesized directly on the class. - IsExpInstDef |= - isa(D) && - cast(D)->getParent()->getTemplateSpecializationKind() == - TSK_ExplicitInstantiationDefinition; - - if (getExternalSource()->DeclIsFromPCHWithObjectFile(D) && !IsExpInstDef) - return false; - } - // If this is a member of a class template, we do not need to emit it. if (D->getDeclContext()->isDependentContext()) return false; @@ -10623,13 +10872,13 @@ MangleContext *ASTContext::createMangleContext(const TargetInfo *T) { if (!T) T = Target; switch (T->getCXXABI().getKind()) { + case TargetCXXABI::AppleARM64: case TargetCXXABI::Fuchsia: case TargetCXXABI::GenericAArch64: case TargetCXXABI::GenericItanium: case TargetCXXABI::GenericARM: case TargetCXXABI::GenericMIPS: case TargetCXXABI::iOS: - case TargetCXXABI::iOS64: case TargetCXXABI::WebAssembly: case TargetCXXABI::WatchOS: case TargetCXXABI::XL: @@ -10823,6 +11072,27 @@ ASTContext::getMSGuidDecl(MSGuidDecl::Parts Parts) const { return New; } +TemplateParamObjectDecl * +ASTContext::getTemplateParamObjectDecl(QualType T, const APValue &V) const { + assert(T->isRecordType() && "template param object of unexpected type"); + + // C++ [temp.param]p8: + // [...] a static storage duration object of type 'const T' [...] + T.addConst(); + + llvm::FoldingSetNodeID ID; + TemplateParamObjectDecl::Profile(ID, T, V); + + void *InsertPos; + if (TemplateParamObjectDecl *Existing = + TemplateParamObjectDecls.FindNodeOrInsertPos(ID, InsertPos)) + return Existing; + + TemplateParamObjectDecl *New = TemplateParamObjectDecl::Create(*this, T, V); + TemplateParamObjectDecls.InsertNode(New, InsertPos); + return New; +} + bool ASTContext::AtomicUsesUnsupportedLibcall(const AtomicExpr *E) const { const llvm::Triple &T = getTargetInfo().getTriple(); if (!T.isOSDarwin()) @@ -11030,29 +11300,30 @@ unsigned char ASTContext::getFixedPointIBits(QualType Ty) const { } } -FixedPointSemantics ASTContext::getFixedPointSemantics(QualType Ty) const { +llvm::FixedPointSemantics +ASTContext::getFixedPointSemantics(QualType Ty) const { assert((Ty->isFixedPointType() || Ty->isIntegerType()) && "Can only get the fixed point semantics for a " "fixed point or integer type."); if (Ty->isIntegerType()) - return FixedPointSemantics::GetIntegerSemantics(getIntWidth(Ty), - Ty->isSignedIntegerType()); + return llvm::FixedPointSemantics::GetIntegerSemantics( + getIntWidth(Ty), Ty->isSignedIntegerType()); bool isSigned = Ty->isSignedFixedPointType(); - return FixedPointSemantics( + return llvm::FixedPointSemantics( static_cast(getTypeSize(Ty)), getFixedPointScale(Ty), isSigned, Ty->isSaturatedFixedPointType(), !isSigned && getTargetInfo().doUnsignedFixedPointTypesHavePadding()); } -APFixedPoint ASTContext::getFixedPointMax(QualType Ty) const { +llvm::APFixedPoint ASTContext::getFixedPointMax(QualType Ty) const { assert(Ty->isFixedPointType()); - return APFixedPoint::getMax(getFixedPointSemantics(Ty)); + return llvm::APFixedPoint::getMax(getFixedPointSemantics(Ty)); } -APFixedPoint ASTContext::getFixedPointMin(QualType Ty) const { +llvm::APFixedPoint ASTContext::getFixedPointMin(QualType Ty) const { assert(Ty->isFixedPointType()); - return APFixedPoint::getMin(getFixedPointSemantics(Ty)); + return llvm::APFixedPoint::getMin(getFixedPointSemantics(Ty)); } QualType ASTContext::getCorrespondingSignedFixedPointType(QualType Ty) const { @@ -11147,8 +11418,7 @@ void ASTContext::getFunctionFeatureMap(llvm::StringMap &FeatureMap, std::vector Features(FeaturesTmp.begin(), FeaturesTmp.end()); Target->initFeatureMap(FeatureMap, getDiagnostics(), TargetCPU, Features); } else { - Target->initFeatureMap(FeatureMap, getDiagnostics(), TargetCPU, - Target->getTargetOpts().Features); + FeatureMap = Target->getTargetOpts().FeatureMap; } } @@ -11157,10 +11427,25 @@ OMPTraitInfo &ASTContext::getNewOMPTraitInfo() { return *OMPTraitInfoVector.back(); } -const DiagnosticBuilder & -clang::operator<<(const DiagnosticBuilder &DB, - const ASTContext::SectionInfo &Section) { +const StreamingDiagnostic &clang:: +operator<<(const StreamingDiagnostic &DB, + const ASTContext::SectionInfo &Section) { if (Section.Decl) return DB << Section.Decl; return DB << "a prior #pragma section"; } + +bool ASTContext::mayExternalizeStaticVar(const Decl *D) const { + return !getLangOpts().GPURelocatableDeviceCode && + ((D->hasAttr() && + !D->getAttr()->isImplicit()) || + (D->hasAttr() && + !D->getAttr()->isImplicit())) && + isa(D) && cast(D)->isFileVarDecl() && + cast(D)->getStorageClass() == SC_Static; +} + +bool ASTContext::shouldExternalizeStaticVar(const Decl *D) const { + return mayExternalizeStaticVar(D) && + CUDAStaticDeviceVarReferencedByHost.count(cast(D)); +} diff --git a/clang/lib/AST/ASTDiagnostic.cpp b/clang/lib/AST/ASTDiagnostic.cpp index 05adf226bae3..2bc731717b98 100644 --- a/clang/lib/AST/ASTDiagnostic.cpp +++ b/clang/lib/AST/ASTDiagnostic.cpp @@ -1560,11 +1560,11 @@ class TemplateDiff { if (!Tree.HasChildren()) { // If we're dealing with a template specialization with zero // arguments, there are no children; special-case this. - OS << FromTD->getNameAsString() << "<>"; + OS << FromTD->getDeclName() << "<>"; return; } - OS << FromTD->getNameAsString() << '<'; + OS << FromTD->getDeclName() << '<'; Tree.MoveToChild(); unsigned NumElideArgs = 0; bool AllArgsElided = true; @@ -1724,7 +1724,7 @@ class TemplateDiff { } if (Same) { - OS << "template " << FromTD->getNameAsString(); + OS << "template " << FromTD->getDeclName(); } else if (!PrintTree) { OS << (FromDefault ? "(default) template " : "template "); Bold(); @@ -1834,7 +1834,14 @@ class TemplateDiff { if (VD) { if (AddressOf) OS << "&"; - OS << VD->getName(); + else if (auto *TPO = dyn_cast(VD)) { + // FIXME: Diffing the APValue would be neat. + // FIXME: Suppress this and use the full name of the declaration if the + // parameter is a pointer or reference. + TPO->printAsInit(OS); + return; + } + VD->printName(OS); return; } diff --git a/clang/lib/AST/ASTDumper.cpp b/clang/lib/AST/ASTDumper.cpp index 284e5bdbc6b0..3d368a0a7b63 100644 --- a/clang/lib/AST/ASTDumper.cpp +++ b/clang/lib/AST/ASTDumper.cpp @@ -129,9 +129,11 @@ void ASTDumper::dumpTemplateDecl(const TemplateDecl *D, bool DumpExplicitInst) { Visit(D->getTemplatedDecl()); - for (const auto *Child : D->specializations()) - dumpTemplateDeclSpecialization(Child, DumpExplicitInst, - !D->isCanonicalDecl()); + if (GetTraversalKind() == TK_AsIs) { + for (const auto *Child : D->specializations()) + dumpTemplateDeclSpecialization(Child, DumpExplicitInst, + !D->isCanonicalDecl()); + } } void ASTDumper::VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) { diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 3779e0cb872b..085c50c0667b 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -202,6 +202,9 @@ namespace clang { return *MaybeVal; } + ExplicitSpecifier importExplicitSpecifier(Error &Err, + ExplicitSpecifier ESpec); + // Wrapper for an overload set. template struct CallOverloadedCreateFun { template decltype(auto) operator()(Args &&... args) { @@ -261,16 +264,6 @@ namespace clang { void InitializeImportedDecl(Decl *FromD, Decl *ToD) { ToD->IdentifierNamespace = FromD->IdentifierNamespace; - if (FromD->hasAttrs()) - for (const Attr *FromAttr : FromD->getAttrs()) { - // FIXME: Return of the error here is not possible until store of - // import errors is implemented. - auto ToAttrOrErr = import(FromAttr); - if (ToAttrOrErr) - ToD->addAttr(*ToAttrOrErr); - else - llvm::consumeError(ToAttrOrErr.takeError()); - } if (FromD->isUsed()) ToD->setIsUsed(); if (FromD->isImplicit()) @@ -385,6 +378,8 @@ namespace clang { ExpectedType VisitObjCObjectPointerType(const ObjCObjectPointerType *T); // Importing declarations + Error ImportDeclParts(NamedDecl *D, DeclarationName &Name, NamedDecl *&ToD, + SourceLocation &Loc); Error ImportDeclParts( NamedDecl *D, DeclContext *&DC, DeclContext *&LexicalDC, DeclarationName &Name, NamedDecl *&ToD, SourceLocation &Loc); @@ -397,6 +392,7 @@ namespace clang { Error ImportImplicitMethods(const CXXRecordDecl *From, CXXRecordDecl *To); Expected ImportCastPath(CastExpr *E); + Expected ImportAPValue(const APValue &FromValue); using Designator = DesignatedInitExpr::Designator; @@ -498,6 +494,7 @@ namespace clang { ExpectedDecl VisitCXXConstructorDecl(CXXConstructorDecl *D); ExpectedDecl VisitCXXDestructorDecl(CXXDestructorDecl *D); ExpectedDecl VisitCXXConversionDecl(CXXConversionDecl *D); + ExpectedDecl VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D); ExpectedDecl VisitFieldDecl(FieldDecl *D); ExpectedDecl VisitIndirectFieldDecl(IndirectFieldDecl *D); ExpectedDecl VisitFriendDecl(FriendDecl *D); @@ -580,6 +577,7 @@ namespace clang { ExpectedStmt VisitVAArgExpr(VAArgExpr *E); ExpectedStmt VisitChooseExpr(ChooseExpr *E); ExpectedStmt VisitGNUNullExpr(GNUNullExpr *E); + ExpectedStmt VisitGenericSelectionExpr(GenericSelectionExpr *E); ExpectedStmt VisitPredefinedExpr(PredefinedExpr *E); ExpectedStmt VisitDeclRefExpr(DeclRefExpr *E); ExpectedStmt VisitImplicitValueInitExpr(ImplicitValueInitExpr *E); @@ -646,6 +644,7 @@ namespace clang { ExpectedStmt VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *E); ExpectedStmt VisitTypeTraitExpr(TypeTraitExpr *E); ExpectedStmt VisitCXXTypeidExpr(CXXTypeidExpr *E); + ExpectedStmt VisitCXXFoldExpr(CXXFoldExpr *E); template Error ImportArrayChecked(IIter Ibegin, IIter Iend, OIter Obegin) { @@ -882,11 +881,9 @@ ASTNodeImporter::import(const TemplateArgumentLoc &TALoc) { import(FromInfo.getTemplateEllipsisLoc()); if (!ToTemplateEllipsisLocOrErr) return ToTemplateEllipsisLocOrErr.takeError(); - ToInfo = TemplateArgumentLocInfo( - *ToTemplateQualifierLocOrErr, - *ToTemplateNameLocOrErr, - *ToTemplateEllipsisLocOrErr); + Importer.getToContext(), *ToTemplateQualifierLocOrErr, + *ToTemplateNameLocOrErr, *ToTemplateEllipsisLocOrErr); } return TemplateArgumentLoc(Arg, ToInfo); @@ -1036,6 +1033,10 @@ ExpectedType ASTNodeImporter::VisitBuiltinType(const BuiltinType *T) { case BuiltinType::Id: \ return Importer.getToContext().SingletonId; #include "clang/Basic/AArch64SVEACLETypes.def" +#define PPC_VECTOR_TYPE(Name, Id, Size) \ + case BuiltinType::Id: \ + return Importer.getToContext().Id##Ty; +#include "clang/Basic/PPCTypes.def" #define SHARED_SINGLETON_TYPE(Expansion) #define BUILTIN_TYPE(Id, SingletonId) \ case BuiltinType::Id: return Importer.getToContext().SingletonId; @@ -1498,7 +1499,8 @@ ASTNodeImporter::VisitPackExpansionType(const PackExpansionType *T) { return ToPatternOrErr.takeError(); return Importer.getToContext().getPackExpansionType(*ToPatternOrErr, - T->getNumExpansions()); + T->getNumExpansions(), + /*ExpactPack=*/false); } ExpectedType ASTNodeImporter::VisitDependentTemplateSpecializationType( @@ -1639,6 +1641,25 @@ Error ASTNodeImporter::ImportDeclParts( return Error::success(); } +Error ASTNodeImporter::ImportDeclParts(NamedDecl *D, DeclarationName &Name, + NamedDecl *&ToD, SourceLocation &Loc) { + + // Import the name of this declaration. + if (Error Err = importInto(Name, D->getDeclName())) + return Err; + + // Import the location of this declaration. + if (Error Err = importInto(Loc, D->getLocation())) + return Err; + + ToD = cast_or_null(Importer.GetAlreadyImportedOrNull(D)); + if (ToD) + if (Error Err = ASTNodeImporter(*this).ImportDefinitionIfNeeded(D, ToD)) + return Err; + + return Error::success(); +} + Error ASTNodeImporter::ImportDefinitionIfNeeded(Decl *FromD, Decl *ToD) { if (!FromD) return Error::success(); @@ -1743,12 +1764,28 @@ ASTNodeImporter::ImportDeclContext(DeclContext *FromDC, bool ForceImport) { Decl *ImportedDecl = *ImportedOrErr; FieldDecl *FieldTo = dyn_cast_or_null(ImportedDecl); if (FieldFrom && FieldTo) { - const RecordType *RecordFrom = FieldFrom->getType()->getAs(); - const RecordType *RecordTo = FieldTo->getType()->getAs(); - if (RecordFrom && RecordTo) { - RecordDecl *FromRecordDecl = RecordFrom->getDecl(); - RecordDecl *ToRecordDecl = RecordTo->getDecl(); + RecordDecl *FromRecordDecl = nullptr; + RecordDecl *ToRecordDecl = nullptr; + // If we have a field that is an ArrayType we need to check if the array + // element is a RecordDecl and if so we need to import the defintion. + if (FieldFrom->getType()->isArrayType()) { + // getBaseElementTypeUnsafe(...) handles multi-dimensonal arrays for us. + FromRecordDecl = FieldFrom->getType()->getBaseElementTypeUnsafe()->getAsRecordDecl(); + ToRecordDecl = FieldTo->getType()->getBaseElementTypeUnsafe()->getAsRecordDecl(); + } + + if (!FromRecordDecl || !ToRecordDecl) { + const RecordType *RecordFrom = + FieldFrom->getType()->getAs(); + const RecordType *RecordTo = FieldTo->getType()->getAs(); + + if (RecordFrom && RecordTo) { + FromRecordDecl = RecordFrom->getDecl(); + ToRecordDecl = RecordTo->getDecl(); + } + } + if (FromRecordDecl && ToRecordDecl) { if (FromRecordDecl->isCompleteDefinition() && !ToRecordDecl->isCompleteDefinition()) { Error Err = ImportDefinition(FromRecordDecl, ToRecordDecl); @@ -1900,7 +1937,8 @@ Error ASTNodeImporter::ImportDefinition( else return ToCaptureOrErr.takeError(); } - cast(To)->setCaptures(ToCaptures); + cast(To)->setCaptures(Importer.getToContext(), + ToCaptures); } Error Result = ImportDeclContext(From, /*ForceImport=*/true); @@ -1998,10 +2036,11 @@ Error ASTNodeImporter::ImportInitializer(VarDecl *From, VarDecl *To) { return ToInitOrErr.takeError(); To->setInit(*ToInitOrErr); - if (From->isInitKnownICE()) { - EvaluatedStmt *Eval = To->ensureEvaluatedStmt(); - Eval->CheckedICE = true; - Eval->IsICE = From->isInitICE(); + if (EvaluatedStmt *FromEval = From->getEvaluatedStmt()) { + EvaluatedStmt *ToEval = To->ensureEvaluatedStmt(); + ToEval->HasConstantInitialization = FromEval->HasConstantInitialization; + ToEval->HasConstantDestruction = FromEval->HasConstantDestruction; + // FIXME: Also import the initializer value. } // FIXME: Other bits to merge? @@ -2389,22 +2428,29 @@ ExpectedDecl ASTNodeImporter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { ExpectedDecl ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) { // Import the major distinguishing characteristics of this typedef. - DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; NamedDecl *ToD; - if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) + // Do not import the DeclContext, we will import it once the TypedefNameDecl + // is created. + if (Error Err = ImportDeclParts(D, Name, ToD, Loc)) return std::move(Err); if (ToD) return ToD; + DeclContext *DC = cast_or_null( + Importer.GetAlreadyImportedOrNull(cast(D->getDeclContext()))); + DeclContext *LexicalDC = + cast_or_null(Importer.GetAlreadyImportedOrNull( + cast(D->getLexicalDeclContext()))); + // If this typedef is not in block scope, determine whether we've // seen a typedef with the same name (that we can merge with) or any // other entity by that name (which name lookup could conflict with). // Note: Repeated typedefs are not valid in C99: // 'typedef int T; typedef int T;' is invalid // We do not care about this now. - if (!DC->isFunctionOrMethod()) { + if (DC && !DC->isFunctionOrMethod()) { SmallVector ConflictingDecls; unsigned IDNS = Decl::IDNS_Ordinary; auto FoundDecls = Importer.findDeclsInToCtx(DC, Name); @@ -2461,8 +2507,15 @@ ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) { Name.getAsIdentifierInfo(), ToTypeSourceInfo)) return ToTypedef; - ToTypedef->setAccess(D->getAccess()); + // Import the DeclContext and set it to the Typedef. + if ((Err = ImportDeclContext(D, DC, LexicalDC))) + return std::move(Err); + ToTypedef->setDeclContext(DC); ToTypedef->setLexicalDeclContext(LexicalDC); + // Add to the lookupTable because we could not do that in MapImported. + Importer.AddToLookupTable(ToTypedef); + + ToTypedef->setAccess(D->getAccess()); // Templated declarations should not appear in DeclContext. TypeAliasDecl *FromAlias = IsAlias ? cast(D) : nullptr; @@ -3130,6 +3183,14 @@ bool ASTNodeImporter::hasAutoReturnTypeDeclaredInside(FunctionDecl *D) { return false; } +ExplicitSpecifier +ASTNodeImporter::importExplicitSpecifier(Error &Err, ExplicitSpecifier ESpec) { + Expr *ExplicitExpr = ESpec.getExpr(); + if (ExplicitExpr) + ExplicitExpr = importChecked(Err, ESpec.getExpr()); + return ExplicitSpecifier(ExplicitExpr, ESpec.getKind()); +} + ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { SmallVector Redecls = getCanonicalForwardRedeclChain(D); @@ -3309,20 +3370,14 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { // Create the imported function. FunctionDecl *ToFunction = nullptr; if (auto *FromConstructor = dyn_cast(D)) { - Expr *ExplicitExpr = nullptr; - if (FromConstructor->getExplicitSpecifier().getExpr()) { - auto Imp = import(FromConstructor->getExplicitSpecifier().getExpr()); - if (!Imp) - return Imp.takeError(); - ExplicitExpr = *Imp; - } + ExplicitSpecifier ESpec = + importExplicitSpecifier(Err, FromConstructor->getExplicitSpecifier()); + if (Err) + return std::move(Err); if (GetImportedOrCreateDecl( ToFunction, D, Importer.getToContext(), cast(DC), - ToInnerLocStart, NameInfo, T, TInfo, - ExplicitSpecifier( - ExplicitExpr, - FromConstructor->getExplicitSpecifier().getKind()), - D->isInlineSpecified(), D->isImplicit(), D->getConstexprKind(), + ToInnerLocStart, NameInfo, T, TInfo, ESpec, D->isInlineSpecified(), + D->isImplicit(), D->getConstexprKind(), InheritedConstructor(), // FIXME: Properly import inherited // constructor info TrailingRequiresClause)) @@ -3347,18 +3402,13 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { ToDtor->setOperatorDelete(ToOperatorDelete, ToThisArg); } else if (CXXConversionDecl *FromConversion = dyn_cast(D)) { - Expr *ExplicitExpr = nullptr; - if (FromConversion->getExplicitSpecifier().getExpr()) { - auto Imp = import(FromConversion->getExplicitSpecifier().getExpr()); - if (!Imp) - return Imp.takeError(); - ExplicitExpr = *Imp; - } + ExplicitSpecifier ESpec = + importExplicitSpecifier(Err, FromConversion->getExplicitSpecifier()); + if (Err) + return std::move(Err); if (GetImportedOrCreateDecl( ToFunction, D, Importer.getToContext(), cast(DC), - ToInnerLocStart, NameInfo, T, TInfo, D->isInlineSpecified(), - ExplicitSpecifier(ExplicitExpr, - FromConversion->getExplicitSpecifier().getKind()), + ToInnerLocStart, NameInfo, T, TInfo, D->isInlineSpecified(), ESpec, D->getConstexprKind(), SourceLocation(), TrailingRequiresClause)) return ToFunction; } else if (auto *Method = dyn_cast(D)) { @@ -3368,6 +3418,17 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { Method->isInlineSpecified(), D->getConstexprKind(), SourceLocation(), TrailingRequiresClause)) return ToFunction; + } else if (auto *Guide = dyn_cast(D)) { + ExplicitSpecifier ESpec = + importExplicitSpecifier(Err, Guide->getExplicitSpecifier()); + if (Err) + return std::move(Err); + if (GetImportedOrCreateDecl( + ToFunction, D, Importer.getToContext(), DC, ToInnerLocStart, ESpec, + NameInfo, T, TInfo, ToEndLoc)) + return ToFunction; + cast(ToFunction) + ->setIsCopyDeductionCandidate(Guide->isCopyDeductionCandidate()); } else { if (GetImportedOrCreateDecl( ToFunction, D, Importer.getToContext(), DC, ToInnerLocStart, @@ -3495,6 +3556,11 @@ ExpectedDecl ASTNodeImporter::VisitCXXConversionDecl(CXXConversionDecl *D) { return VisitCXXMethodDecl(D); } +ExpectedDecl +ASTNodeImporter::VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D) { + return VisitFunctionDecl(D); +} + ExpectedDecl ASTNodeImporter::VisitFieldDecl(FieldDecl *D) { // Import the major distinguishing characteristics of a variable. DeclContext *DC, *LexicalDC; @@ -4758,11 +4824,10 @@ Error ASTNodeImporter::ImportDefinition( return ToImplOrErr.takeError(); } - if (shouldForceImportDeclContext(Kind)) { - // Import all of the members of this class. - if (Error Err = ImportDeclContext(From, /*ForceImport=*/true)) - return Err; - } + // Import all of the members of this class. + if (Error Err = ImportDeclContext(From, /*ForceImport=*/true)) + return Err; + return Error::success(); } @@ -5137,8 +5202,6 @@ ASTNodeImporter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) { // context. This context will be fixed when the actual template declaration // is created. - // FIXME: Import default argument and constraint expression. - ExpectedSLoc BeginLocOrErr = import(D->getBeginLoc()); if (!BeginLocOrErr) return BeginLocOrErr.takeError(); @@ -5185,6 +5248,14 @@ ASTNodeImporter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) { ToIDC); } + if (D->hasDefaultArgument()) { + Expected ToDefaultArgOrErr = + import(D->getDefaultArgumentInfo()); + if (!ToDefaultArgOrErr) + return ToDefaultArgOrErr.takeError(); + ToD->setDefaultArgument(*ToDefaultArgOrErr); + } + return ToD; } @@ -5200,15 +5271,22 @@ ASTNodeImporter::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) { if (Err) return std::move(Err); - // FIXME: Import default argument. - NonTypeTemplateParmDecl *ToD = nullptr; - (void)GetImportedOrCreateDecl( - ToD, D, Importer.getToContext(), - Importer.getToContext().getTranslationUnitDecl(), - ToInnerLocStart, ToLocation, D->getDepth(), - D->getPosition(), ToDeclName.getAsIdentifierInfo(), ToType, - D->isParameterPack(), ToTypeSourceInfo); + if (GetImportedOrCreateDecl(ToD, D, Importer.getToContext(), + Importer.getToContext().getTranslationUnitDecl(), + ToInnerLocStart, ToLocation, D->getDepth(), + D->getPosition(), + ToDeclName.getAsIdentifierInfo(), ToType, + D->isParameterPack(), ToTypeSourceInfo)) + return ToD; + + if (D->hasDefaultArgument()) { + ExpectedExpr ToDefaultArgOrErr = import(D->getDefaultArgument()); + if (!ToDefaultArgOrErr) + return ToDefaultArgOrErr.takeError(); + ToD->setDefaultArgument(*ToDefaultArgOrErr); + } + return ToD; } @@ -5229,15 +5307,22 @@ ASTNodeImporter::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) { if (!TemplateParamsOrErr) return TemplateParamsOrErr.takeError(); - // FIXME: Import default argument. - TemplateTemplateParmDecl *ToD = nullptr; - (void)GetImportedOrCreateDecl( - ToD, D, Importer.getToContext(), - Importer.getToContext().getTranslationUnitDecl(), *LocationOrErr, - D->getDepth(), D->getPosition(), D->isParameterPack(), - (*NameOrErr).getAsIdentifierInfo(), - *TemplateParamsOrErr); + if (GetImportedOrCreateDecl( + ToD, D, Importer.getToContext(), + Importer.getToContext().getTranslationUnitDecl(), *LocationOrErr, + D->getDepth(), D->getPosition(), D->isParameterPack(), + (*NameOrErr).getAsIdentifierInfo(), *TemplateParamsOrErr)) + return ToD; + + if (D->hasDefaultArgument()) { + Expected ToDefaultArgOrErr = + import(D->getDefaultArgument()); + if (!ToDefaultArgOrErr) + return ToDefaultArgOrErr.takeError(); + ToD->setDefaultArgument(Importer.getToContext(), *ToDefaultArgOrErr); + } + return ToD; } @@ -5309,16 +5394,16 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { CXXRecordDecl *FromTemplated = D->getTemplatedDecl(); + auto TemplateParamsOrErr = import(D->getTemplateParameters()); + if (!TemplateParamsOrErr) + return TemplateParamsOrErr.takeError(); + // Create the declaration that is being templated. CXXRecordDecl *ToTemplated; if (Error Err = importInto(ToTemplated, FromTemplated)) return std::move(Err); // Create the class template declaration itself. - auto TemplateParamsOrErr = import(D->getTemplateParameters()); - if (!TemplateParamsOrErr) - return TemplateParamsOrErr.takeError(); - ClassTemplateDecl *D2; if (GetImportedOrCreateDecl(D2, D, Importer.getToContext(), DC, Loc, Name, *TemplateParamsOrErr, ToTemplated)) @@ -5402,8 +5487,9 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateSpecializationDecl( if (PrevDecl) { if (IsStructuralMatch(D, PrevDecl)) { - if (D->isThisDeclarationADefinition() && PrevDecl->getDefinition()) { - Importer.MapImported(D, PrevDecl->getDefinition()); + CXXRecordDecl *PrevDefinition = PrevDecl->getDefinition(); + if (D->isThisDeclarationADefinition() && PrevDefinition) { + Importer.MapImported(D, PrevDefinition); // Import those default field initializers which have been // instantiated in the "From" context, but not in the "To" context. for (auto *FromField : D->fields()) { @@ -5425,7 +5511,7 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateSpecializationDecl( // // Generally, ASTCommon.h/DeclUpdateKind enum gives a very good hint // what else could be fused during an AST merge. - return PrevDecl; + return PrevDefinition; } } else { // ODR violation. // FIXME HandleNameConflict @@ -6066,6 +6152,8 @@ ExpectedStmt ASTNodeImporter::VisitIfStmt(IfStmt *S) { auto ToInit = importChecked(Err, S->getInit()); auto ToConditionVariable = importChecked(Err, S->getConditionVariable()); auto ToCond = importChecked(Err, S->getCond()); + auto ToLParenLoc = importChecked(Err, S->getLParenLoc()); + auto ToRParenLoc = importChecked(Err, S->getRParenLoc()); auto ToThen = importChecked(Err, S->getThen()); auto ToElseLoc = importChecked(Err, S->getElseLoc()); auto ToElse = importChecked(Err, S->getElse()); @@ -6073,8 +6161,8 @@ ExpectedStmt ASTNodeImporter::VisitIfStmt(IfStmt *S) { return std::move(Err); return IfStmt::Create(Importer.getToContext(), ToIfLoc, S->isConstexpr(), - ToInit, ToConditionVariable, ToCond, ToThen, ToElseLoc, - ToElse); + ToInit, ToConditionVariable, ToCond, ToLParenLoc, + ToRParenLoc, ToThen, ToElseLoc, ToElse); } ExpectedStmt ASTNodeImporter::VisitSwitchStmt(SwitchStmt *S) { @@ -6083,13 +6171,16 @@ ExpectedStmt ASTNodeImporter::VisitSwitchStmt(SwitchStmt *S) { auto ToInit = importChecked(Err, S->getInit()); auto ToConditionVariable = importChecked(Err, S->getConditionVariable()); auto ToCond = importChecked(Err, S->getCond()); + auto ToLParenLoc = importChecked(Err, S->getLParenLoc()); + auto ToRParenLoc = importChecked(Err, S->getRParenLoc()); auto ToBody = importChecked(Err, S->getBody()); auto ToSwitchLoc = importChecked(Err, S->getSwitchLoc()); if (Err) return std::move(Err); - auto *ToStmt = SwitchStmt::Create(Importer.getToContext(), ToInit, - ToConditionVariable, ToCond); + auto *ToStmt = + SwitchStmt::Create(Importer.getToContext(), ToInit, ToConditionVariable, + ToCond, ToLParenLoc, ToRParenLoc); ToStmt->setBody(ToBody); ToStmt->setSwitchLoc(ToSwitchLoc); @@ -6437,6 +6528,40 @@ ExpectedStmt ASTNodeImporter::VisitGNUNullExpr(GNUNullExpr *E) { return new (Importer.getToContext()) GNUNullExpr(*TypeOrErr, *BeginLocOrErr); } +ExpectedStmt +ASTNodeImporter::VisitGenericSelectionExpr(GenericSelectionExpr *E) { + Error Err = Error::success(); + auto ToGenericLoc = importChecked(Err, E->getGenericLoc()); + auto *ToControllingExpr = importChecked(Err, E->getControllingExpr()); + auto ToDefaultLoc = importChecked(Err, E->getDefaultLoc()); + auto ToRParenLoc = importChecked(Err, E->getRParenLoc()); + if (Err) + return std::move(Err); + + ArrayRef FromAssocTypes(E->getAssocTypeSourceInfos()); + SmallVector ToAssocTypes(FromAssocTypes.size()); + if (Error Err = ImportContainerChecked(FromAssocTypes, ToAssocTypes)) + return std::move(Err); + + ArrayRef FromAssocExprs(E->getAssocExprs()); + SmallVector ToAssocExprs(FromAssocExprs.size()); + if (Error Err = ImportContainerChecked(FromAssocExprs, ToAssocExprs)) + return std::move(Err); + + const ASTContext &ToCtx = Importer.getToContext(); + if (E->isResultDependent()) { + return GenericSelectionExpr::Create( + ToCtx, ToGenericLoc, ToControllingExpr, + llvm::makeArrayRef(ToAssocTypes), llvm::makeArrayRef(ToAssocExprs), + ToDefaultLoc, ToRParenLoc, E->containsUnexpandedParameterPack()); + } + + return GenericSelectionExpr::Create( + ToCtx, ToGenericLoc, ToControllingExpr, llvm::makeArrayRef(ToAssocTypes), + llvm::makeArrayRef(ToAssocExprs), ToDefaultLoc, ToRParenLoc, + E->containsUnexpandedParameterPack(), E->getResultIndex()); +} + ExpectedStmt ASTNodeImporter::VisitPredefinedExpr(PredefinedExpr *E) { Error Err = Error::success(); @@ -6671,18 +6796,11 @@ ExpectedStmt ASTNodeImporter::VisitAddrLabelExpr(AddrLabelExpr *E) { ExpectedStmt ASTNodeImporter::VisitConstantExpr(ConstantExpr *E) { Error Err = Error::success(); auto ToSubExpr = importChecked(Err, E->getSubExpr()); + auto ToResult = importChecked(Err, E->getAPValueResult()); if (Err) return std::move(Err); - // TODO : Handle APValue::ValueKind that require importing. - - APValue::ValueKind Kind = E->getResultAPValueKind(); - if (Kind == APValue::Int || Kind == APValue::Float || - Kind == APValue::FixedPoint || Kind == APValue::ComplexFloat || - Kind == APValue::ComplexInt) - return ConstantExpr::Create(Importer.getToContext(), ToSubExpr, - E->getAPValueResult()); - return ConstantExpr::Create(Importer.getToContext(), ToSubExpr); + return ConstantExpr::Create(Importer.getToContext(), ToSubExpr, ToResult); } ExpectedStmt ASTNodeImporter::VisitParenExpr(ParenExpr *E) { Error Err = Error::success(); @@ -6924,7 +7042,7 @@ ExpectedStmt ASTNodeImporter::VisitImplicitCastExpr(ImplicitCastExpr *E) { return ImplicitCastExpr::Create( Importer.getToContext(), *ToTypeOrErr, E->getCastKind(), *ToSubExprOrErr, - &(*ToBasePathOrErr), E->getValueKind()); + &(*ToBasePathOrErr), E->getValueKind(), E->getFPFeatures()); } ExpectedStmt ASTNodeImporter::VisitExplicitCastExpr(ExplicitCastExpr *E) { @@ -6951,8 +7069,8 @@ ExpectedStmt ASTNodeImporter::VisitExplicitCastExpr(ExplicitCastExpr *E) { return ToRParenLocOrErr.takeError(); return CStyleCastExpr::Create( Importer.getToContext(), ToType, E->getValueKind(), E->getCastKind(), - ToSubExpr, ToBasePath, ToTypeInfoAsWritten, *ToLParenLocOrErr, - *ToRParenLocOrErr); + ToSubExpr, ToBasePath, CCE->getFPFeatures(), ToTypeInfoAsWritten, + *ToLParenLocOrErr, *ToRParenLocOrErr); } case Stmt::CXXFunctionalCastExprClass: { @@ -6965,8 +7083,8 @@ ExpectedStmt ASTNodeImporter::VisitExplicitCastExpr(ExplicitCastExpr *E) { return ToRParenLocOrErr.takeError(); return CXXFunctionalCastExpr::Create( Importer.getToContext(), ToType, E->getValueKind(), ToTypeInfoAsWritten, - E->getCastKind(), ToSubExpr, ToBasePath, *ToLParenLocOrErr, - *ToRParenLocOrErr); + E->getCastKind(), ToSubExpr, ToBasePath, FCE->getFPFeatures(), + *ToLParenLocOrErr, *ToRParenLocOrErr); } case Stmt::ObjCBridgedCastExprClass: { @@ -7338,7 +7456,8 @@ ExpectedStmt ASTNodeImporter::VisitCXXMemberCallExpr(CXXMemberCallExpr *E) { return std::move(Err); return CXXMemberCallExpr::Create(Importer.getToContext(), ToCallee, ToArgs, - ToType, E->getValueKind(), ToRParenLoc); + ToType, E->getValueKind(), ToRParenLoc, + E->getFPFeatures()); } ExpectedStmt ASTNodeImporter::VisitCXXThisExpr(CXXThisExpr *E) { @@ -7514,17 +7633,18 @@ ExpectedStmt ASTNodeImporter::VisitCXXUnresolvedConstructExpr( Error Err = Error::success(); auto ToLParenLoc = importChecked(Err, E->getLParenLoc()); auto ToRParenLoc = importChecked(Err, E->getRParenLoc()); + auto ToType = importChecked(Err, E->getType()); auto ToTypeSourceInfo = importChecked(Err, E->getTypeSourceInfo()); if (Err) return std::move(Err); - SmallVector ToArgs(E->arg_size()); + SmallVector ToArgs(E->getNumArgs()); if (Error Err = ImportArrayChecked(E->arg_begin(), E->arg_end(), ToArgs.begin())) return std::move(Err); return CXXUnresolvedConstructExpr::Create( - Importer.getToContext(), ToTypeSourceInfo, ToLParenLoc, + Importer.getToContext(), ToType, ToTypeSourceInfo, ToLParenLoc, llvm::makeArrayRef(ToArgs), ToRParenLoc); } @@ -7648,8 +7768,8 @@ ExpectedStmt ASTNodeImporter::VisitCallExpr(CallExpr *E) { } return CallExpr::Create(Importer.getToContext(), ToCallee, ToArgs, ToType, - E->getValueKind(), ToRParenLoc, /*MinNumArgs=*/0, - E->getADLCallKind()); + E->getValueKind(), ToRParenLoc, E->getFPFeatures(), + /*MinNumArgs=*/0, E->getADLCallKind()); } ExpectedStmt ASTNodeImporter::VisitLambdaExpr(LambdaExpr *E) { @@ -7808,10 +7928,11 @@ ExpectedStmt ASTNodeImporter::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) { if (!ToBasePathOrErr) return ToBasePathOrErr.takeError(); - if (isa(E)) { + if (auto CCE = dyn_cast(E)) { return CXXStaticCastExpr::Create( Importer.getToContext(), ToType, VK, CK, ToSubExpr, &(*ToBasePathOrErr), - ToTypeInfoAsWritten, ToOperatorLoc, ToRParenLoc, ToAngleBrackets); + ToTypeInfoAsWritten, CCE->getFPFeatures(), ToOperatorLoc, ToRParenLoc, + ToAngleBrackets); } else if (isa(E)) { return CXXDynamicCastExpr::Create( Importer.getToContext(), ToType, VK, CK, ToSubExpr, &(*ToBasePathOrErr), @@ -7841,7 +7962,8 @@ ExpectedStmt ASTNodeImporter::VisitSubstNonTypeTemplateParmExpr( return std::move(Err); return new (Importer.getToContext()) SubstNonTypeTemplateParmExpr( - ToType, E->getValueKind(), ToExprLoc, ToParameter, ToReplacement); + ToType, E->getValueKind(), ToExprLoc, ToParameter, + E->isReferenceParameter(), ToReplacement); } ExpectedStmt ASTNodeImporter::VisitTypeTraitExpr(TypeTraitExpr *E) { @@ -7890,6 +8012,25 @@ ExpectedStmt ASTNodeImporter::VisitCXXTypeidExpr(CXXTypeidExpr *E) { *ToTypeOrErr, *ToExprOperandOrErr, *ToSourceRangeOrErr); } +ExpectedStmt ASTNodeImporter::VisitCXXFoldExpr(CXXFoldExpr *E) { + Error Err = Error::success(); + + QualType ToType = importChecked(Err, E->getType()); + UnresolvedLookupExpr *ToCallee = importChecked(Err, E->getCallee()); + SourceLocation ToLParenLoc = importChecked(Err, E->getLParenLoc()); + Expr *ToLHS = importChecked(Err, E->getLHS()); + SourceLocation ToEllipsisLoc = importChecked(Err, E->getEllipsisLoc()); + Expr *ToRHS = importChecked(Err, E->getRHS()); + SourceLocation ToRParenLoc = importChecked(Err, E->getRParenLoc()); + + if (Err) + return std::move(Err); + + return new (Importer.getToContext()) + CXXFoldExpr(ToType, ToCallee, ToLParenLoc, ToLHS, E->getOperator(), + ToEllipsisLoc, ToRHS, ToRParenLoc, E->getNumExpansions()); +} + Error ASTNodeImporter::ImportOverriddenMethods(CXXMethodDecl *ToMethod, CXXMethodDecl *FromMethod) { Error ImportErrors = Error::success(); @@ -8077,6 +8218,16 @@ Expected ASTImporter::Import(const Attr *FromAttr) { ToAttr = To; break; } + case attr::Format: { + const auto *From = cast(FromAttr); + FormatAttr *To; + IdentifierInfo *ToAttrType = Import(From->getType()); + To = FormatAttr::Create(ToContext, ToAttrType, From->getFormatIdx(), + From->getFirstArg(), ToRange, From->getSyntax()); + To->setInherited(From->isInherited()); + ToAttr = To; + break; + } default: // FIXME: 'clone' copies every member but some of them should be imported. // Handle other Attrs that have parameters that should be imported. @@ -8127,7 +8278,7 @@ Expected ASTImporter::Import(Decl *FromD) { return make_error(*Error); } - // If FromD has some updated flags after last import, apply it + // If FromD has some updated flags after last import, apply it. updateFlags(FromD, ToD); // If we encounter a cycle during an import then we save the relevant part // of the import path associated to the Decl. @@ -8222,6 +8373,15 @@ Expected ASTImporter::Import(Decl *FromD) { // Make sure that ImportImpl registered the imported decl. assert(ImportedDecls.count(FromD) != 0 && "Missing call to MapImported?"); + if (FromD->hasAttrs()) + for (const Attr *FromAttr : FromD->getAttrs()) { + auto ToAttrOrErr = Import(FromAttr); + if (ToAttrOrErr) + ToD->addAttr(*ToAttrOrErr); + else + return ToAttrOrErr.takeError(); + } + // Notify subclasses. Imported(FromD, ToD); @@ -8625,7 +8785,7 @@ Expected ASTImporter::Import(FileID FromID, bool IsBuiltin) { } ToID = ToSM.getFileID(MLoc); } else { - const SrcMgr::ContentCache *Cache = FromSLoc.getFile().getContentCache(); + const SrcMgr::ContentCache *Cache = &FromSLoc.getFile().getContentCache(); if (!IsBuiltin && !Cache->BufferOverridden) { // Include location of this file. @@ -8648,7 +8808,7 @@ Expected ASTImporter::Import(FileID FromID, bool IsBuiltin) { // FIXME: We definitely want to re-use the existing MemoryBuffer, rather // than mmap the files several times. auto Entry = - ToFileManager.getFile(Cache->OrigEntry->getName()); + ToFileManager.getOptionalFileRef(Cache->OrigEntry->getName()); // FIXME: The filename may be a virtual name that does probably not // point to a valid file and we get no Entry here. In this case try with // the memory buffer below. @@ -8660,12 +8820,10 @@ Expected ASTImporter::Import(FileID FromID, bool IsBuiltin) { if (ToID.isInvalid() || IsBuiltin) { // FIXME: We want to re-use the existing MemoryBuffer! - bool Invalid = true; - const llvm::MemoryBuffer *FromBuf = - Cache->getBuffer(FromContext.getDiagnostics(), - FromSM.getFileManager(), SourceLocation{}, &Invalid); - if (!FromBuf || Invalid) - // FIXME: Use a new error kind? + llvm::Optional FromBuf = + Cache->getBufferOrNone(FromContext.getDiagnostics(), + FromSM.getFileManager(), SourceLocation{}); + if (!FromBuf) return llvm::make_error(ImportError::Unknown); std::unique_ptr ToBuf = @@ -8772,6 +8930,11 @@ ASTImporter::Import(const CXXBaseSpecifier *BaseSpec) { return Imported; } +llvm::Expected ASTImporter::Import(const APValue &FromValue) { + ASTNodeImporter Importer(*this); + return Importer.ImportAPValue(FromValue); +} + Error ASTImporter::ImportDefinition(Decl *From) { ExpectedDecl ToOrErr = Import(From); if (!ToOrErr) @@ -8902,6 +9065,169 @@ Expected ASTImporter::Import(Selector FromSel) { return ToContext.Selectors.getSelector(FromSel.getNumArgs(), Idents.data()); } +llvm::Expected +ASTNodeImporter::ImportAPValue(const APValue &FromValue) { + APValue Result; + llvm::Error Err = llvm::Error::success(); + auto ImportLoop = [&](const APValue *From, APValue *To, unsigned Size) { + for (unsigned Idx = 0; Idx < Size; Idx++) { + APValue Tmp = importChecked(Err, From[Idx]); + To[Idx] = Tmp; + } + }; + switch (FromValue.getKind()) { + case APValue::None: + case APValue::Indeterminate: + case APValue::Int: + case APValue::Float: + case APValue::FixedPoint: + case APValue::ComplexInt: + case APValue::ComplexFloat: + Result = FromValue; + break; + case APValue::Vector: { + Result.MakeVector(); + MutableArrayRef Elts = + Result.setVectorUninit(FromValue.getVectorLength()); + ImportLoop(((const APValue::Vec *)(const char *)&FromValue.Data)->Elts, + Elts.data(), FromValue.getVectorLength()); + break; + } + case APValue::Array: + Result.MakeArray(FromValue.getArrayInitializedElts(), + FromValue.getArraySize()); + ImportLoop(((const APValue::Arr *)(const char *)&FromValue.Data)->Elts, + ((const APValue::Arr *)(const char *)&Result.Data)->Elts, + FromValue.getArrayInitializedElts()); + break; + case APValue::Struct: + Result.MakeStruct(FromValue.getStructNumBases(), + FromValue.getStructNumFields()); + ImportLoop( + ((const APValue::StructData *)(const char *)&FromValue.Data)->Elts, + ((const APValue::StructData *)(const char *)&Result.Data)->Elts, + FromValue.getStructNumBases() + FromValue.getStructNumFields()); + break; + case APValue::Union: { + Result.MakeUnion(); + const Decl *ImpFDecl = importChecked(Err, FromValue.getUnionField()); + APValue ImpValue = importChecked(Err, FromValue.getUnionValue()); + if (Err) + return std::move(Err); + Result.setUnion(cast(ImpFDecl), ImpValue); + break; + } + case APValue::AddrLabelDiff: { + Result.MakeAddrLabelDiff(); + const Expr *ImpLHS = importChecked(Err, FromValue.getAddrLabelDiffLHS()); + const Expr *ImpRHS = importChecked(Err, FromValue.getAddrLabelDiffRHS()); + if (Err) + return std::move(Err); + Result.setAddrLabelDiff(cast(ImpLHS), + cast(ImpRHS)); + break; + } + case APValue::MemberPointer: { + const Decl *ImpMemPtrDecl = + importChecked(Err, FromValue.getMemberPointerDecl()); + if (Err) + return std::move(Err); + MutableArrayRef ToPath = + Result.setMemberPointerUninit( + cast(ImpMemPtrDecl), + FromValue.isMemberPointerToDerivedMember(), + FromValue.getMemberPointerPath().size()); + llvm::ArrayRef FromPath = + Result.getMemberPointerPath(); + for (unsigned Idx = 0; Idx < FromValue.getMemberPointerPath().size(); + Idx++) { + const Decl *ImpDecl = importChecked(Err, FromPath[Idx]); + if (Err) + return std::move(Err); + ToPath[Idx] = cast(ImpDecl->getCanonicalDecl()); + } + break; + } + case APValue::LValue: + APValue::LValueBase Base; + QualType FromElemTy; + if (FromValue.getLValueBase()) { + assert(!FromValue.getLValueBase().is() && + "in C++20 dynamic allocation are transient so they shouldn't " + "appear in the AST"); + if (!FromValue.getLValueBase().is()) { + if (const auto *E = + FromValue.getLValueBase().dyn_cast()) { + FromElemTy = E->getType(); + const Expr *ImpExpr = importChecked(Err, E); + if (Err) + return std::move(Err); + Base = APValue::LValueBase(ImpExpr, + FromValue.getLValueBase().getCallIndex(), + FromValue.getLValueBase().getVersion()); + } else { + FromElemTy = + FromValue.getLValueBase().get()->getType(); + const Decl *ImpDecl = importChecked( + Err, FromValue.getLValueBase().get()); + if (Err) + return std::move(Err); + Base = APValue::LValueBase(cast(ImpDecl), + FromValue.getLValueBase().getCallIndex(), + FromValue.getLValueBase().getVersion()); + } + } else { + FromElemTy = FromValue.getLValueBase().getTypeInfoType(); + QualType ImpTypeInfo = importChecked( + Err, + QualType(FromValue.getLValueBase().get().getType(), + 0)); + QualType ImpType = + importChecked(Err, FromValue.getLValueBase().getTypeInfoType()); + if (Err) + return std::move(Err); + Base = APValue::LValueBase::getTypeInfo( + TypeInfoLValue(ImpTypeInfo.getTypePtr()), ImpType); + } + } + CharUnits Offset = FromValue.getLValueOffset(); + unsigned PathLength = FromValue.getLValuePath().size(); + Result.MakeLValue(); + if (FromValue.hasLValuePath()) { + MutableArrayRef ToPath = Result.setLValueUninit( + Base, Offset, PathLength, FromValue.isLValueOnePastTheEnd(), + FromValue.isNullPointer()); + llvm::ArrayRef FromPath = + FromValue.getLValuePath(); + for (unsigned LoopIdx = 0; LoopIdx < PathLength; LoopIdx++) { + if (FromElemTy->isRecordType()) { + const Decl *FromDecl = + FromPath[LoopIdx].getAsBaseOrMember().getPointer(); + const Decl *ImpDecl = importChecked(Err, FromDecl); + if (Err) + return std::move(Err); + if (auto *RD = dyn_cast(FromDecl)) + FromElemTy = Importer.FromContext.getRecordType(RD); + else + FromElemTy = cast(FromDecl)->getType(); + ToPath[LoopIdx] = APValue::LValuePathEntry(APValue::BaseOrMemberType( + ImpDecl, FromPath[LoopIdx].getAsBaseOrMember().getInt())); + } else { + FromElemTy = + Importer.FromContext.getAsArrayType(FromElemTy)->getElementType(); + ToPath[LoopIdx] = APValue::LValuePathEntry::ArrayIndex( + FromPath[LoopIdx].getAsArrayIndex()); + } + } + } else + Result.setLValue(Base, Offset, APValue::NoLValuePath{}, + FromValue.isNullPointer()); + } + if (Err) + return std::move(Err); + return Result; +} + Expected ASTImporter::HandleNameConflict(DeclarationName Name, DeclContext *DC, unsigned IDNS, @@ -8961,7 +9287,11 @@ Decl *ASTImporter::MapImported(Decl *From, Decl *To) { // This mapping should be maintained only in this function. Therefore do not // check for additional consistency. ImportedFromDecls[To] = From; - AddToLookupTable(To); + // In the case of TypedefNameDecl we create the Decl first and only then we + // import and set its DeclContext. So, the DC is still not set when we reach + // here from GetImportedOrCreateDecl. + if (To->getDeclContext()) + AddToLookupTable(To); return To; } diff --git a/clang/lib/AST/ASTImporterLookupTable.cpp b/clang/lib/AST/ASTImporterLookupTable.cpp index 4d6fff8f3419..e17d6082dcdc 100644 --- a/clang/lib/AST/ASTImporterLookupTable.cpp +++ b/clang/lib/AST/ASTImporterLookupTable.cpp @@ -22,6 +22,20 @@ namespace { struct Builder : RecursiveASTVisitor { ASTImporterLookupTable < Builder(ASTImporterLookupTable <) : LT(LT) {} + + bool VisitTypedefNameDecl(TypedefNameDecl *D) { + QualType Ty = D->getUnderlyingType(); + Ty = Ty.getCanonicalType(); + if (const auto *RTy = dyn_cast(Ty)) { + LT.add(RTy->getAsRecordDecl()); + // iterate over the field decls, adding them + for (auto *it : RTy->getAsRecordDecl()->fields()) { + LT.add(it); + } + } + return true; + } + bool VisitNamedDecl(NamedDecl *D) { LT.add(D); return true; diff --git a/clang/lib/AST/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp index 8b5b2444f1e2..d004e443ae06 100644 --- a/clang/lib/AST/ASTStructuralEquivalence.cpp +++ b/clang/lib/AST/ASTStructuralEquivalence.cpp @@ -66,9 +66,15 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclFriend.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclOpenMP.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/ExprCXX.h" +#include "clang/AST/ExprConcepts.h" +#include "clang/AST/ExprObjC.h" +#include "clang/AST/ExprOpenMP.h" #include "clang/AST/NestedNameSpecifier.h" +#include "clang/AST/StmtObjC.h" +#include "clang/AST/StmtOpenMP.h" #include "clang/AST/TemplateBase.h" #include "clang/AST/TemplateName.h" #include "clang/AST/Type.h" @@ -149,32 +155,253 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, return true; } -/// Determine structural equivalence of two expressions. -static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, - const Expr *E1, const Expr *E2) { - if (!E1 || !E2) - return E1 == E2; +namespace { +/// Encapsulates Stmt comparison logic. +class StmtComparer { + StructuralEquivalenceContext &Context; + + // IsStmtEquivalent overloads. Each overload compares a specific statement + // and only has to compare the data that is specific to the specific statement + // class. Should only be called from TraverseStmt. + + bool IsStmtEquivalent(const AddrLabelExpr *E1, const AddrLabelExpr *E2) { + return IsStructurallyEquivalent(Context, E1->getLabel(), E2->getLabel()); + } + + bool IsStmtEquivalent(const AtomicExpr *E1, const AtomicExpr *E2) { + return E1->getOp() == E2->getOp(); + } - if (auto *DE1 = dyn_cast(E1)) { - auto *DE2 = dyn_cast(E2); - if (!DE2) + bool IsStmtEquivalent(const BinaryOperator *E1, const BinaryOperator *E2) { + return E1->getOpcode() == E2->getOpcode(); + } + + bool IsStmtEquivalent(const CallExpr *E1, const CallExpr *E2) { + // FIXME: IsStructurallyEquivalent requires non-const Decls. + Decl *Callee1 = const_cast(E1->getCalleeDecl()); + Decl *Callee2 = const_cast(E2->getCalleeDecl()); + + // Compare whether both calls know their callee. + if (static_cast(Callee1) != static_cast(Callee2)) return false; + + // Both calls have no callee, so nothing to do. + if (!static_cast(Callee1)) + return true; + + assert(Callee2); + return IsStructurallyEquivalent(Context, Callee1, Callee2); + } + + bool IsStmtEquivalent(const CharacterLiteral *E1, + const CharacterLiteral *E2) { + return E1->getValue() == E2->getValue() && E1->getKind() == E2->getKind(); + } + + bool IsStmtEquivalent(const ChooseExpr *E1, const ChooseExpr *E2) { + return true; // Semantics only depend on children. + } + + bool IsStmtEquivalent(const CompoundStmt *E1, const CompoundStmt *E2) { + // Number of children is actually checked by the generic children comparison + // code, but a CompoundStmt is one of the few statements where the number of + // children frequently differs and the number of statements is also always + // precomputed. Directly comparing the number of children here is thus + // just an optimization. + return E1->size() == E2->size(); + } + + bool IsStmtEquivalent(const DependentScopeDeclRefExpr *DE1, + const DependentScopeDeclRefExpr *DE2) { if (!IsStructurallyEquivalent(Context, DE1->getDeclName(), DE2->getDeclName())) return false; return IsStructurallyEquivalent(Context, DE1->getQualifier(), DE2->getQualifier()); - } else if (auto CastE1 = dyn_cast(E1)) { - auto *CastE2 = dyn_cast(E2); - if (!CastE2) + } + + bool IsStmtEquivalent(const Expr *E1, const Expr *E2) { + return IsStructurallyEquivalent(Context, E1->getType(), E2->getType()); + } + + bool IsStmtEquivalent(const ExpressionTraitExpr *E1, + const ExpressionTraitExpr *E2) { + return E1->getTrait() == E2->getTrait() && E1->getValue() == E2->getValue(); + } + + bool IsStmtEquivalent(const FloatingLiteral *E1, const FloatingLiteral *E2) { + return E1->isExact() == E2->isExact() && E1->getValue() == E2->getValue(); + } + + bool IsStmtEquivalent(const GenericSelectionExpr *E1, + const GenericSelectionExpr *E2) { + for (auto Pair : zip_longest(E1->getAssocTypeSourceInfos(), + E2->getAssocTypeSourceInfos())) { + Optional Child1 = std::get<0>(Pair); + Optional Child2 = std::get<1>(Pair); + // Skip this case if there are a different number of associated types. + if (!Child1 || !Child2) + return false; + + if (!IsStructurallyEquivalent(Context, (*Child1)->getType(), + (*Child2)->getType())) + return false; + } + + return true; + } + + bool IsStmtEquivalent(const ImplicitCastExpr *CastE1, + const ImplicitCastExpr *CastE2) { + return IsStructurallyEquivalent(Context, CastE1->getType(), + CastE2->getType()); + } + + bool IsStmtEquivalent(const IntegerLiteral *E1, const IntegerLiteral *E2) { + return E1->getValue() == E2->getValue(); + } + + bool IsStmtEquivalent(const MemberExpr *E1, const MemberExpr *E2) { + return IsStructurallyEquivalent(Context, E1->getFoundDecl(), + E2->getFoundDecl()); + } + + bool IsStmtEquivalent(const ObjCStringLiteral *E1, + const ObjCStringLiteral *E2) { + // Just wraps a StringLiteral child. + return true; + } + + bool IsStmtEquivalent(const Stmt *S1, const Stmt *S2) { return true; } + + bool IsStmtEquivalent(const SourceLocExpr *E1, const SourceLocExpr *E2) { + return E1->getIdentKind() == E2->getIdentKind(); + } + + bool IsStmtEquivalent(const StmtExpr *E1, const StmtExpr *E2) { + return E1->getTemplateDepth() == E2->getTemplateDepth(); + } + + bool IsStmtEquivalent(const StringLiteral *E1, const StringLiteral *E2) { + return E1->getBytes() == E2->getBytes(); + } + + bool IsStmtEquivalent(const SubstNonTypeTemplateParmExpr *E1, + const SubstNonTypeTemplateParmExpr *E2) { + return IsStructurallyEquivalent(Context, E1->getParameter(), + E2->getParameter()); + } + + bool IsStmtEquivalent(const SubstNonTypeTemplateParmPackExpr *E1, + const SubstNonTypeTemplateParmPackExpr *E2) { + return IsStructurallyEquivalent(Context, E1->getArgumentPack(), + E2->getArgumentPack()); + } + + bool IsStmtEquivalent(const TypeTraitExpr *E1, const TypeTraitExpr *E2) { + if (E1->getTrait() != E2->getTrait()) + return false; + + for (auto Pair : zip_longest(E1->getArgs(), E2->getArgs())) { + Optional Child1 = std::get<0>(Pair); + Optional Child2 = std::get<1>(Pair); + // Different number of args. + if (!Child1 || !Child2) + return false; + + if (!IsStructurallyEquivalent(Context, (*Child1)->getType(), + (*Child2)->getType())) + return false; + } + return true; + } + + bool IsStmtEquivalent(const UnaryExprOrTypeTraitExpr *E1, + const UnaryExprOrTypeTraitExpr *E2) { + if (E1->getKind() != E2->getKind()) return false; - if (!IsStructurallyEquivalent(Context, CastE1->getType(), - CastE2->getType())) + return IsStructurallyEquivalent(Context, E1->getTypeOfArgument(), + E2->getTypeOfArgument()); + } + + bool IsStmtEquivalent(const UnaryOperator *E1, const UnaryOperator *E2) { + return E1->getOpcode() == E2->getOpcode(); + } + + bool IsStmtEquivalent(const VAArgExpr *E1, const VAArgExpr *E2) { + // Semantics only depend on children. + return true; + } + + /// End point of the traversal chain. + bool TraverseStmt(const Stmt *S1, const Stmt *S2) { return true; } + + // Create traversal methods that traverse the class hierarchy and return + // the accumulated result of the comparison. Each TraverseStmt overload + // calls the TraverseStmt overload of the parent class. For example, + // the TraverseStmt overload for 'BinaryOperator' calls the TraverseStmt + // overload of 'Expr' which then calls the overload for 'Stmt'. +#define STMT(CLASS, PARENT) \ + bool TraverseStmt(const CLASS *S1, const CLASS *S2) { \ + if (!TraverseStmt(static_cast(S1), \ + static_cast(S2))) \ + return false; \ + return IsStmtEquivalent(S1, S2); \ + } +#include "clang/AST/StmtNodes.inc" + +public: + StmtComparer(StructuralEquivalenceContext &C) : Context(C) {} + + /// Determine whether two statements are equivalent. The statements have to + /// be of the same kind. The children of the statements and their properties + /// are not compared by this function. + bool IsEquivalent(const Stmt *S1, const Stmt *S2) { + if (S1->getStmtClass() != S2->getStmtClass()) + return false; + + // Each TraverseStmt walks the class hierarchy from the leaf class to + // the root class 'Stmt' (e.g. 'BinaryOperator' -> 'Expr' -> 'Stmt'). Cast + // the Stmt we have here to its specific subclass so that we call the + // overload that walks the whole class hierarchy from leaf to root (e.g., + // cast to 'BinaryOperator' so that 'Expr' and 'Stmt' is traversed). + switch (S1->getStmtClass()) { + case Stmt::NoStmtClass: + llvm_unreachable("Can't traverse NoStmtClass"); +#define STMT(CLASS, PARENT) \ + case Stmt::StmtClass::CLASS##Class: \ + return TraverseStmt(static_cast(S1), \ + static_cast(S2)); +#define ABSTRACT_STMT(S) +#include "clang/AST/StmtNodes.inc" + } + llvm_unreachable("Invalid statement kind"); + } +}; +} // namespace + +/// Determine structural equivalence of two statements. +static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, + const Stmt *S1, const Stmt *S2) { + if (!S1 || !S2) + return S1 == S2; + + // Compare the statements itself. + StmtComparer Comparer(Context); + if (!Comparer.IsEquivalent(S1, S2)) + return false; + + // Iterate over the children of both statements and also compare them. + for (auto Pair : zip_longest(S1->children(), S2->children())) { + Optional Child1 = std::get<0>(Pair); + Optional Child2 = std::get<1>(Pair); + // One of the statements has a different amount of children than the other, + // so the statements can't be equivalent. + if (!Child1 || !Child2) + return false; + if (!IsStructurallyEquivalent(Context, *Child1, *Child2)) return false; - return IsStructurallyEquivalent(Context, CastE1->getSubExpr(), - CastE2->getSubExpr()); } - // FIXME: Handle other kind of expressions! return true; } @@ -1047,48 +1274,9 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, return false; } - if (Field1->isBitField() != Field2->isBitField()) { - if (Context.Complain) { - Context.Diag2( - Owner2->getLocation(), - Context.getApplicableDiagnostic(diag::err_odr_tag_type_inconsistent)) - << Context.ToCtx.getTypeDeclType(Owner2); - if (Field1->isBitField()) { - Context.Diag1(Field1->getLocation(), diag::note_odr_bit_field) - << Field1->getDeclName() << Field1->getType() - << Field1->getBitWidthValue(Context.FromCtx); - Context.Diag2(Field2->getLocation(), diag::note_odr_not_bit_field) - << Field2->getDeclName(); - } else { - Context.Diag2(Field2->getLocation(), diag::note_odr_bit_field) - << Field2->getDeclName() << Field2->getType() - << Field2->getBitWidthValue(Context.ToCtx); - Context.Diag1(Field1->getLocation(), diag::note_odr_not_bit_field) - << Field1->getDeclName(); - } - } - return false; - } - - if (Field1->isBitField()) { - // Make sure that the bit-fields are the same length. - unsigned Bits1 = Field1->getBitWidthValue(Context.FromCtx); - unsigned Bits2 = Field2->getBitWidthValue(Context.ToCtx); - - if (Bits1 != Bits2) { - if (Context.Complain) { - Context.Diag2(Owner2->getLocation(), - Context.getApplicableDiagnostic( - diag::err_odr_tag_type_inconsistent)) - << Context.ToCtx.getTypeDeclType(Owner2); - Context.Diag2(Field2->getLocation(), diag::note_odr_bit_field) - << Field2->getDeclName() << Field2->getType() << Bits2; - Context.Diag1(Field1->getLocation(), diag::note_odr_bit_field) - << Field1->getDeclName() << Field1->getType() << Bits1; - } - return false; - } - } + if (Field1->isBitField()) + return IsStructurallyEquivalent(Context, Field1->getBitWidth(), + Field2->getBitWidth()); return true; } @@ -1161,6 +1349,17 @@ IsStructurallyEquivalentLambdas(StructuralEquivalenceContext &Context, /// Determine structural equivalence of two records. static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, RecordDecl *D1, RecordDecl *D2) { + + // Check for equivalent structure names. + IdentifierInfo *Name1 = D1->getIdentifier(); + if (!Name1 && D1->getTypedefNameForAnonDecl()) + Name1 = D1->getTypedefNameForAnonDecl()->getIdentifier(); + IdentifierInfo *Name2 = D2->getIdentifier(); + if (!Name2 && D2->getTypedefNameForAnonDecl()) + Name2 = D2->getTypedefNameForAnonDecl()->getIdentifier(); + if (!IsStructurallyEquivalent(Name1, Name2)) + return false; + if (D1->isUnion() != D2->isUnion()) { if (Context.Complain) { Context.Diag2(D2->getLocation(), Context.getApplicableDiagnostic( @@ -1395,6 +1594,16 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, EnumDecl *D1, EnumDecl *D2) { + // Check for equivalent enum names. + IdentifierInfo *Name1 = D1->getIdentifier(); + if (!Name1 && D1->getTypedefNameForAnonDecl()) + Name1 = D1->getTypedefNameForAnonDecl()->getIdentifier(); + IdentifierInfo *Name2 = D2->getIdentifier(); + if (!Name2 && D2->getTypedefNameForAnonDecl()) + Name2 = D2->getTypedefNameForAnonDecl()->getIdentifier(); + if (!IsStructurallyEquivalent(Name1, Name2)) + return false; + // Compare the definitions of these two enums. If either or both are // incomplete (i.e. forward declared), we assume that they are equivalent. D1 = D1->getDefinition(); @@ -1620,8 +1829,27 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, return false; } +static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, + TypedefNameDecl *D1, TypedefNameDecl *D2) { + if (!IsStructurallyEquivalent(D1->getIdentifier(), D2->getIdentifier())) + return false; + + return IsStructurallyEquivalent(Context, D1->getUnderlyingType(), + D2->getUnderlyingType()); +} + static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, FunctionDecl *D1, FunctionDecl *D2) { + if (!IsStructurallyEquivalent(D1->getIdentifier(), D2->getIdentifier())) + return false; + + if (D1->isOverloadedOperator()) { + if (!D2->isOverloadedOperator()) + return false; + if (D1->getOverloadedOperator() != D2->getOverloadedOperator()) + return false; + } + // FIXME: Consider checking for function attributes as well. if (!IsStructurallyEquivalent(Context, D1->getType(), D2->getType())) return false; @@ -1790,6 +2018,15 @@ bool StructuralEquivalenceContext::IsEquivalent(QualType T1, QualType T2) { return !Finish(); } +bool StructuralEquivalenceContext::IsEquivalent(Stmt *S1, Stmt *S2) { + assert(DeclsToCheck.empty()); + assert(VisitedDecls.empty()); + if (!::IsStructurallyEquivalent(*this, S1, S2)) + return false; + + return !Finish(); +} + bool StructuralEquivalenceContext::CheckCommonEquivalence(Decl *D1, Decl *D2) { // Check for equivalent described template. TemplateDecl *Template1 = D1->getDescribedTemplate(); @@ -1806,136 +2043,21 @@ bool StructuralEquivalenceContext::CheckCommonEquivalence(Decl *D1, Decl *D2) { bool StructuralEquivalenceContext::CheckKindSpecificEquivalence( Decl *D1, Decl *D2) { - // FIXME: Switch on all declaration kinds. For now, we're just going to - // check the obvious ones. - if (auto *Record1 = dyn_cast(D1)) { - if (auto *Record2 = dyn_cast(D2)) { - // Check for equivalent structure names. - IdentifierInfo *Name1 = Record1->getIdentifier(); - if (!Name1 && Record1->getTypedefNameForAnonDecl()) - Name1 = Record1->getTypedefNameForAnonDecl()->getIdentifier(); - IdentifierInfo *Name2 = Record2->getIdentifier(); - if (!Name2 && Record2->getTypedefNameForAnonDecl()) - Name2 = Record2->getTypedefNameForAnonDecl()->getIdentifier(); - if (!::IsStructurallyEquivalent(Name1, Name2) || - !::IsStructurallyEquivalent(*this, Record1, Record2)) - return false; - } else { - // Record/non-record mismatch. - return false; - } - } else if (auto *Enum1 = dyn_cast(D1)) { - if (auto *Enum2 = dyn_cast(D2)) { - // Check for equivalent enum names. - IdentifierInfo *Name1 = Enum1->getIdentifier(); - if (!Name1 && Enum1->getTypedefNameForAnonDecl()) - Name1 = Enum1->getTypedefNameForAnonDecl()->getIdentifier(); - IdentifierInfo *Name2 = Enum2->getIdentifier(); - if (!Name2 && Enum2->getTypedefNameForAnonDecl()) - Name2 = Enum2->getTypedefNameForAnonDecl()->getIdentifier(); - if (!::IsStructurallyEquivalent(Name1, Name2) || - !::IsStructurallyEquivalent(*this, Enum1, Enum2)) - return false; - } else { - // Enum/non-enum mismatch - return false; - } - } else if (const auto *Typedef1 = dyn_cast(D1)) { - if (const auto *Typedef2 = dyn_cast(D2)) { - if (!::IsStructurallyEquivalent(Typedef1->getIdentifier(), - Typedef2->getIdentifier()) || - !::IsStructurallyEquivalent(*this, Typedef1->getUnderlyingType(), - Typedef2->getUnderlyingType())) - return false; - } else { - // Typedef/non-typedef mismatch. - return false; - } - } else if (auto *ClassTemplate1 = dyn_cast(D1)) { - if (auto *ClassTemplate2 = dyn_cast(D2)) { - if (!::IsStructurallyEquivalent(*this, ClassTemplate1, - ClassTemplate2)) - return false; - } else { - // Class template/non-class-template mismatch. - return false; - } - } else if (auto *FunctionTemplate1 = dyn_cast(D1)) { - if (auto *FunctionTemplate2 = dyn_cast(D2)) { - if (!::IsStructurallyEquivalent(*this, FunctionTemplate1, - FunctionTemplate2)) - return false; - } else { - // Class template/non-class-template mismatch. - return false; - } - } else if (auto *ConceptDecl1 = dyn_cast(D1)) { - if (auto *ConceptDecl2 = dyn_cast(D2)) { - if (!::IsStructurallyEquivalent(*this, ConceptDecl1, ConceptDecl2)) - return false; - } else { - // Concept/non-concept mismatch. - return false; - } - } else if (auto *TTP1 = dyn_cast(D1)) { - if (auto *TTP2 = dyn_cast(D2)) { - if (!::IsStructurallyEquivalent(*this, TTP1, TTP2)) - return false; - } else { - // Kind mismatch. - return false; - } - } else if (auto *NTTP1 = dyn_cast(D1)) { - if (auto *NTTP2 = dyn_cast(D2)) { - if (!::IsStructurallyEquivalent(*this, NTTP1, NTTP2)) - return false; - } else { - // Kind mismatch. - return false; - } - } else if (auto *TTP1 = dyn_cast(D1)) { - if (auto *TTP2 = dyn_cast(D2)) { - if (!::IsStructurallyEquivalent(*this, TTP1, TTP2)) - return false; - } else { - // Kind mismatch. - return false; - } - } else if (auto *MD1 = dyn_cast(D1)) { - if (auto *MD2 = dyn_cast(D2)) { - if (!::IsStructurallyEquivalent(*this, MD1, MD2)) - return false; - } else { - // Kind mismatch. - return false; - } - } else if (FunctionDecl *FD1 = dyn_cast(D1)) { - if (FunctionDecl *FD2 = dyn_cast(D2)) { - if (FD1->isOverloadedOperator()) { - if (!FD2->isOverloadedOperator()) - return false; - if (FD1->getOverloadedOperator() != FD2->getOverloadedOperator()) - return false; - } - if (!::IsStructurallyEquivalent(FD1->getIdentifier(), - FD2->getIdentifier())) - return false; - if (!::IsStructurallyEquivalent(*this, FD1, FD2)) - return false; - } else { - // Kind mismatch. - return false; - } - } else if (FriendDecl *FrD1 = dyn_cast(D1)) { - if (FriendDecl *FrD2 = dyn_cast(D2)) { - if (!::IsStructurallyEquivalent(*this, FrD1, FrD2)) - return false; - } else { - // Kind mismatch. - return false; - } - } + // Kind mismatch. + if (D1->getKind() != D2->getKind()) + return false; + + // Cast the Decls to their actual subclass so that the right overload of + // IsStructurallyEquivalent is called. + switch (D1->getKind()) { +#define ABSTRACT_DECL(DECL) +#define DECL(DERIVED, BASE) \ + case Decl::Kind::DERIVED: \ + return ::IsStructurallyEquivalent(*this, static_cast(D1), \ + static_cast(D2)); +#include "clang/AST/DeclNodes.inc" + } return true; } diff --git a/clang/lib/AST/ASTTypeTraits.cpp b/clang/lib/AST/ASTTypeTraits.cpp index 34fc587694be..8f9ceea656a3 100644 --- a/clang/lib/AST/ASTTypeTraits.cpp +++ b/clang/lib/AST/ASTTypeTraits.cpp @@ -21,27 +21,29 @@ using namespace clang; const ASTNodeKind::KindInfo ASTNodeKind::AllKindInfo[] = { - { NKI_None, "" }, - { NKI_None, "TemplateArgument" }, - { NKI_None, "TemplateName" }, - { NKI_None, "NestedNameSpecifierLoc" }, - { NKI_None, "QualType" }, - { NKI_None, "TypeLoc" }, - { NKI_None, "CXXBaseSpecifier" }, - { NKI_None, "CXXCtorInitializer" }, - { NKI_None, "NestedNameSpecifier" }, - { NKI_None, "Decl" }, + {NKI_None, ""}, + {NKI_None, "TemplateArgument"}, + {NKI_None, "TemplateArgumentLoc"}, + {NKI_None, "TemplateName"}, + {NKI_None, "NestedNameSpecifierLoc"}, + {NKI_None, "QualType"}, + {NKI_None, "TypeLoc"}, + {NKI_None, "CXXBaseSpecifier"}, + {NKI_None, "CXXCtorInitializer"}, + {NKI_None, "NestedNameSpecifier"}, + {NKI_None, "Decl"}, #define DECL(DERIVED, BASE) { NKI_##BASE, #DERIVED "Decl" }, #include "clang/AST/DeclNodes.inc" - { NKI_None, "Stmt" }, + {NKI_None, "Stmt"}, #define STMT(DERIVED, BASE) { NKI_##BASE, #DERIVED }, #include "clang/AST/StmtNodes.inc" - { NKI_None, "Type" }, + {NKI_None, "Type"}, #define TYPE(DERIVED, BASE) { NKI_##BASE, #DERIVED "Type" }, #include "clang/AST/TypeNodes.inc" - { NKI_None, "OMPClause" }, -#define OMP_CLAUSE_CLASS(Enum, Str, Class) {NKI_OMPClause, #Class}, -#include "llvm/Frontend/OpenMP/OMPKinds.def" + {NKI_None, "OMPClause"}, +#define GEN_CLANG_CLAUSE_CLASS +#define CLAUSE_CLASS(Enum, Str, Class) {NKI_OMPClause, #Class}, +#include "llvm/Frontend/OpenMP/OMP.inc" }; bool ASTNodeKind::isBaseOf(ASTNodeKind Other, unsigned *Distance) const { @@ -61,6 +63,17 @@ bool ASTNodeKind::isBaseOf(NodeKindId Base, NodeKindId Derived, return Derived == Base; } +ASTNodeKind ASTNodeKind::getCladeKind() const { + NodeKindId LastId = KindId; + while (LastId) { + NodeKindId ParentId = AllKindInfo[LastId].ParentId; + if (ParentId == NKI_None) + return LastId; + LastId = ParentId; + } + return NKI_None; +} + StringRef ASTNodeKind::asStringRef() const { return AllKindInfo[KindId].Name; } ASTNodeKind ASTNodeKind::getMostDerivedType(ASTNodeKind Kind1, @@ -112,15 +125,14 @@ ASTNodeKind ASTNodeKind::getFromNode(const Type &T) { ASTNodeKind ASTNodeKind::getFromNode(const OMPClause &C) { switch (C.getClauseKind()) { -#define OMP_CLAUSE_CLASS(Enum, Str, Class) \ +#define GEN_CLANG_CLAUSE_CLASS +#define CLAUSE_CLASS(Enum, Str, Class) \ case llvm::omp::Clause::Enum: \ return ASTNodeKind(NKI_##Class); -#define OMP_CLAUSE_NO_CLASS(Enum, Str) \ +#define CLAUSE_NO_CLASS(Enum, Str) \ case llvm::omp::Clause::Enum: \ llvm_unreachable("unexpected OpenMP clause kind"); - default: - break; -#include "llvm/Frontend/OpenMP/OMPKinds.def" +#include "llvm/Frontend/OpenMP/OMP.inc" } llvm_unreachable("invalid stmt kind"); } @@ -129,6 +141,8 @@ void DynTypedNode::print(llvm::raw_ostream &OS, const PrintingPolicy &PP) const { if (const TemplateArgument *TA = get()) TA->print(PP, OS); + else if (const TemplateArgumentLoc *TAL = get()) + TAL->getArgument().print(PP, OS); else if (const TemplateName *TN = get()) TN->print(OS, PP); else if (const NestedNameSpecifier *NNS = get()) @@ -175,7 +189,11 @@ SourceRange DynTypedNode::getSourceRange() const { return D->getSourceRange(); if (const Stmt *S = get()) return S->getSourceRange(); + if (const TemplateArgumentLoc *TAL = get()) + return TAL->getSourceRange(); if (const auto *C = get()) return SourceRange(C->getBeginLoc(), C->getEndLoc()); + if (const auto *CBS = get()) + return CBS->getSourceRange(); return SourceRange(); } diff --git a/clang/lib/AST/AttrImpl.cpp b/clang/lib/AST/AttrImpl.cpp index 7818fbb1918b..09fdca67995f 100644 --- a/clang/lib/AST/AttrImpl.cpp +++ b/clang/lib/AST/AttrImpl.cpp @@ -42,7 +42,16 @@ std::string LoopHintAttr::getValueString(const PrintingPolicy &Policy) const { OS << "("; if (state == Numeric) value->printPretty(OS, nullptr, Policy); - else if (state == Enable) + else if (state == FixedWidth || state == ScalableWidth) { + if (value) { + value->printPretty(OS, nullptr, Policy); + if (state == ScalableWidth) + OS << ", scalable"; + } else if (state == ScalableWidth) + OS << "scalable"; + else + OS << "fixed"; + } else if (state == Enable) OS << "enable"; else if (state == Full) OS << "full"; @@ -136,8 +145,16 @@ llvm::Optional OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(const ValueDecl *VD) { if (!VD->hasAttrs()) return llvm::None; - if (const auto *Attr = VD->getAttr()) - return Attr->getMapType(); + unsigned Level = 0; + const OMPDeclareTargetDeclAttr *FoundAttr = nullptr; + for (const auto *Attr : VD->specific_attrs()) { + if (Level < Attr->getLevel()) { + Level = Attr->getLevel(); + FoundAttr = Attr; + } + } + if (FoundAttr) + return FoundAttr->getMapType(); return llvm::None; } @@ -146,8 +163,34 @@ llvm::Optional OMPDeclareTargetDeclAttr::getDeviceType(const ValueDecl *VD) { if (!VD->hasAttrs()) return llvm::None; - if (const auto *Attr = VD->getAttr()) - return Attr->getDevType(); + unsigned Level = 0; + const OMPDeclareTargetDeclAttr *FoundAttr = nullptr; + for (const auto *Attr : VD->specific_attrs()) { + if (Level < Attr->getLevel()) { + Level = Attr->getLevel(); + FoundAttr = Attr; + } + } + if (FoundAttr) + return FoundAttr->getDevType(); + + return llvm::None; +} + +llvm::Optional +OMPDeclareTargetDeclAttr::getLocation(const ValueDecl *VD) { + if (!VD->hasAttrs()) + return llvm::None; + unsigned Level = 0; + const OMPDeclareTargetDeclAttr *FoundAttr = nullptr; + for (const auto *Attr : VD->specific_attrs()) { + if (Level < Attr->getLevel()) { + Level = Attr->getLevel(); + FoundAttr = Attr; + } + } + if (FoundAttr) + return FoundAttr->getRange().getBegin(); return llvm::None; } diff --git a/clang/lib/AST/CXXInheritance.cpp b/clang/lib/AST/CXXInheritance.cpp index 8af97119e3cf..c87bcf31d120 100644 --- a/clang/lib/AST/CXXInheritance.cpp +++ b/clang/lib/AST/CXXInheritance.cpp @@ -33,29 +33,6 @@ using namespace clang; -/// Computes the set of declarations referenced by these base -/// paths. -void CXXBasePaths::ComputeDeclsFound() { - assert(NumDeclsFound == 0 && !DeclsFound && - "Already computed the set of declarations"); - - llvm::SmallSetVector Decls; - for (paths_iterator Path = begin(), PathEnd = end(); Path != PathEnd; ++Path) - Decls.insert(Path->Decls.front()); - - NumDeclsFound = Decls.size(); - DeclsFound = std::make_unique(NumDeclsFound); - std::copy(Decls.begin(), Decls.end(), DeclsFound.get()); -} - -CXXBasePaths::decl_range CXXBasePaths::found_decls() { - if (NumDeclsFound == 0) - ComputeDeclsFound(); - - return decl_range(decl_iterator(DeclsFound.get()), - decl_iterator(DeclsFound.get() + NumDeclsFound)); -} - /// isAmbiguous - Determines whether the set of paths provided is /// ambiguous, i.e., there are two or more paths that refer to /// different base class subobjects of the same type. BaseType must be @@ -402,54 +379,45 @@ bool CXXRecordDecl::FindVirtualBaseClass(const CXXBaseSpecifier *Specifier, ->getCanonicalDecl() == BaseRecord; } -bool CXXRecordDecl::FindTagMember(const CXXBaseSpecifier *Specifier, - CXXBasePath &Path, - DeclarationName Name) { - RecordDecl *BaseRecord = - Specifier->getType()->castAs()->getDecl(); - - for (Path.Decls = BaseRecord->lookup(Name); - !Path.Decls.empty(); - Path.Decls = Path.Decls.slice(1)) { - if (Path.Decls.front()->isInIdentifierNamespace(IDNS_Tag)) - return true; - } - - return false; +static bool isOrdinaryMember(const NamedDecl *ND) { + return ND->isInIdentifierNamespace(Decl::IDNS_Ordinary | Decl::IDNS_Tag | + Decl::IDNS_Member); } -static bool findOrdinaryMember(RecordDecl *BaseRecord, CXXBasePath &Path, +static bool findOrdinaryMember(const CXXRecordDecl *RD, CXXBasePath &Path, DeclarationName Name) { - const unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_Tag | - Decl::IDNS_Member; - for (Path.Decls = BaseRecord->lookup(Name); - !Path.Decls.empty(); - Path.Decls = Path.Decls.slice(1)) { - if (Path.Decls.front()->isInIdentifierNamespace(IDNS)) + Path.Decls = RD->lookup(Name); + for (NamedDecl *ND : Path.Decls) + if (isOrdinaryMember(ND)) return true; - } return false; } -bool CXXRecordDecl::FindOrdinaryMember(const CXXBaseSpecifier *Specifier, - CXXBasePath &Path, - DeclarationName Name) { - RecordDecl *BaseRecord = - Specifier->getType()->castAs()->getDecl(); - return findOrdinaryMember(BaseRecord, Path, Name); +bool CXXRecordDecl::hasMemberName(DeclarationName Name) const { + CXXBasePath P; + if (findOrdinaryMember(this, P, Name)) + return true; + + CXXBasePaths Paths(false, false, false); + return lookupInBases( + [Name](const CXXBaseSpecifier *Specifier, CXXBasePath &Path) { + return findOrdinaryMember(Specifier->getType()->getAsCXXRecordDecl(), + Path, Name); + }, + Paths); } -bool CXXRecordDecl::FindOrdinaryMemberInDependentClasses( - const CXXBaseSpecifier *Specifier, CXXBasePath &Path, - DeclarationName Name) { +static bool +findOrdinaryMemberInDependentClasses(const CXXBaseSpecifier *Specifier, + CXXBasePath &Path, DeclarationName Name) { const TemplateSpecializationType *TST = Specifier->getType()->getAs(); if (!TST) { auto *RT = Specifier->getType()->getAs(); if (!RT) return false; - return findOrdinaryMember(RT->getDecl(), Path, Name); + return findOrdinaryMember(cast(RT->getDecl()), Path, Name); } TemplateName TN = TST->getTemplateName(); const auto *TD = dyn_cast_or_null(TN.getAsTemplateDecl()); @@ -461,80 +429,32 @@ bool CXXRecordDecl::FindOrdinaryMemberInDependentClasses( return findOrdinaryMember(RD, Path, Name); } -bool CXXRecordDecl::FindOMPReductionMember(const CXXBaseSpecifier *Specifier, - CXXBasePath &Path, - DeclarationName Name) { - RecordDecl *BaseRecord = - Specifier->getType()->castAs()->getDecl(); - - for (Path.Decls = BaseRecord->lookup(Name); !Path.Decls.empty(); - Path.Decls = Path.Decls.slice(1)) { - if (Path.Decls.front()->isInIdentifierNamespace(IDNS_OMPReduction)) - return true; - } - - return false; -} - -bool CXXRecordDecl::FindOMPMapperMember(const CXXBaseSpecifier *Specifier, - CXXBasePath &Path, - DeclarationName Name) { - RecordDecl *BaseRecord = - Specifier->getType()->castAs()->getDecl(); - - for (Path.Decls = BaseRecord->lookup(Name); !Path.Decls.empty(); - Path.Decls = Path.Decls.slice(1)) { - if (Path.Decls.front()->isInIdentifierNamespace(IDNS_OMPMapper)) - return true; - } - - return false; -} - -bool CXXRecordDecl:: -FindNestedNameSpecifierMember(const CXXBaseSpecifier *Specifier, - CXXBasePath &Path, - DeclarationName Name) { - RecordDecl *BaseRecord = - Specifier->getType()->castAs()->getDecl(); - - for (Path.Decls = BaseRecord->lookup(Name); - !Path.Decls.empty(); - Path.Decls = Path.Decls.slice(1)) { - // FIXME: Refactor the "is it a nested-name-specifier?" check - if (isa(Path.Decls.front()) || - Path.Decls.front()->isInIdentifierNamespace(IDNS_Tag)) - return true; - } - - return false; -} - std::vector CXXRecordDecl::lookupDependentName( - const DeclarationName &Name, + DeclarationName Name, llvm::function_ref Filter) { std::vector Results; // Lookup in the class. - DeclContext::lookup_result DirectResult = lookup(Name); - if (!DirectResult.empty()) { - for (const NamedDecl *ND : DirectResult) { - if (Filter(ND)) - Results.push_back(ND); - } - return Results; + bool AnyOrdinaryMembers = false; + for (const NamedDecl *ND : lookup(Name)) { + if (isOrdinaryMember(ND)) + AnyOrdinaryMembers = true; + if (Filter(ND)) + Results.push_back(ND); } + if (AnyOrdinaryMembers) + return Results; + // Perform lookup into our base classes. CXXBasePaths Paths; Paths.setOrigin(this); if (!lookupInBases( [&](const CXXBaseSpecifier *Specifier, CXXBasePath &Path) { - return CXXRecordDecl::FindOrdinaryMemberInDependentClasses( - Specifier, Path, Name); + return findOrdinaryMemberInDependentClasses(Specifier, Path, Name); }, Paths, /*LookupInDependent=*/true)) return Results; for (const NamedDecl *ND : Paths.front().Decls) { - if (Filter(ND)) + if (isOrdinaryMember(ND) && Filter(ND)) Results.push_back(ND); } return Results; diff --git a/clang/lib/AST/CommentLexer.cpp b/clang/lib/AST/CommentLexer.cpp index c1ea3eab075e..4bebd41e15ee 100644 --- a/clang/lib/AST/CommentLexer.cpp +++ b/clang/lib/AST/CommentLexer.cpp @@ -740,12 +740,11 @@ void Lexer::lexHTMLEndTag(Token &T) { Lexer::Lexer(llvm::BumpPtrAllocator &Allocator, DiagnosticsEngine &Diags, const CommandTraits &Traits, SourceLocation FileLoc, - const char *BufferStart, const char *BufferEnd, - bool ParseCommands) + const char *BufferStart, const char *BufferEnd, bool ParseCommands) : Allocator(Allocator), Diags(Diags), Traits(Traits), - BufferStart(BufferStart), BufferEnd(BufferEnd), FileLoc(FileLoc), - BufferPtr(BufferStart), CommentState(LCS_BeforeComment), State(LS_Normal), - ParseCommands(ParseCommands) {} + BufferStart(BufferStart), BufferEnd(BufferEnd), BufferPtr(BufferStart), + FileLoc(FileLoc), ParseCommands(ParseCommands), + CommentState(LCS_BeforeComment), State(LS_Normal) {} void Lexer::lex(Token &T) { again: diff --git a/clang/lib/AST/ComparisonCategories.cpp b/clang/lib/AST/ComparisonCategories.cpp index 6b6826c02a12..896050482644 100644 --- a/clang/lib/AST/ComparisonCategories.cpp +++ b/clang/lib/AST/ComparisonCategories.cpp @@ -42,7 +42,7 @@ clang::getComparisonCategoryForBuiltinCmp(QualType T) { bool ComparisonCategoryInfo::ValueInfo::hasValidIntValue() const { assert(VD && "must have var decl"); - if (!VD->checkInitIsICE()) + if (!VD->isUsableInConstantExpressions(VD->getASTContext())) return false; // Before we attempt to get the value of the first field, ensure that we diff --git a/clang/lib/AST/ComputeDependence.cpp b/clang/lib/AST/ComputeDependence.cpp index 2333993dbeb4..4026fdc76fd6 100644 --- a/clang/lib/AST/ComputeDependence.cpp +++ b/clang/lib/AST/ComputeDependence.cpp @@ -37,9 +37,39 @@ ExprDependence clang::computeDependence(ParenExpr *E) { return E->getSubExpr()->getDependence(); } -ExprDependence clang::computeDependence(UnaryOperator *E) { - return toExprDependence(E->getType()->getDependence()) | - E->getSubExpr()->getDependence(); +ExprDependence clang::computeDependence(UnaryOperator *E, + const ASTContext &Ctx) { + ExprDependence Dep = toExprDependence(E->getType()->getDependence()) | + E->getSubExpr()->getDependence(); + + // C++ [temp.dep.constexpr]p5: + // An expression of the form & qualified-id where the qualified-id names a + // dependent member of the current instantiation is value-dependent. An + // expression of the form & cast-expression is also value-dependent if + // evaluating cast-expression as a core constant expression succeeds and + // the result of the evaluation refers to a templated entity that is an + // object with static or thread storage duration or a member function. + // + // What this amounts to is: constant-evaluate the operand and check whether it + // refers to a templated entity other than a variable with local storage. + if (Ctx.getLangOpts().CPlusPlus && E->getOpcode() == UO_AddrOf && + !(Dep & ExprDependence::Value)) { + Expr::EvalResult Result; + SmallVector Diag; + Result.Diag = &Diag; + // FIXME: This doesn't enforce the C++98 constant expression rules. + if (E->getSubExpr()->EvaluateAsConstantExpr(Result, Ctx) && Diag.empty() && + Result.Val.isLValue()) { + auto *VD = Result.Val.getLValueBase().dyn_cast(); + if (VD && VD->isTemplated()) { + auto *VarD = dyn_cast(VD); + if (!VarD || !VarD->hasLocalStorage()) + Dep |= ExprDependence::Value; + } + } + } + + return Dep; } ExprDependence clang::computeDependence(UnaryExprOrTypeTraitExpr *E) { @@ -423,22 +453,21 @@ ExprDependence clang::computeDependence(DeclRefExpr *E, const ASTContext &Ctx) { Deps |= ExprDependence::UnexpandedPack; Deps |= toExprDependence(Type->getDependence()) & ExprDependence::Error; - // (TD) C++ [temp.dep.expr]p3: + // C++ [temp.dep.expr]p3: // An id-expression is type-dependent if it contains: - // - // and - // - // (VD) C++ [temp.dep.constexpr]p2: - // An identifier is value-dependent if it is: - // (TD) - an identifier that was declared with dependent type - // (VD) - a name declared with a dependent type, + // - an identifier associated by name lookup with one or more declarations + // declared with a dependent type + // + // [The "or more" case is not modeled as a DeclRefExpr. There are a bunch + // more bullets here that we handle by treating the declaration as having a + // dependent type if they involve a placeholder type that can't be deduced.] if (Type->isDependentType()) return Deps | ExprDependence::TypeValueInstantiation; else if (Type->isInstantiationDependentType()) Deps |= ExprDependence::Instantiation; - // (TD) - a conversion-function-id that specifies a dependent type + // - a conversion-function-id that specifies a dependent type if (Decl->getDeclName().getNameKind() == DeclarationName::CXXConversionFunctionName) { QualType T = Decl->getDeclName().getCXXNameType(); @@ -449,48 +478,65 @@ ExprDependence clang::computeDependence(DeclRefExpr *E, const ASTContext &Ctx) { Deps |= ExprDependence::Instantiation; } - // (VD) - the name of a non-type template parameter, + // - a template-id that is dependent, + // - a nested-name-specifier or a qualified-id that names a member of an + // unknown specialization + // [These are not modeled as DeclRefExprs.] + + // or if it names a dependent member of the current instantiation that is a + // static data member of type "array of unknown bound of T" for some T + // [handled below]. + + // C++ [temp.dep.constexpr]p2: + // An id-expression is value-dependent if: + + // - it is type-dependent [handled above] + + // - it is the name of a non-type template parameter, if (isa(Decl)) return Deps | ExprDependence::ValueInstantiation; - // (VD) - a constant with integral or enumeration type and is - // initialized with an expression that is value-dependent. - // (VD) - a constant with literal type and is initialized with an - // expression that is value-dependent [C++11]. - // (VD) - FIXME: Missing from the standard: - // - an entity with reference type and is initialized with an - // expression that is value-dependent [C++11] - if (VarDecl *Var = dyn_cast(Decl)) { - if ((Ctx.getLangOpts().CPlusPlus11 - ? Var->getType()->isLiteralType(Ctx) - : Var->getType()->isIntegralOrEnumerationType()) && - (Var->getType().isConstQualified() || - Var->getType()->isReferenceType())) { - if (const Expr *Init = Var->getAnyInitializer()) - if (Init->isValueDependent()) { + // - it names a potentially-constant variable that is initialized with an + // expression that is value-dependent + if (const auto *Var = dyn_cast(Decl)) { + if (Var->mightBeUsableInConstantExpressions(Ctx)) { + if (const Expr *Init = Var->getAnyInitializer()) { + if (Init->isValueDependent()) Deps |= ExprDependence::ValueInstantiation; - } + if (Init->containsErrors()) + Deps |= ExprDependence::Error; + } } - // (VD) - FIXME: Missing from the standard: - // - a member function or a static data member of the current - // instantiation + // - it names a static data member that is a dependent member of the + // current instantiation and is not initialized in a member-declarator, if (Var->isStaticDataMember() && - Var->getDeclContext()->isDependentContext()) { - Deps |= ExprDependence::ValueInstantiation; - TypeSourceInfo *TInfo = Var->getFirstDecl()->getTypeSourceInfo(); - if (TInfo->getType()->isIncompleteArrayType()) - Deps |= ExprDependence::Type; + Var->getDeclContext()->isDependentContext() && + !Var->getFirstDecl()->hasInit()) { + const VarDecl *First = Var->getFirstDecl(); + TypeSourceInfo *TInfo = First->getTypeSourceInfo(); + if (TInfo->getType()->isIncompleteArrayType()) { + Deps |= ExprDependence::TypeValueInstantiation; + } else if (!First->hasInit()) { + Deps |= ExprDependence::ValueInstantiation; + } } return Deps; } - // (VD) - FIXME: Missing from the standard: - // - a member function or a static data member of the current - // instantiation - if (isa(Decl) && Decl->getDeclContext()->isDependentContext()) - Deps |= ExprDependence::ValueInstantiation; + // - it names a static member function that is a dependent member of the + // current instantiation + // + // FIXME: It's unclear that the restriction to static members here has any + // effect: any use of a non-static member function name requires either + // forming a pointer-to-member or providing an object parameter, either of + // which makes the overall expression value-dependent. + if (auto *MD = dyn_cast(Decl)) { + if (MD->isStatic() && Decl->getDeclContext()->isDependentContext()) + Deps |= ExprDependence::ValueInstantiation; + } + return Deps; } @@ -502,7 +548,7 @@ ExprDependence clang::computeDependence(RecoveryExpr *E) { // dependent type), or the type is known and dependent, or it has // type-dependent subexpressions. auto D = toExprDependence(E->getType()->getDependence()) | - ExprDependence::ValueInstantiation | ExprDependence::Error; + ExprDependence::ErrorDependent; // FIXME: remove the type-dependent bit from subexpressions, if the // RecoveryExpr has a non-dependent type. for (auto *S : E->subExpressions()) @@ -694,6 +740,10 @@ ExprDependence clang::computeDependence(CXXConstructExpr *E) { return D; } +ExprDependence clang::computeDependence(CXXDefaultInitExpr *E) { + return E->getExpr()->getDependence(); +} + ExprDependence clang::computeDependence(LambdaExpr *E, bool ContainsUnexpandedParameterPack) { auto D = toExprDependence(E->getType()->getDependence()); @@ -705,8 +755,6 @@ ExprDependence clang::computeDependence(LambdaExpr *E, ExprDependence clang::computeDependence(CXXUnresolvedConstructExpr *E) { auto D = ExprDependence::ValueInstantiation; D |= toExprDependence(E->getType()->getDependence()); - if (E->getType()->getContainedDeducedType()) - D |= ExprDependence::Type; for (auto *A : E->arguments()) D |= A->getDependence() & (ExprDependence::UnexpandedPack | ExprDependence::Error); diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 5c0a98815dd7..feb9b0645ebc 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -1299,7 +1299,8 @@ LinkageInfo LinkageComputer::getLVForLocalDecl(const NamedDecl *D, // we should not make static local variables in the function hidden. LV = getLVForDecl(FD, computation); if (isa(D) && useInlineVisibilityHidden(FD) && - !LV.isVisibilityExplicit()) { + !LV.isVisibilityExplicit() && + !Context.getLangOpts().VisibilityInlinesHiddenStaticLocalVar) { assert(cast(D)->isStaticLocal()); // If this was an implicitly hidden inline method, check again for // explicit visibility on the parent class, and use that for static locals @@ -1394,6 +1395,15 @@ LinkageInfo LinkageComputer::computeLVForDecl(const NamedDecl *D, break; } + + case Decl::TemplateParamObject: { + // The template parameter object can be referenced from anywhere its type + // and value can be referenced. + auto *TPO = cast(D); + LinkageInfo LV = getLVForType(*TPO->getType(), computation); + LV.merge(getLVForValue(TPO->getValue(), computation)); + return LV; + } } // Handle linkage for namespace-scope names. @@ -1590,21 +1600,37 @@ void NamedDecl::printNestedNameSpecifier(raw_ostream &OS, ContextsTy Contexts; // Collect named contexts. - while (Ctx) { - if (isa(Ctx)) - Contexts.push_back(Ctx); - Ctx = Ctx->getParent(); + DeclarationName NameInScope = getDeclName(); + for (; Ctx; Ctx = Ctx->getParent()) { + // Suppress anonymous namespace if requested. + if (P.SuppressUnwrittenScope && isa(Ctx) && + cast(Ctx)->isAnonymousNamespace()) + continue; + + // Suppress inline namespace if it doesn't make the result ambiguous. + if (P.SuppressInlineNamespace && Ctx->isInlineNamespace() && NameInScope && + Ctx->lookup(NameInScope).size() == + Ctx->getParent()->lookup(NameInScope).size()) + continue; + + // Skip non-named contexts such as linkage specifications and ExportDecls. + const NamedDecl *ND = dyn_cast(Ctx); + if (!ND) + continue; + + Contexts.push_back(Ctx); + NameInScope = ND->getDeclName(); } - for (const DeclContext *DC : llvm::reverse(Contexts)) { + for (unsigned I = Contexts.size(); I != 0; --I) { + const DeclContext *DC = Contexts[I - 1]; if (const auto *Spec = dyn_cast(DC)) { OS << Spec->getName(); const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); - printTemplateArgumentList(OS, TemplateArgs.asArray(), P); + printTemplateArgumentList( + OS, TemplateArgs.asArray(), P, + Spec->getSpecializedTemplate()->getTemplateParameters()); } else if (const auto *ND = dyn_cast(DC)) { - if (P.SuppressUnwrittenScope && - (ND->isAnonymousNamespace() || ND->isInline())) - continue; if (ND->isAnonymousNamespace()) { OS << (P.MSVCFormatting ? "`anonymous namespace\'" : "(anonymous namespace)"); @@ -1797,8 +1823,7 @@ template static SourceLocation getTemplateOrInnerLocStart(const DeclT *decl) { if (decl->getNumTemplateParameterLists() > 0) return decl->getTemplateParameterList(0)->getTemplateLoc(); - else - return decl->getInnerLocStart(); + return decl->getInnerLocStart(); } SourceLocation DeclaratorDecl::getTypeSpecStartLoc() const { @@ -2106,10 +2131,9 @@ VarDecl::isThisDeclarationADefinition(ASTContext &C) const { TSK_ExplicitSpecialization) || isa(this))) return Definition; - else if (!isOutOfLine() && isInline()) + if (!isOutOfLine() && isInline()) return Definition; - else - return DeclarationOnly; + return DeclarationOnly; } // C99 6.7p5: // A definition of an identifier is a declaration for that identifier that @@ -2172,7 +2196,7 @@ VarDecl *VarDecl::getActingDefinition() { Kind = I->isThisDeclarationADefinition(); if (Kind == Definition) return nullptr; - else if (Kind == TentativeDefinition) + if (Kind == TentativeDefinition) LastTentative = I; } return LastTentative; @@ -2244,8 +2268,7 @@ VarDecl *VarDecl::getInitializingDeclaration() { if (I->isThisDeclarationADefinition()) { if (isStaticDataMember()) return I; - else - Def = I; + Def = I; } } return Def; @@ -2276,16 +2299,22 @@ void VarDecl::setInit(Expr *I) { Init = I; } -bool VarDecl::mightBeUsableInConstantExpressions(ASTContext &C) const { +bool VarDecl::mightBeUsableInConstantExpressions(const ASTContext &C) const { const LangOptions &Lang = C.getLangOpts(); - if (!Lang.CPlusPlus) + // OpenCL permits const integral variables to be used in constant + // expressions, like in C++98. + if (!Lang.CPlusPlus && !Lang.OpenCL) return false; // Function parameters are never usable in constant expressions. if (isa(this)) return false; + // The values of weak variables are never usable in constant expressions. + if (isWeak()) + return false; + // In C++11, any variable of reference type can be used in a constant // expression if it is initialized by a constant expression. if (Lang.CPlusPlus11 && getType()->isReferenceType()) @@ -2294,7 +2323,7 @@ bool VarDecl::mightBeUsableInConstantExpressions(ASTContext &C) const { // Only const objects can be used in constant expressions in C++. C++98 does // not require the variable to be non-volatile, but we consider this to be a // defect. - if (!getType().isConstQualified() || getType().isVolatileQualified()) + if (!getType().isConstant(C) || getType().isVolatileQualified()) return false; // In C++, const, non-volatile variables of integral or enumeration types @@ -2307,7 +2336,7 @@ bool VarDecl::mightBeUsableInConstantExpressions(ASTContext &C) const { return Lang.CPlusPlus11 && isConstexpr(); } -bool VarDecl::isUsableInConstantExpressions(ASTContext &Context) const { +bool VarDecl::isUsableInConstantExpressions(const ASTContext &Context) const { // C++2a [expr.const]p3: // A variable is usable in constant expressions after its initializing // declaration is encountered... @@ -2320,7 +2349,16 @@ bool VarDecl::isUsableInConstantExpressions(ASTContext &Context) const { if (!DefVD->mightBeUsableInConstantExpressions(Context)) return false; // ... and its initializer is a constant initializer. - return DefVD->checkInitIsICE(); + if (Context.getLangOpts().CPlusPlus && !DefVD->hasConstantInitialization()) + return false; + // C++98 [expr.const]p1: + // An integral constant-expression can involve only [...] const variables + // or static data members of integral or enumeration types initialized with + // [integer] constant expressions (dcl.init) + if ((Context.getLangOpts().CPlusPlus || Context.getLangOpts().OpenCL) && + !Context.getLangOpts().CPlusPlus11 && !DefVD->hasICEInitializer(Context)) + return false; + return true; } /// Convert the initializer for this declaration to the elaborated EvaluatedStmt @@ -2340,35 +2378,45 @@ EvaluatedStmt *VarDecl::ensureEvaluatedStmt() const { return Eval; } +EvaluatedStmt *VarDecl::getEvaluatedStmt() const { + return Init.dyn_cast(); +} + APValue *VarDecl::evaluateValue() const { SmallVector Notes; - return evaluateValue(Notes); + return evaluateValueImpl(Notes, hasConstantInitialization()); } -APValue *VarDecl::evaluateValue( - SmallVectorImpl &Notes) const { +APValue *VarDecl::evaluateValueImpl(SmallVectorImpl &Notes, + bool IsConstantInitialization) const { EvaluatedStmt *Eval = ensureEvaluatedStmt(); + const auto *Init = cast(Eval->Value); + assert(!Init->isValueDependent()); + // We only produce notes indicating why an initializer is non-constant the // first time it is evaluated. FIXME: The notes won't always be emitted the // first time we try evaluation, so might not be produced at all. if (Eval->WasEvaluated) return Eval->Evaluated.isAbsent() ? nullptr : &Eval->Evaluated; - const auto *Init = cast(Eval->Value); - assert(!Init->isValueDependent()); - if (Eval->IsEvaluating) { // FIXME: Produce a diagnostic for self-initialization. - Eval->CheckedICE = true; - Eval->IsICE = false; return nullptr; } Eval->IsEvaluating = true; - bool Result = Init->EvaluateAsInitializer(Eval->Evaluated, getASTContext(), - this, Notes); + ASTContext &Ctx = getASTContext(); + bool Result = Init->EvaluateAsInitializer(Eval->Evaluated, Ctx, this, Notes, + IsConstantInitialization); + + // In C++11, this isn't a constant initializer if we produced notes. In that + // case, we can't keep the result, because it may only be correct under the + // assumption that the initializer is a constant context. + if (IsConstantInitialization && Ctx.getLangOpts().CPlusPlus11 && + !Notes.empty()) + Result = false; // Ensure the computed APValue is cleaned up later if evaluation succeeded, // or that it's empty (so that there's nothing to clean up) if evaluation @@ -2376,76 +2424,69 @@ APValue *VarDecl::evaluateValue( if (!Result) Eval->Evaluated = APValue(); else if (Eval->Evaluated.needsCleanup()) - getASTContext().addDestruction(&Eval->Evaluated); + Ctx.addDestruction(&Eval->Evaluated); Eval->IsEvaluating = false; Eval->WasEvaluated = true; - // In C++11, we have determined whether the initializer was a constant - // expression as a side-effect. - if (getASTContext().getLangOpts().CPlusPlus11 && !Eval->CheckedICE) { - Eval->CheckedICE = true; - Eval->IsICE = Result && Notes.empty(); - } - return Result ? &Eval->Evaluated : nullptr; } APValue *VarDecl::getEvaluatedValue() const { - if (EvaluatedStmt *Eval = Init.dyn_cast()) + if (EvaluatedStmt *Eval = getEvaluatedStmt()) if (Eval->WasEvaluated) return &Eval->Evaluated; return nullptr; } -bool VarDecl::isInitKnownICE() const { - if (EvaluatedStmt *Eval = Init.dyn_cast()) - return Eval->CheckedICE; +bool VarDecl::hasICEInitializer(const ASTContext &Context) const { + const Expr *Init = getInit(); + assert(Init && "no initializer"); - return false; + EvaluatedStmt *Eval = ensureEvaluatedStmt(); + if (!Eval->CheckedForICEInit) { + Eval->CheckedForICEInit = true; + Eval->HasICEInit = Init->isIntegerConstantExpr(Context); + } + return Eval->HasICEInit; } -bool VarDecl::isInitICE() const { - assert(isInitKnownICE() && - "Check whether we already know that the initializer is an ICE"); - return Init.get()->IsICE; -} +bool VarDecl::hasConstantInitialization() const { + // In C, all globals (and only globals) have constant initialization. + if (hasGlobalStorage() && !getASTContext().getLangOpts().CPlusPlus) + return true; -bool VarDecl::checkInitIsICE() const { - // Initializers of weak variables are never ICEs. - if (isWeak()) - return false; + // In C++, it depends on whether the evaluation at the point of definition + // was evaluatable as a constant initializer. + if (EvaluatedStmt *Eval = getEvaluatedStmt()) + return Eval->HasConstantInitialization; - EvaluatedStmt *Eval = ensureEvaluatedStmt(); - if (Eval->CheckedICE) - // We have already checked whether this subexpression is an - // integral constant expression. - return Eval->IsICE; + return false; +} - const auto *Init = cast(Eval->Value); - assert(!Init->isValueDependent()); +bool VarDecl::checkForConstantInitialization( + SmallVectorImpl &Notes) const { + EvaluatedStmt *Eval = ensureEvaluatedStmt(); + // If we ask for the value before we know whether we have a constant + // initializer, we can compute the wrong value (for example, due to + // std::is_constant_evaluated()). + assert(!Eval->WasEvaluated && + "already evaluated var value before checking for constant init"); + assert(getASTContext().getLangOpts().CPlusPlus && "only meaningful in C++"); - // In C++11, evaluate the initializer to check whether it's a constant - // expression. - if (getASTContext().getLangOpts().CPlusPlus11) { - SmallVector Notes; - evaluateValue(Notes); - return Eval->IsICE; - } + assert(!cast(Eval->Value)->isValueDependent()); - // It's an ICE whether or not the definition we found is - // out-of-line. See DR 721 and the discussion in Clang PR - // 6206 for details. + // Evaluate the initializer to check whether it's a constant expression. + Eval->HasConstantInitialization = + evaluateValueImpl(Notes, true) && Notes.empty(); - if (Eval->CheckingICE) - return false; - Eval->CheckingICE = true; + // If evaluation as a constant initializer failed, allow re-evaluation as a + // non-constant initializer if we later find we want the value. + if (!Eval->HasConstantInitialization) + Eval->WasEvaluated = false; - Eval->IsICE = Init->isIntegerConstantExpr(getASTContext()); - Eval->CheckingICE = false; - Eval->CheckedICE = true; - return Eval->IsICE; + return Eval->HasConstantInitialization; } bool VarDecl::isParameterPack() const { @@ -2598,7 +2639,7 @@ bool VarDecl::isNoDestroy(const ASTContext &Ctx) const { QualType::DestructionKind VarDecl::needsDestruction(const ASTContext &Ctx) const { - if (EvaluatedStmt *Eval = Init.dyn_cast()) + if (EvaluatedStmt *Eval = getEvaluatedStmt()) if (Eval->HasConstantDestruction) return QualType::DK_none; @@ -2694,6 +2735,17 @@ SourceRange ParmVarDecl::getSourceRange() const { return DeclaratorDecl::getSourceRange(); } +bool ParmVarDecl::isDestroyedInCallee() const { + if (hasAttr()) + return true; + + auto *RT = getType()->getAs(); + if (RT && RT->getDecl()->isParamDestroyedInCallee()) + return true; + + return false; +} + Expr *ParmVarDecl::getDefaultArg() { assert(!hasUnparsedDefaultArg() && "Default argument is not yet parsed!"); assert(!hasUninstantiatedDefaultArg() && @@ -2790,7 +2842,7 @@ FunctionDecl::FunctionDecl(Kind DK, ASTContext &C, DeclContext *DC, FunctionDeclBits.HasDefaultedFunctionInfo = false; FunctionDeclBits.HasImplicitReturnZero = false; FunctionDeclBits.IsLateTemplateParsed = false; - FunctionDeclBits.ConstexprKind = ConstexprKind; + FunctionDeclBits.ConstexprKind = static_cast(ConstexprKind); FunctionDeclBits.InstantiationIsPending = false; FunctionDeclBits.UsesSEHTry = false; FunctionDeclBits.UsesFPIntrin = false; @@ -2867,10 +2919,55 @@ bool FunctionDecl::hasTrivialBody() const { return false; } -bool FunctionDecl::isDefined(const FunctionDecl *&Definition) const { - for (auto I : redecls()) { - if (I->isThisDeclarationADefinition()) { - Definition = I; +bool FunctionDecl::isThisDeclarationInstantiatedFromAFriendDefinition() const { + if (!getFriendObjectKind()) + return false; + + // Check for a friend function instantiated from a friend function + // definition in a templated class. + if (const FunctionDecl *InstantiatedFrom = + getInstantiatedFromMemberFunction()) + return InstantiatedFrom->getFriendObjectKind() && + InstantiatedFrom->isThisDeclarationADefinition(); + + // Check for a friend function template instantiated from a friend + // function template definition in a templated class. + if (const FunctionTemplateDecl *Template = getDescribedFunctionTemplate()) { + if (const FunctionTemplateDecl *InstantiatedFrom = + Template->getInstantiatedFromMemberTemplate()) + return InstantiatedFrom->getFriendObjectKind() && + InstantiatedFrom->isThisDeclarationADefinition(); + } + + return false; +} + +bool FunctionDecl::isDefined(const FunctionDecl *&Definition, + bool CheckForPendingFriendDefinition) const { + for (const FunctionDecl *FD : redecls()) { + if (FD->isThisDeclarationADefinition()) { + Definition = FD; + return true; + } + + // If this is a friend function defined in a class template, it does not + // have a body until it is used, nevertheless it is a definition, see + // [temp.inst]p2: + // + // ... for the purpose of determining whether an instantiated redeclaration + // is valid according to [basic.def.odr] and [class.mem], a declaration that + // corresponds to a definition in the template is considered to be a + // definition. + // + // The following code must produce redefinition error: + // + // template struct C20 { friend void func_20() {} }; + // C20 c20i; + // void func_20() {} + // + if (CheckForPendingFriendDefinition && + FD->isThisDeclarationInstantiatedFromAFriendDefinition()) { + Definition = FD; return true; } } @@ -3162,44 +3259,24 @@ FunctionDecl *FunctionDecl::getCanonicalDecl() { return getFirstDecl(); } /// functions as their wrapped builtins. This shouldn't be done in general, but /// it's useful in Sema to diagnose calls to wrappers based on their semantics. unsigned FunctionDecl::getBuiltinID(bool ConsiderWrapperFunctions) const { - unsigned BuiltinID; + unsigned BuiltinID = 0; if (const auto *ABAA = getAttr()) { BuiltinID = ABAA->getBuiltinName()->getBuiltinID(); - } else { - if (!getIdentifier()) - return 0; - - BuiltinID = getIdentifier()->getBuiltinID(); + } else if (const auto *A = getAttr()) { + BuiltinID = A->getID(); } if (!BuiltinID) return 0; - ASTContext &Context = getASTContext(); - if (Context.getLangOpts().CPlusPlus) { - const auto *LinkageDecl = - dyn_cast(getFirstDecl()->getDeclContext()); - // In C++, the first declaration of a builtin is always inside an implicit - // extern "C". - // FIXME: A recognised library function may not be directly in an extern "C" - // declaration, for instance "extern "C" { namespace std { decl } }". - if (!LinkageDecl) { - if (BuiltinID == Builtin::BI__GetExceptionInfo && - Context.getTargetInfo().getCXXABI().isMicrosoft()) - return Builtin::BI__GetExceptionInfo; - return 0; - } - if (LinkageDecl->getLanguage() != LinkageSpecDecl::lang_c) - return 0; - } - // If the function is marked "overloadable", it has a different mangled name // and is not the C library function. if (!ConsiderWrapperFunctions && hasAttr() && !hasAttr()) return 0; + ASTContext &Context = getASTContext(); if (!Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) return BuiltinID; @@ -3515,8 +3592,7 @@ bool FunctionDecl::isInlineDefinitionExternallyVisible() const { OverloadedOperatorKind FunctionDecl::getOverloadedOperator() const { if (getDeclName().getNameKind() == DeclarationName::CXXOperatorName) return getDeclName().getCXXOverloadedOperator(); - else - return OO_None; + return OO_None; } /// getLiteralIdentifier - The literal suffix identifier this function @@ -3524,8 +3600,7 @@ OverloadedOperatorKind FunctionDecl::getOverloadedOperator() const { const IdentifierInfo *FunctionDecl::getLiteralIdentifier() const { if (getDeclName().getNameKind() == DeclarationName::CXXLiteralOperatorName) return getDeclName().getCXXLiteralIdentifier(); - else - return nullptr; + return nullptr; } FunctionDecl::TemplatedKind FunctionDecl::getTemplatedKind() const { @@ -3640,7 +3715,13 @@ FunctionDecl::getTemplateInstantiationPattern(bool ForDefinition) const { return getDefinitionOrSelf(getPrimaryTemplate()->getTemplatedDecl()); } - if (MemberSpecializationInfo *Info = getMemberSpecializationInfo()) { + // Check for a declaration of this function that was instantiated from a + // friend definition. + const FunctionDecl *FD = nullptr; + if (!isDefined(FD, /*CheckForPendingFriendDefinition=*/true)) + FD = this; + + if (MemberSpecializationInfo *Info = FD->getMemberSpecializationInfo()) { if (ForDefinition && !clang::isTemplateInstantiation(Info->getTemplateSpecializationKind())) return nullptr; @@ -3852,8 +3933,8 @@ SourceLocation FunctionDecl::getPointOfInstantiation() const { = TemplateOrSpecialization.dyn_cast< FunctionTemplateSpecializationInfo*>()) return FTSInfo->getPointOfInstantiation(); - else if (MemberSpecializationInfo *MSInfo - = TemplateOrSpecialization.dyn_cast()) + if (MemberSpecializationInfo *MSInfo = + TemplateOrSpecialization.dyn_cast()) return MSInfo->getPointOfInstantiation(); return SourceLocation(); @@ -3960,34 +4041,40 @@ unsigned FunctionDecl::getMemoryFunctionKind() const { case Builtin::BIbzero: return Builtin::BIbzero; + case Builtin::BIfree: + return Builtin::BIfree; + default: if (isExternC()) { if (FnInfo->isStr("memset")) return Builtin::BImemset; - else if (FnInfo->isStr("memcpy")) + if (FnInfo->isStr("memcpy")) return Builtin::BImemcpy; - else if (FnInfo->isStr("mempcpy")) + if (FnInfo->isStr("mempcpy")) return Builtin::BImempcpy; - else if (FnInfo->isStr("memmove")) + if (FnInfo->isStr("memmove")) return Builtin::BImemmove; - else if (FnInfo->isStr("memcmp")) + if (FnInfo->isStr("memcmp")) return Builtin::BImemcmp; - else if (FnInfo->isStr("bcmp")) + if (FnInfo->isStr("bcmp")) return Builtin::BIbcmp; - else if (FnInfo->isStr("strncpy")) + if (FnInfo->isStr("strncpy")) return Builtin::BIstrncpy; - else if (FnInfo->isStr("strncmp")) + if (FnInfo->isStr("strncmp")) return Builtin::BIstrncmp; - else if (FnInfo->isStr("strncasecmp")) + if (FnInfo->isStr("strncasecmp")) return Builtin::BIstrncasecmp; - else if (FnInfo->isStr("strncat")) + if (FnInfo->isStr("strncat")) return Builtin::BIstrncat; - else if (FnInfo->isStr("strndup")) + if (FnInfo->isStr("strndup")) return Builtin::BIstrndup; - else if (FnInfo->isStr("strlen")) + if (FnInfo->isStr("strlen")) return Builtin::BIstrlen; - else if (FnInfo->isStr("bzero")) + if (FnInfo->isStr("bzero")) return Builtin::BIbzero; + } else if (isInStdNamespace()) { + if (FnInfo->isStr("free")) + return Builtin::BIfree; } break; } @@ -4705,11 +4792,9 @@ char *Buffer = new (getASTContext(), 1) char[Name.size() + 1]; void ValueDecl::anchor() {} bool ValueDecl::isWeak() const { - for (const auto *I : attrs()) - if (isa(I) || isa(I)) - return true; - - return isWeakImported(); + auto *MostRecent = getMostRecentDecl(); + return MostRecent->hasAttr() || + MostRecent->hasAttr() || isWeakImported(); } void ImplicitParamDecl::anchor() {} @@ -4748,9 +4833,9 @@ FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC, } FunctionDecl *FunctionDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - return new (C, ID) FunctionDecl(Function, C, nullptr, SourceLocation(), - DeclarationNameInfo(), QualType(), nullptr, - SC_None, false, CSK_unspecified, nullptr); + return new (C, ID) FunctionDecl( + Function, C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(), + nullptr, SC_None, false, ConstexprSpecKind::Unspecified, nullptr); } BlockDecl *BlockDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L) { diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index da1eadd9d931..c26d6d1a42ea 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -230,11 +230,11 @@ bool Decl::isTemplateDecl() const { TemplateDecl *Decl::getDescribedTemplate() const { if (auto *FD = dyn_cast(this)) return FD->getDescribedFunctionTemplate(); - else if (auto *RD = dyn_cast(this)) + if (auto *RD = dyn_cast(this)) return RD->getDescribedClassTemplate(); - else if (auto *VD = dyn_cast(this)) + if (auto *VD = dyn_cast(this)) return VD->getDescribedVarTemplate(); - else if (auto *AD = dyn_cast(this)) + if (auto *AD = dyn_cast(this)) return AD->getDescribedAliasTemplate(); return nullptr; @@ -695,24 +695,23 @@ bool Decl::canBeWeakImported(bool &IsDefinition) const { return false; } return true; - + } // Functions, if they aren't definitions. - } else if (const auto *FD = dyn_cast(this)) { + if (const auto *FD = dyn_cast(this)) { if (FD->hasBody()) { IsDefinition = true; return false; } return true; + } // Objective-C classes, if this is the non-fragile runtime. - } else if (isa(this) && + if (isa(this) && getASTContext().getLangOpts().ObjCRuntime.hasWeakClassImport()) { return true; - - // Nothing else. - } else { - return false; } + // Nothing else. + return false; } bool Decl::isWeakImported() const { @@ -720,7 +719,7 @@ bool Decl::isWeakImported() const { if (!canBeWeakImported(IsDefinition)) return false; - for (const auto *A : attrs()) { + for (const auto *A : getMostRecentDecl()->attrs()) { if (isa(A)) return true; @@ -835,6 +834,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { case ExternCContext: case Decomposition: case MSGuid: + case TemplateParamObject: case UsingDirective: case BuiltinTemplate: @@ -970,21 +970,19 @@ bool Decl::AccessDeclContextSanity() const { // 5. it's invalid // 6. it's a C++0x static_assert. // 7. it's a block literal declaration - if (isa(this) || - isa(this) || - isa(this) || - !getDeclContext() || - !isa(getDeclContext()) || - isInvalidDecl() || - isa(this) || - isa(this) || + // 8. it's a temporary with lifetime extended due to being default value. + if (isa(this) || isa(this) || + isa(this) || !getDeclContext() || + !isa(getDeclContext()) || isInvalidDecl() || + isa(this) || isa(this) || // FIXME: a ParmVarDecl can have ClassTemplateSpecialization // as DeclContext (?). isa(this) || // FIXME: a ClassTemplateSpecialization or CXXRecordDecl can have // AS_none as access specifier. isa(this) || - isa(this)) + isa(this) || + isa(this)) return true; assert(Access != AS_none && @@ -1028,16 +1026,16 @@ template static Decl *getNonClosureContext(T *D) { MD->getParent()->isLambda()) return getNonClosureContext(MD->getParent()->getParent()); return MD; - } else if (auto *FD = dyn_cast(D)) + } + if (auto *FD = dyn_cast(D)) return FD; - else if (auto *MD = dyn_cast(D)) + if (auto *MD = dyn_cast(D)) return MD; - else if (auto *BD = dyn_cast(D)) + if (auto *BD = dyn_cast(D)) return getNonClosureContext(BD->getParent()); - else if (auto *CD = dyn_cast(D)) + if (auto *CD = dyn_cast(D)) return getNonClosureContext(CD->getParent()); - else - return nullptr; + return nullptr; } Decl *Decl::getNonClosureContext() { @@ -1172,10 +1170,8 @@ bool DeclContext::isDependentContext() const { bool DeclContext::isTransparentContext() const { if (getDeclKind() == Decl::Enum) return !cast(this)->isScoped(); - else if (getDeclKind() == Decl::LinkageSpec || getDeclKind() == Decl::Export) - return true; - return false; + return getDeclKind() == Decl::LinkageSpec || getDeclKind() == Decl::Export; } static bool isLinkageSpecContext(const DeclContext *DC, @@ -1487,6 +1483,13 @@ static bool shouldBeHidden(NamedDecl *D) { if (FD->isFunctionTemplateSpecialization()) return true; + // Hide destructors that are invalid. There should always be one destructor, + // but if it is an invalid decl, another one is created. We need to hide the + // invalid one from places that expect exactly one destructor, like the + // serialization code. + if (isa(D) && D->isInvalidDecl()) + return true; + return false; } @@ -2020,9 +2023,9 @@ DependentDiagnostic *DependentDiagnostic::Create(ASTContext &C, // Allocate the copy of the PartialDiagnostic via the ASTContext's // BumpPtrAllocator, rather than the ASTContext itself. - PartialDiagnostic::Storage *DiagStorage = nullptr; + DiagnosticStorage *DiagStorage = nullptr; if (PDiag.hasStorage()) - DiagStorage = new (C) PartialDiagnostic::Storage; + DiagStorage = new (C) DiagnosticStorage; auto *DD = new (C) DependentDiagnostic(PDiag, DiagStorage); diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 6f1fd2f14ede..0368ada0b81c 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -81,7 +81,9 @@ CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D) HasPublicFields(false), HasMutableFields(false), HasVariantMembers(false), HasOnlyCMembers(true), HasInClassInitializer(false), HasUninitializedReferenceMember(false), HasUninitializedFields(false), - HasInheritedConstructor(false), HasInheritedAssignment(false), + HasInheritedConstructor(false), + HasInheritedDefaultConstructor(false), + HasInheritedAssignment(false), NeedOverloadResolutionForCopyConstructor(false), NeedOverloadResolutionForMoveConstructor(false), NeedOverloadResolutionForCopyAssignment(false), @@ -100,7 +102,7 @@ CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D) DefaultedDefaultConstructorIsConstexpr(true), HasConstexprDefaultConstructor(false), DefaultedDestructorIsConstexpr(true), - HasNonLiteralTypeFieldsOrBases(false), + HasNonLiteralTypeFieldsOrBases(false), StructuralIfLiteral(true), UserProvidedDefaultConstructor(false), DeclaredSpecialMembers(0), ImplicitCopyConstructorCanHaveConstParamForVBase(true), ImplicitCopyConstructorCanHaveConstParamForNonVBase(true), @@ -258,9 +260,15 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, // C++1z [dcl.init.agg]p1: // An aggregate is a class with [...] no private or protected base classes - if (Base->getAccessSpecifier() != AS_public) + if (Base->getAccessSpecifier() != AS_public) { data().Aggregate = false; + // C++20 [temp.param]p7: + // A structural type is [...] a literal class type with [...] all base + // classes [...] public + data().StructuralIfLiteral = false; + } + // C++ [class.virtual]p1: // A class that declares or inherits a virtual function is called a // polymorphic class. @@ -536,6 +544,13 @@ void CXXRecordDecl::addedClassSubobject(CXXRecordDecl *Subobj) { // array thereof, that class type shall have a constexpr destructor if (!Subobj->hasConstexprDestructor()) data().DefaultedDestructorIsConstexpr = false; + + // C++20 [temp.param]p7: + // A structural type is [...] a literal class type [for which] the types + // of all base classes and non-static data members are structural types or + // (possibly multi-dimensional) array thereof + if (!Subobj->data().StructuralIfLiteral) + data().StructuralIfLiteral = false; } bool CXXRecordDecl::hasConstexprDestructor() const { @@ -801,6 +816,8 @@ void CXXRecordDecl::addedMember(Decl *D) { // constructor [...] if (Constructor->isConstexpr() && !Constructor->isCopyOrMoveConstructor()) data().HasConstexprNonCopyMoveConstructor = true; + if (!isa(D) && Constructor->isDefaultConstructor()) + data().HasInheritedDefaultConstructor = true; } // Handle destructors. @@ -956,6 +973,11 @@ void CXXRecordDecl::addedMember(Decl *D) { if (D->getAccess() == AS_private || D->getAccess() == AS_protected) { data().Aggregate = false; data().PlainOldData = false; + + // C++20 [temp.param]p7: + // A structural type is [...] a literal class type [for which] all + // non-static data members are public + data().StructuralIfLiteral = false; } // Track whether this is the first field. We use this when checking @@ -980,9 +1002,15 @@ void CXXRecordDecl::addedMember(Decl *D) { } // Keep track of the presence of mutable fields. - if (Field->isMutable()) + if (Field->isMutable()) { data().HasMutableFields = true; + // C++20 [temp.param]p7: + // A structural type is [...] a literal class type [for which] all + // non-static data members are public + data().StructuralIfLiteral = false; + } + // C++11 [class.union]p8, DR1460: // If X is a union, a non-static data member of X that is not an anonymous // union is a variant member of X. @@ -1315,6 +1343,14 @@ void CXXRecordDecl::addedMember(Decl *D) { data().DefaultedCopyAssignmentIsDeleted = true; data().DefaultedMoveAssignmentIsDeleted = true; } + + // C++20 [temp.param]p7: + // A structural type is [...] a literal class type [for which] the + // types of all non-static data members are structural types or + // (possibly multidimensional) array thereof + // We deal with class types elsewhere. + if (!T->isStructuralType()) + data().StructuralIfLiteral = false; } // C++14 [meta.unary.prop]p4: @@ -1383,8 +1419,8 @@ void CXXRecordDecl::finishedDefaultedOrDeletedMember(CXXMethodDecl *D) { data().DeclaredNonTrivialSpecialMembers |= SMKind; } -void CXXRecordDecl::setCaptures(ArrayRef Captures) { - ASTContext &Context = getASTContext(); +void CXXRecordDecl::setCaptures(ASTContext &Context, + ArrayRef Captures) { CXXRecordDecl::LambdaDefinitionData &Data = getLambdaData(); // Copy captures. @@ -1475,18 +1511,38 @@ CXXMethodDecl *CXXRecordDecl::getLambdaCallOperator() const { } CXXMethodDecl* CXXRecordDecl::getLambdaStaticInvoker() const { - if (!isLambda()) return nullptr; + CXXMethodDecl *CallOp = getLambdaCallOperator(); + CallingConv CC = CallOp->getType()->castAs()->getCallConv(); + return getLambdaStaticInvoker(CC); +} + +static DeclContext::lookup_result +getLambdaStaticInvokers(const CXXRecordDecl &RD) { + assert(RD.isLambda() && "Must be a lambda"); DeclarationName Name = - &getASTContext().Idents.get(getLambdaStaticInvokerName()); - DeclContext::lookup_result Invoker = lookup(Name); - if (Invoker.empty()) return nullptr; - assert(allLookupResultsAreTheSame(Invoker) && - "More than one static invoker operator!"); - NamedDecl *InvokerFun = Invoker.front(); - if (const auto *InvokerTemplate = dyn_cast(InvokerFun)) + &RD.getASTContext().Idents.get(getLambdaStaticInvokerName()); + return RD.lookup(Name); +} + +static CXXMethodDecl *getInvokerAsMethod(NamedDecl *ND) { + if (const auto *InvokerTemplate = dyn_cast(ND)) return cast(InvokerTemplate->getTemplatedDecl()); + return cast(ND); +} + +CXXMethodDecl *CXXRecordDecl::getLambdaStaticInvoker(CallingConv CC) const { + if (!isLambda()) + return nullptr; + DeclContext::lookup_result Invoker = getLambdaStaticInvokers(*this); + + for (NamedDecl *ND : Invoker) { + const auto *FTy = + cast(ND->getAsFunction())->getType()->castAs(); + if (FTy->getCallConv() == CC) + return getInvokerAsMethod(ND); + } - return cast(InvokerFun); + return nullptr; } void CXXRecordDecl::getCaptureFields( @@ -2135,10 +2191,10 @@ CXXMethodDecl *CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD, } CXXMethodDecl *CXXMethodDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - return new (C, ID) CXXMethodDecl( - CXXMethod, C, nullptr, SourceLocation(), DeclarationNameInfo(), - QualType(), nullptr, SC_None, false, CSK_unspecified, SourceLocation(), - nullptr); + return new (C, ID) + CXXMethodDecl(CXXMethod, C, nullptr, SourceLocation(), + DeclarationNameInfo(), QualType(), nullptr, SC_None, false, + ConstexprSpecKind::Unspecified, SourceLocation(), nullptr); } CXXMethodDecl *CXXMethodDecl::getDevirtualizedMethod(const Expr *Base, @@ -2427,14 +2483,8 @@ bool CXXMethodDecl::hasInlineBody() const { bool CXXMethodDecl::isLambdaStaticInvoker() const { const CXXRecordDecl *P = getParent(); - if (P->isLambda()) { - if (const CXXMethodDecl *StaticInvoker = P->getLambdaStaticInvoker()) { - if (StaticInvoker == this) return true; - if (P->isGenericLambda() && this->isFunctionTemplateSpecialization()) - return StaticInvoker == this->getPrimaryTemplate()->getTemplatedDecl(); - } - } - return false; + return P->isLambda() && getDeclName().isIdentifier() && + getName() == getLambdaStaticInvokerName(); } CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context, @@ -2543,10 +2593,10 @@ CXXConstructorDecl *CXXConstructorDecl::CreateDeserialized(ASTContext &C, unsigned Extra = additionalSizeToAlloc( isInheritingConstructor, hasTraillingExplicit); - auto *Result = new (C, ID, Extra) - CXXConstructorDecl(C, nullptr, SourceLocation(), DeclarationNameInfo(), - QualType(), nullptr, ExplicitSpecifier(), false, false, - CSK_unspecified, InheritedConstructor(), nullptr); + auto *Result = new (C, ID, Extra) CXXConstructorDecl( + C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(), nullptr, + ExplicitSpecifier(), false, false, ConstexprSpecKind::Unspecified, + InheritedConstructor(), nullptr); Result->setInheritingConstructor(isInheritingConstructor); Result->CXXConstructorDeclBits.HasTrailingExplicitSpecifier = hasTraillingExplicit; @@ -2684,10 +2734,9 @@ void CXXDestructorDecl::anchor() {} CXXDestructorDecl * CXXDestructorDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - return new (C, ID) - CXXDestructorDecl(C, nullptr, SourceLocation(), DeclarationNameInfo(), - QualType(), nullptr, false, false, CSK_unspecified, - nullptr); + return new (C, ID) CXXDestructorDecl( + C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(), nullptr, + false, false, ConstexprSpecKind::Unspecified, nullptr); } CXXDestructorDecl *CXXDestructorDecl::Create( @@ -2720,7 +2769,8 @@ CXXConversionDecl * CXXConversionDecl::CreateDeserialized(ASTContext &C, unsigned ID) { return new (C, ID) CXXConversionDecl( C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(), nullptr, - false, ExplicitSpecifier(), CSK_unspecified, SourceLocation(), nullptr); + false, ExplicitSpecifier(), ConstexprSpecKind::Unspecified, + SourceLocation(), nullptr); } CXXConversionDecl *CXXConversionDecl::Create( @@ -3301,12 +3351,7 @@ static const char *getAccessName(AccessSpecifier AS) { llvm_unreachable("Invalid access specifier!"); } -const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, - AccessSpecifier AS) { - return DB << getAccessName(AS); -} - -const PartialDiagnostic &clang::operator<<(const PartialDiagnostic &DB, - AccessSpecifier AS) { +const StreamingDiagnostic &clang::operator<<(const StreamingDiagnostic &DB, + AccessSpecifier AS) { return DB << getAccessName(AS); } diff --git a/clang/lib/AST/DeclObjC.cpp b/clang/lib/AST/DeclObjC.cpp index 5c8b34731f36..5f82fcec90e3 100644 --- a/clang/lib/AST/DeclObjC.cpp +++ b/clang/lib/AST/DeclObjC.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include using namespace clang; @@ -949,7 +950,8 @@ ObjCMethodDecl *ObjCMethodDecl::getNextRedeclarationImpl() { if (!Redecl && isRedeclaration()) { // This is the last redeclaration, go back to the first method. return cast(CtxD)->getMethod(getSelector(), - isInstanceMethod()); + isInstanceMethod(), + /*AllowHidden=*/true); } return Redecl ? Redecl : this; @@ -982,7 +984,8 @@ ObjCMethodDecl *ObjCMethodDecl::getCanonicalDecl() { if (isRedeclaration()) { // It is possible that we have not done deserializing the ObjCMethod yet. ObjCMethodDecl *MD = - cast(CtxD)->getMethod(Sel, isInstanceMethod()); + cast(CtxD)->getMethod(Sel, isInstanceMethod(), + /*AllowHidden=*/true); return MD ? MD : this; } @@ -1165,6 +1168,14 @@ ObjCInterfaceDecl *ObjCMethodDecl::getClassInterface() { llvm_unreachable("unknown method context"); } +ObjCCategoryDecl *ObjCMethodDecl::getCategory() { + if (auto *CD = dyn_cast(getDeclContext())) + return CD; + if (auto *IMD = dyn_cast(getDeclContext())) + return IMD->getCategoryDecl(); + return nullptr; +} + SourceRange ObjCMethodDecl::getReturnTypeSourceRange() const { const auto *TSI = getReturnTypeSourceInfo(); if (TSI) @@ -1299,8 +1310,9 @@ void ObjCMethodDecl::getOverriddenMethods( const ObjCMethodDecl *Method = this; if (Method->isRedeclaration()) { - Method = cast(Method->getDeclContext())-> - getMethod(Method->getSelector(), Method->isInstanceMethod()); + Method = cast(Method->getDeclContext()) + ->getMethod(Method->getSelector(), Method->isInstanceMethod(), + /*AllowHidden=*/true); } if (Method->isOverriding()) { @@ -1449,9 +1461,7 @@ SourceRange ObjCTypeParamDecl::getSourceRange() const { ObjCTypeParamList::ObjCTypeParamList(SourceLocation lAngleLoc, ArrayRef typeParams, SourceLocation rAngleLoc) - : NumParams(typeParams.size()) { - Brackets.Begin = lAngleLoc.getRawEncoding(); - Brackets.End = rAngleLoc.getRawEncoding(); + : Brackets(lAngleLoc, rAngleLoc), NumParams(typeParams.size()) { std::copy(typeParams.begin(), typeParams.end(), begin()); } @@ -1897,6 +1907,27 @@ ObjCProtocolDecl *ObjCProtocolDecl::CreateDeserialized(ASTContext &C, return Result; } +bool ObjCProtocolDecl::isNonRuntimeProtocol() const { + return hasAttr(); +} + +void ObjCProtocolDecl::getImpliedProtocols( + llvm::DenseSet &IPs) const { + std::queue WorkQueue; + WorkQueue.push(this); + + while (!WorkQueue.empty()) { + const auto *PD = WorkQueue.front(); + WorkQueue.pop(); + for (const auto *Parent : PD->protocols()) { + const auto *Can = Parent->getCanonicalDecl(); + auto Result = IPs.insert(Can); + if (Result.second) + WorkQueue.push(Parent); + } + } +} + ObjCProtocolDecl *ObjCProtocolDecl::lookupProtocolNamed(IdentifierInfo *Name) { ObjCProtocolDecl *PDecl = this; diff --git a/clang/lib/AST/DeclOpenMP.cpp b/clang/lib/AST/DeclOpenMP.cpp index af321280d417..867ef31656f7 100644 --- a/clang/lib/AST/DeclOpenMP.cpp +++ b/clang/lib/AST/DeclOpenMP.cpp @@ -23,16 +23,14 @@ using namespace clang; // OMPThreadPrivateDecl Implementation. //===----------------------------------------------------------------------===// -void OMPThreadPrivateDecl::anchor() { } +void OMPThreadPrivateDecl::anchor() {} OMPThreadPrivateDecl *OMPThreadPrivateDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef VL) { - OMPThreadPrivateDecl *D = - new (C, DC, additionalSizeToAlloc(VL.size())) - OMPThreadPrivateDecl(OMPThreadPrivate, DC, L); - D->NumVars = VL.size(); + auto *D = OMPDeclarativeDirective::createDirective( + C, DC, llvm::None, VL.size(), L); D->setVars(VL); return D; } @@ -40,16 +38,14 @@ OMPThreadPrivateDecl *OMPThreadPrivateDecl::Create(ASTContext &C, OMPThreadPrivateDecl *OMPThreadPrivateDecl::CreateDeserialized(ASTContext &C, unsigned ID, unsigned N) { - OMPThreadPrivateDecl *D = new (C, ID, additionalSizeToAlloc(N)) - OMPThreadPrivateDecl(OMPThreadPrivate, nullptr, SourceLocation()); - D->NumVars = N; - return D; + return OMPDeclarativeDirective::createEmptyDirective( + C, ID, 0, N); } void OMPThreadPrivateDecl::setVars(ArrayRef VL) { - assert(VL.size() == NumVars && + assert(VL.size() == Data->getNumChildren() && "Number of variables is not the same as the preallocated buffer"); - std::uninitialized_copy(VL.begin(), VL.end(), getTrailingObjects()); + llvm::copy(VL, getVars().begin()); } //===----------------------------------------------------------------------===// @@ -61,38 +57,23 @@ void OMPAllocateDecl::anchor() { } OMPAllocateDecl *OMPAllocateDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef VL, ArrayRef CL) { - OMPAllocateDecl *D = new ( - C, DC, additionalSizeToAlloc(VL.size(), CL.size())) - OMPAllocateDecl(OMPAllocate, DC, L); - D->NumVars = VL.size(); + auto *D = OMPDeclarativeDirective::createDirective( + C, DC, CL, VL.size(), L); D->setVars(VL); - D->NumClauses = CL.size(); - D->setClauses(CL); return D; } OMPAllocateDecl *OMPAllocateDecl::CreateDeserialized(ASTContext &C, unsigned ID, unsigned NVars, unsigned NClauses) { - OMPAllocateDecl *D = - new (C, ID, additionalSizeToAlloc(NVars, NClauses)) - OMPAllocateDecl(OMPAllocate, nullptr, SourceLocation()); - D->NumVars = NVars; - D->NumClauses = NClauses; - return D; + return OMPDeclarativeDirective::createEmptyDirective( + C, ID, NClauses, NVars, SourceLocation()); } void OMPAllocateDecl::setVars(ArrayRef VL) { - assert(VL.size() == NumVars && + assert(VL.size() == Data->getNumChildren() && "Number of variables is not the same as the preallocated buffer"); - std::uninitialized_copy(VL.begin(), VL.end(), getTrailingObjects()); -} - -void OMPAllocateDecl::setClauses(ArrayRef CL) { - assert(CL.size() == NumClauses && - "Number of variables is not the same as the preallocated buffer"); - std::uninitialized_copy(CL.begin(), CL.end(), - getTrailingObjects()); + llvm::copy(VL, getVars().begin()); } //===----------------------------------------------------------------------===// @@ -104,27 +85,14 @@ void OMPRequiresDecl::anchor() {} OMPRequiresDecl *OMPRequiresDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef CL) { - OMPRequiresDecl *D = - new (C, DC, additionalSizeToAlloc(CL.size())) - OMPRequiresDecl(OMPRequires, DC, L); - D->NumClauses = CL.size(); - D->setClauses(CL); - return D; + return OMPDeclarativeDirective::createDirective(C, DC, CL, 0, + L); } OMPRequiresDecl *OMPRequiresDecl::CreateDeserialized(ASTContext &C, unsigned ID, unsigned N) { - OMPRequiresDecl *D = new (C, ID, additionalSizeToAlloc(N)) - OMPRequiresDecl(OMPRequires, nullptr, SourceLocation()); - D->NumClauses = N; - return D; -} - -void OMPRequiresDecl::setClauses(ArrayRef CL) { - assert(CL.size() == NumClauses && - "Number of clauses is not the same as the preallocated buffer"); - std::uninitialized_copy(CL.begin(), CL.end(), - getTrailingObjects()); + return OMPDeclarativeDirective::createEmptyDirective( + C, ID, N, 0, SourceLocation()); } //===----------------------------------------------------------------------===// @@ -171,48 +139,20 @@ OMPDeclareReductionDecl::getPrevDeclInScope() const { void OMPDeclareMapperDecl::anchor() {} -OMPDeclareMapperDecl * -OMPDeclareMapperDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, - DeclarationName Name, QualType T, - DeclarationName VarName, - OMPDeclareMapperDecl *PrevDeclInScope) { - return new (C, DC) OMPDeclareMapperDecl(OMPDeclareMapper, DC, L, Name, T, - VarName, PrevDeclInScope); +OMPDeclareMapperDecl *OMPDeclareMapperDecl::Create( + ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, + QualType T, DeclarationName VarName, ArrayRef Clauses, + OMPDeclareMapperDecl *PrevDeclInScope) { + return OMPDeclarativeDirective::createDirective( + C, DC, Clauses, 1, L, Name, T, VarName, PrevDeclInScope); } OMPDeclareMapperDecl *OMPDeclareMapperDecl::CreateDeserialized(ASTContext &C, unsigned ID, unsigned N) { - auto *D = new (C, ID) - OMPDeclareMapperDecl(OMPDeclareMapper, /*DC=*/nullptr, SourceLocation(), - DeclarationName(), QualType(), DeclarationName(), - /*PrevDeclInScope=*/nullptr); - if (N) { - auto **ClauseStorage = C.Allocate(N); - D->Clauses = llvm::makeMutableArrayRef(ClauseStorage, N); - } - return D; -} - -/// Creates an array of clauses to this mapper declaration and intializes -/// them. The space used to store clause pointers is dynamically allocated, -/// because we do not know the number of clauses when creating -/// OMPDeclareMapperDecl -void OMPDeclareMapperDecl::CreateClauses(ASTContext &C, - ArrayRef CL) { - assert(Clauses.empty() && "Number of clauses should be 0 on initialization"); - size_t NumClauses = CL.size(); - if (NumClauses) { - auto **ClauseStorage = C.Allocate(NumClauses); - Clauses = llvm::makeMutableArrayRef(ClauseStorage, NumClauses); - setClauses(CL); - } -} - -void OMPDeclareMapperDecl::setClauses(ArrayRef CL) { - assert(CL.size() == Clauses.size() && - "Number of clauses is not the same as the preallocated buffer"); - std::uninitialized_copy(CL.begin(), CL.end(), Clauses.data()); + return OMPDeclarativeDirective::createEmptyDirective( + C, ID, N, 1, SourceLocation(), DeclarationName(), QualType(), + DeclarationName(), /*PrevDeclInScope=*/nullptr); } OMPDeclareMapperDecl *OMPDeclareMapperDecl::getPrevDeclInScope() { diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp index 2e48b2b46c4d..ca64f8f6cfbe 100644 --- a/clang/lib/AST/DeclPrinter.cpp +++ b/clang/lib/AST/DeclPrinter.cpp @@ -528,7 +528,8 @@ void DeclPrinter::VisitEnumDecl(EnumDecl *D) { prettyPrintAttributes(D); - Out << ' ' << *D; + if (D->getDeclName()) + Out << ' ' << D->getDeclName(); if (D->isFixed()) Out << " : " << D->getIntegerType().stream(Policy); @@ -933,7 +934,12 @@ void DeclPrinter::VisitStaticAssertDecl(StaticAssertDecl *D) { void DeclPrinter::VisitNamespaceDecl(NamespaceDecl *D) { if (D->isInline()) Out << "inline "; - Out << "namespace " << *D << " {\n"; + + Out << "namespace "; + if (D->getDeclName()) + Out << D->getDeclName() << ' '; + Out << "{\n"; + VisitDeclContext(D); Indent() << "}"; } @@ -1091,10 +1097,15 @@ void DeclPrinter::VisitTemplateDecl(const TemplateDecl *D) { if (const TemplateTemplateParmDecl *TTP = dyn_cast(D)) { - Out << "class "; + Out << "class"; + if (TTP->isParameterPack()) - Out << "..."; - Out << D->getName(); + Out << " ..."; + else if (TTP->getDeclName()) + Out << ' '; + + if (TTP->getDeclName()) + Out << TTP->getDeclName(); } else if (auto *TD = D->getTemplatedDecl()) Visit(TD); else if (const auto *Concept = dyn_cast(D)) { @@ -1216,7 +1227,7 @@ void DeclPrinter::PrintObjCTypeParams(ObjCTypeParamList *Params) { break; } - Out << Param->getDeclName().getAsString(); + Out << Param->getDeclName(); if (Param->hasExplicitBound()) { Out << " : " << Param->getUnderlyingType().getAsString(Policy); @@ -1695,10 +1706,11 @@ void DeclPrinter::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *TTP) { if (TTP->isParameterPack()) Out << " ..."; - else if (!TTP->getName().empty()) + else if (TTP->getDeclName()) Out << ' '; - Out << *TTP; + if (TTP->getDeclName()) + Out << TTP->getDeclName(); if (TTP->hasDefaultArgument()) { Out << " = "; diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp index 7857e75f57a1..25235c56ec46 100644 --- a/clang/lib/AST/DeclTemplate.cpp +++ b/clang/lib/AST/DeclTemplate.cpp @@ -102,24 +102,10 @@ unsigned TemplateParameterList::getMinRequiredArguments() const { unsigned NumRequiredArgs = 0; for (const NamedDecl *P : asArray()) { if (P->isTemplateParameterPack()) { - if (const auto *NTTP = dyn_cast(P)) { - if (NTTP->isExpandedParameterPack()) { - NumRequiredArgs += NTTP->getNumExpansionTypes(); - continue; - } - } else if (const auto *TTP = dyn_cast(P)) { - if (TTP->isExpandedParameterPack()) { - NumRequiredArgs += TTP->getNumExpansionParameters(); - continue; - } - } else { - const auto *TP = cast(P); - if (TP->isExpandedParameterPack()) { - NumRequiredArgs += TP->getNumExpansionTemplateParameters(); - continue; - } + if (Optional Expansions = getExpandedPackSize(P)) { + NumRequiredArgs += *Expansions; + continue; } - break; } @@ -440,7 +426,7 @@ ClassTemplateDecl::getSpecializations() const { } llvm::FoldingSetVector & -ClassTemplateDecl::getPartialSpecializations() { +ClassTemplateDecl::getPartialSpecializations() const { LoadLazySpecializations(); return getCommonPtr()->PartialSpecializations; } @@ -528,7 +514,7 @@ void ClassTemplateDecl::AddPartialSpecialization( } void ClassTemplateDecl::getPartialSpecializations( - SmallVectorImpl &PS) { + SmallVectorImpl &PS) const { llvm::FoldingSetVector &PartialSpecs = getPartialSpecializations(); PS.clear(); @@ -914,10 +900,14 @@ void ClassTemplateSpecializationDecl::getNameForDiagnostic( const auto *PS = dyn_cast(this); if (const ASTTemplateArgumentListInfo *ArgsAsWritten = PS ? PS->getTemplateArgsAsWritten() : nullptr) { - printTemplateArgumentList(OS, ArgsAsWritten->arguments(), Policy); + printTemplateArgumentList( + OS, ArgsAsWritten->arguments(), Policy, + getSpecializedTemplate()->getTemplateParameters()); } else { const TemplateArgumentList &TemplateArgs = getTemplateArgs(); - printTemplateArgumentList(OS, TemplateArgs.asArray(), Policy); + printTemplateArgumentList( + OS, TemplateArgs.asArray(), Policy, + getSpecializedTemplate()->getTemplateParameters()); } } @@ -1142,7 +1132,7 @@ VarTemplateDecl::getSpecializations() const { } llvm::FoldingSetVector & -VarTemplateDecl::getPartialSpecializations() { +VarTemplateDecl::getPartialSpecializations() const { LoadLazySpecializations(); return getCommonPtr()->PartialSpecializations; } @@ -1198,7 +1188,7 @@ void VarTemplateDecl::AddPartialSpecialization( } void VarTemplateDecl::getPartialSpecializations( - SmallVectorImpl &PS) { + SmallVectorImpl &PS) const { llvm::FoldingSetVector &PartialSpecs = getPartialSpecializations(); PS.clear(); @@ -1261,10 +1251,14 @@ void VarTemplateSpecializationDecl::getNameForDiagnostic( const auto *PS = dyn_cast(this); if (const ASTTemplateArgumentListInfo *ArgsAsWritten = PS ? PS->getTemplateArgsAsWritten() : nullptr) { - printTemplateArgumentList(OS, ArgsAsWritten->arguments(), Policy); + printTemplateArgumentList( + OS, ArgsAsWritten->arguments(), Policy, + getSpecializedTemplate()->getTemplateParameters()); } else { const TemplateArgumentList &TemplateArgs = getTemplateArgs(); - printTemplateArgumentList(OS, TemplateArgs.asArray(), Policy); + printTemplateArgumentList( + OS, TemplateArgs.asArray(), Policy, + getSpecializedTemplate()->getTemplateParameters()); } } @@ -1431,3 +1425,36 @@ void TypeConstraint::print(llvm::raw_ostream &OS, PrintingPolicy Policy) const { OS << ">"; } } + +TemplateParamObjectDecl *TemplateParamObjectDecl::Create(const ASTContext &C, + QualType T, + const APValue &V) { + DeclContext *DC = C.getTranslationUnitDecl(); + auto *TPOD = new (C, DC) TemplateParamObjectDecl(DC, T, V); + C.addDestruction(&TPOD->Value); + return TPOD; +} + +TemplateParamObjectDecl * +TemplateParamObjectDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + auto *TPOD = new (C, ID) TemplateParamObjectDecl(nullptr, QualType(), APValue()); + C.addDestruction(&TPOD->Value); + return TPOD; +} + +void TemplateParamObjectDecl::printName(llvm::raw_ostream &OS) const { + OS << "