summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--contrib/llvm/include/llvm/ADT/APInt.h6
-rw-r--r--contrib/llvm/include/llvm/ADT/ArrayRef.h5
-rw-r--r--contrib/llvm/include/llvm/ADT/ImmutableIntervalMap.h2
-rw-r--r--contrib/llvm/include/llvm/ADT/ImmutableMap.h2
-rw-r--r--contrib/llvm/include/llvm/Analysis/DIBuilder.h154
-rw-r--r--contrib/llvm/include/llvm/CodeGen/AsmPrinter.h3
-rw-r--r--contrib/llvm/include/llvm/CodeGen/FunctionLoweringInfo.h63
-rw-r--r--contrib/llvm/include/llvm/CodeGen/MachineConstantPool.h3
-rw-r--r--contrib/llvm/include/llvm/CodeGen/MachineFunction.h2
-rw-r--r--contrib/llvm/include/llvm/CodeGen/MachineRegisterInfo.h14
-rw-r--r--contrib/llvm/include/llvm/IntrinsicsXCore.td19
-rw-r--r--contrib/llvm/include/llvm/MC/MCAsmInfo.h8
-rw-r--r--contrib/llvm/include/llvm/MC/MCParser/MCAsmParserExtension.h4
-rw-r--r--contrib/llvm/include/llvm/MC/MCStreamer.h37
-rw-r--r--contrib/llvm/include/llvm/Support/NoFolder.h72
-rw-r--r--contrib/llvm/include/llvm/Support/PathV1.h6
-rw-r--r--contrib/llvm/include/llvm/Target/TargetLowering.h96
-rw-r--r--contrib/llvm/include/llvm/Transforms/Utils/Local.h2
-rw-r--r--contrib/llvm/lib/Analysis/DIBuilder.cpp154
-rw-r--r--contrib/llvm/lib/Analysis/InstructionSimplify.cpp10
-rw-r--r--contrib/llvm/lib/CodeGen/AllocationOrder.h2
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp10
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp9
-rw-r--r--contrib/llvm/lib/CodeGen/BranchFolding.cpp6
-rw-r--r--contrib/llvm/lib/CodeGen/InlineSpiller.cpp20
-rw-r--r--contrib/llvm/lib/CodeGen/LowerSubregs.cpp10
-rw-r--r--contrib/llvm/lib/CodeGen/MachineFunction.cpp12
-rw-r--r--contrib/llvm/lib/CodeGen/MachineRegisterInfo.cpp9
-rw-r--r--contrib/llvm/lib/CodeGen/RegAllocBase.h15
-rw-r--r--contrib/llvm/lib/CodeGen/RegAllocBasic.cpp60
-rw-r--r--contrib/llvm/lib/CodeGen/RegAllocGreedy.cpp197
-rw-r--r--contrib/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp133
-rw-r--r--contrib/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp118
-rw-r--r--contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp49
-rw-r--r--contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp10
-rw-r--r--contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp19
-rw-r--r--contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp31
-rw-r--r--contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h2
-rw-r--r--contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp55
-rw-r--r--contrib/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp26
-rw-r--r--contrib/llvm/lib/CodeGen/SplitKit.cpp18
-rw-r--r--contrib/llvm/lib/CodeGen/SplitKit.h7
-rw-r--r--contrib/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp30
-rw-r--r--contrib/llvm/lib/CodeGen/VirtRegRewriter.cpp6
-rw-r--r--contrib/llvm/lib/MC/ELFObjectWriter.cpp10
-rw-r--r--contrib/llvm/lib/MC/MCAsmInfo.cpp1
-rw-r--r--contrib/llvm/lib/MC/MCAsmInfoDarwin.cpp1
-rw-r--r--contrib/llvm/lib/MC/MCDisassembler/EDOperand.cpp20
-rw-r--r--contrib/llvm/lib/MC/MCDisassembler/EDToken.cpp4
-rw-r--r--contrib/llvm/lib/MC/MCObjectStreamer.cpp18
-rw-r--r--contrib/llvm/lib/MC/MCParser/AsmParser.cpp2
-rw-r--r--contrib/llvm/lib/MC/MCParser/ELFAsmParser.cpp12
-rw-r--r--contrib/llvm/lib/MC/MCParser/MCAsmParserExtension.cpp3
-rw-r--r--contrib/llvm/lib/MC/MCSectionMachO.cpp17
-rw-r--r--contrib/llvm/lib/MC/MCStreamer.cpp4
-rw-r--r--contrib/llvm/lib/Support/APInt.cpp2
-rw-r--r--contrib/llvm/lib/Target/ARM/ARMBaseInstrInfo.h3
-rw-r--r--contrib/llvm/lib/Target/ARM/ARMFastISel.cpp38
-rw-r--r--contrib/llvm/lib/Target/ARM/ARMFrameLowering.cpp16
-rw-r--r--contrib/llvm/lib/Target/ARM/ARMHazardRecognizer.cpp17
-rw-r--r--contrib/llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp15
-rw-r--r--contrib/llvm/lib/Target/ARM/ARMISelLowering.cpp102
-rw-r--r--contrib/llvm/lib/Target/ARM/ARMInstrFormats.td7
-rw-r--r--contrib/llvm/lib/Target/ARM/ARMInstrInfo.td4
-rw-r--r--contrib/llvm/lib/Target/ARM/ARMInstrNEON.td31
-rw-r--r--contrib/llvm/lib/Target/ARM/ARMInstrVFP.td162
-rw-r--r--contrib/llvm/lib/Target/ARM/ARMSubtarget.cpp4
-rw-r--r--contrib/llvm/lib/Target/ARM/MLxExpansionPass.cpp20
-rw-r--r--contrib/llvm/lib/Target/ARM/NEONMoveFix.cpp9
-rw-r--r--contrib/llvm/lib/Target/ARM/Thumb2InstrInfo.cpp6
-rw-r--r--contrib/llvm/lib/Target/Alpha/AlphaISelLowering.cpp1
-rw-r--r--contrib/llvm/lib/Target/Alpha/AlphaISelLowering.h14
-rw-r--r--contrib/llvm/lib/Target/Blackfin/BlackfinISelLowering.cpp1
-rw-r--r--contrib/llvm/lib/Target/Blackfin/BlackfinISelLowering.h1
-rw-r--r--contrib/llvm/lib/Target/CellSPU/SPUISelLowering.cpp7
-rw-r--r--contrib/llvm/lib/Target/CellSPU/SPUISelLowering.h6
-rw-r--r--contrib/llvm/lib/Target/MBlaze/MBlazeISelLowering.cpp4
-rw-r--r--contrib/llvm/lib/Target/MSP430/MSP430ISelLowering.cpp6
-rw-r--r--contrib/llvm/lib/Target/MSP430/MSP430ISelLowering.h2
-rw-r--r--contrib/llvm/lib/Target/PowerPC/PPCISelLowering.cpp25
-rw-r--r--contrib/llvm/lib/Target/PowerPC/PPCISelLowering.h94
-rw-r--r--contrib/llvm/lib/Target/Sparc/DelaySlotFiller.cpp31
-rw-r--r--contrib/llvm/lib/Target/Sparc/SparcISelLowering.cpp43
-rw-r--r--contrib/llvm/lib/Target/Sparc/SparcISelLowering.h2
-rw-r--r--contrib/llvm/lib/Target/Sparc/SparcInstrInfo.td18
-rw-r--r--contrib/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp3
-rw-r--r--contrib/llvm/lib/Target/SystemZ/SystemZISelLowering.h2
-rw-r--r--contrib/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp13
-rw-r--r--contrib/llvm/lib/Target/X86/Disassembler/X86Disassembler.cpp8
-rw-r--r--contrib/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h2
-rw-r--r--contrib/llvm/lib/Target/X86/X86FastISel.cpp8
-rw-r--r--contrib/llvm/lib/Target/X86/X86ISelLowering.cpp50
-rw-r--r--contrib/llvm/lib/Target/X86/X86ISelLowering.h18
-rw-r--r--contrib/llvm/lib/Target/X86/X86InstrFormats.td2
-rw-r--r--contrib/llvm/lib/Target/X86/X86InstrInfo.cpp4
-rw-r--r--contrib/llvm/lib/Target/X86/X86InstrInfo.h4
-rw-r--r--contrib/llvm/lib/Target/X86/X86InstrInfo.td3
-rw-r--r--contrib/llvm/lib/Target/X86/X86InstrSystem.td5
-rw-r--r--contrib/llvm/lib/Target/X86/X86MCCodeEmitter.cpp8
-rw-r--r--contrib/llvm/lib/Target/X86/X86Subtarget.cpp7
-rw-r--r--contrib/llvm/lib/Target/X86/X86Subtarget.h2
-rw-r--r--contrib/llvm/lib/Target/XCore/XCoreISelLowering.cpp125
-rw-r--r--contrib/llvm/lib/Target/XCore/XCoreISelLowering.h23
-rw-r--r--contrib/llvm/lib/Target/XCore/XCoreInstrInfo.td55
-rw-r--r--contrib/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp33
-rw-r--r--contrib/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp20
-rw-r--r--contrib/llvm/lib/Transforms/Scalar/LoopDeletion.cpp23
-rw-r--r--contrib/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp18
-rw-r--r--contrib/llvm/lib/Transforms/Scalar/SimplifyLibCalls.cpp1343
-rw-r--r--contrib/llvm/lib/Transforms/Utils/Local.cpp42
-rw-r--r--contrib/llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp13
-rw-r--r--contrib/llvm/lib/Transforms/Utils/SimplifyCFG.cpp5
-rw-r--r--contrib/llvm/tools/clang/include/clang-c/Index.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ASTContext.h7
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ASTImporter.h9
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/Decl.h84
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclBase.h11
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclCXX.h218
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclGroup.h4
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclTemplate.h17
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/Expr.h4
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ExprCXX.h77
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/NestedNameSpecifier.h163
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/RecursiveASTVisitor.h48
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/Stmt.h3
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h49
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/AnalysisContext.h12
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Builtins.def5
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Builtins.h5
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.h5
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticFrontendKinds.td9
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticGroups.td6
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticIDs.h6
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticParseKinds.td9
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td55
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/LangOptions.h7
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/PartialDiagnostic.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/SourceManager.h8
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/CC1Options.td16
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/Options.td1
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/AnalyzerOptions.h4
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/DeclXML.def2
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/HeaderSearchOptions.h4
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/Utils.h4
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/Preprocessor.h3
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/TokenLexer.h4
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/AnalysisBasedWarnings.h11
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/DeclSpec.h151
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/ExternalSemaSource.h12
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/Initialization.h17
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/ParsedTemplate.h6
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/ScopeInfo.h17
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/Sema.h168
-rw-r--r--contrib/llvm/tools/clang/include/clang/Serialization/ASTReader.h10
-rw-r--r--contrib/llvm/tools/clang/include/clang/Serialization/ASTWriter.h7
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/LocalCheckers.h1
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h14
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h10
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h352
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerProvider.h5
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerV2.h191
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Checker.h160
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h187
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h14
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h4
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h16
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h5
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/FrontendActions.h2
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ASTContext.cpp106
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp48
-rw-r--r--contrib/llvm/tools/clang/lib/AST/Decl.cpp73
-rw-r--r--contrib/llvm/tools/clang/lib/AST/DeclBase.cpp16
-rw-r--r--contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp32
-rw-r--r--contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp6
-rw-r--r--contrib/llvm/tools/clang/lib/AST/Expr.cpp13
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp42
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp10
-rw-r--r--contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp182
-rw-r--r--contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp93
-rw-r--r--contrib/llvm/tools/clang/lib/AST/Stmt.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/AST/StmtDumper.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp18
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/AnalysisContext.cpp28
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/CFG.cpp53
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/CFGReachabilityAnalysis.cpp76
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp11
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp17
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets.cpp1
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.cpp36
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.h1
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp11
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp465
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.h12
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGDecl.cpp386
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGException.cpp16
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp82
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGObjC.cpp25
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGObjCGNU.cpp15
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGObjCMac.cpp11
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp26
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.h50
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.h11
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.cpp11
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp3
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp14
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Tools.cpp10
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp3
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp52
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/DocumentXML.cpp5
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/InitHeaderSearch.cpp107
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/InitPreprocessor.cpp37
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/TextDiagnosticPrinter.cpp14
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/VerifyDiagnosticsClient.cpp8
-rw-r--r--contrib/llvm/tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp6
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp9
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/Pragma.cpp68
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp5
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp49
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp55
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/Parser.cpp8
-rw-r--r--contrib/llvm/tools/clang/lib/Rewrite/RewriteObjC.cpp27
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp78
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp236
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/Sema.cpp29
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp257
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp74
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp75
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp48
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp54
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp70
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp406
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp52
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp304
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp7
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp77
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp104
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp36
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp14
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp11
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp158
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaType.cpp187
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/TreeTransform.h323
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h13
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp128
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp32
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp20
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp71
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp15
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp6
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp32
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp116
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp261
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp31
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp32
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/Checkers.td32
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp43
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ClangSACheckerProvider.cpp56
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExperimentalChecks.cpp11
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExprEngine.cpp105
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp31
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp148
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/InternalChecks.h3
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp35
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp43
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp42
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp123
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp31
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp31
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp39
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp34
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp (renamed from contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StackAddrLeakChecker.cpp)63
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp148
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp50
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp58
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporter.cpp70
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp397
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp7
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Environment.cpp5
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp6
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp18
-rw-r--r--contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp249
-rw-r--r--contrib/llvm/utils/TableGen/AsmWriterEmitter.h1
-rw-r--r--contrib/llvm/utils/TableGen/ClangSACheckersEmitter.cpp1
-rw-r--r--contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp4
-rw-r--r--lib/clang/include/clang/Basic/Version.inc4
-rw-r--r--lib/clang/libclanganalysis/Makefile1
-rw-r--r--lib/clang/libclangstaticanalyzercheckers/Makefile2
292 files changed, 9232 insertions, 4858 deletions
diff --git a/contrib/llvm/include/llvm/ADT/APInt.h b/contrib/llvm/include/llvm/ADT/APInt.h
index b91d5dc..d1fd3e5 100644
--- a/contrib/llvm/include/llvm/ADT/APInt.h
+++ b/contrib/llvm/include/llvm/ADT/APInt.h
@@ -1193,6 +1193,12 @@ public:
/// @brief Count the number of leading one bits.
unsigned countLeadingOnes() const;
+ /// Computes the number of leading bits of this APInt that are equal to its
+ /// sign bit.
+ unsigned getNumSignBits() const {
+ return isNegative() ? countLeadingOnes() : countLeadingZeros();
+ }
+
/// countTrailingZeros - This function is an APInt version of the
/// countTrailingZeros_{32,64} functions in MathExtras.h. It counts
/// the number of zeros from the least significant bit to the first set bit.
diff --git a/contrib/llvm/include/llvm/ADT/ArrayRef.h b/contrib/llvm/include/llvm/ADT/ArrayRef.h
index 1c5470d..d3ea9c0 100644
--- a/contrib/llvm/include/llvm/ADT/ArrayRef.h
+++ b/contrib/llvm/include/llvm/ADT/ArrayRef.h
@@ -64,7 +64,10 @@ namespace llvm {
/*implicit*/ ArrayRef(const std::vector<T> &Vec)
: Data(Vec.empty() ? (T*)0 : &Vec[0]), Length(Vec.size()) {}
- // TODO: C arrays.
+ /// Construct an ArrayRef from a C array.
+ template <size_t N>
+ /*implicit*/ ArrayRef(const T (&Arr)[N])
+ : Data(Arr), Length(N) {}
/// @}
/// @name Simple Operations
diff --git a/contrib/llvm/include/llvm/ADT/ImmutableIntervalMap.h b/contrib/llvm/include/llvm/ADT/ImmutableIntervalMap.h
index d3196ca..0d8fcf3 100644
--- a/contrib/llvm/include/llvm/ADT/ImmutableIntervalMap.h
+++ b/contrib/llvm/include/llvm/ADT/ImmutableIntervalMap.h
@@ -215,7 +215,7 @@ public:
ImmutableIntervalMap add(ImmutableIntervalMap Old,
key_type_ref K, data_type_ref D) {
- TreeTy *T = F.add(Old.Root, std::make_pair<key_type, data_type>(K, D));
+ TreeTy *T = F.add(Old.Root, std::pair<key_type, data_type>(K, D));
return ImmutableIntervalMap(F.getCanonicalTree(T));
}
diff --git a/contrib/llvm/include/llvm/ADT/ImmutableMap.h b/contrib/llvm/include/llvm/ADT/ImmutableMap.h
index e439a09..d6cce7c 100644
--- a/contrib/llvm/include/llvm/ADT/ImmutableMap.h
+++ b/contrib/llvm/include/llvm/ADT/ImmutableMap.h
@@ -108,7 +108,7 @@ public:
ImmutableMap getEmptyMap() { return ImmutableMap(F.getEmptyTree()); }
ImmutableMap add(ImmutableMap Old, key_type_ref K, data_type_ref D) {
- TreeTy *T = F.add(Old.Root, std::make_pair<key_type,data_type>(K,D));
+ TreeTy *T = F.add(Old.Root, std::pair<key_type,data_type>(K,D));
return ImmutableMap(Canonicalize ? F.getCanonicalTree(T): T);
}
diff --git a/contrib/llvm/include/llvm/Analysis/DIBuilder.h b/contrib/llvm/include/llvm/Analysis/DIBuilder.h
index bd22134..417dbc4 100644
--- a/contrib/llvm/include/llvm/Analysis/DIBuilder.h
+++ b/contrib/llvm/include/llvm/Analysis/DIBuilder.h
@@ -58,7 +58,7 @@ namespace llvm {
const MDNode *getCU() { return TheCU; }
enum ComplexAddrKind { OpPlus=1, OpDeref };
- /// CreateCompileUnit - A CompileUnit provides an anchor for all debugging
+ /// createCompileUnit - A CompileUnit provides an anchor for all debugging
/// information generated during this instance of compilation.
/// @param Lang Source programming language, eg. dwarf::DW_LANG_C99
/// @param File File name
@@ -72,67 +72,67 @@ namespace llvm {
/// by a tool analyzing generated debugging information.
/// @param RV This indicates runtime version for languages like
/// Objective-C.
- void CreateCompileUnit(unsigned Lang, StringRef File, StringRef Dir,
+ void createCompileUnit(unsigned Lang, StringRef File, StringRef Dir,
StringRef Producer,
bool isOptimized, StringRef Flags, unsigned RV);
- /// CreateFile - Create a file descriptor to hold debugging information
+ /// createFile - Create a file descriptor to hold debugging information
/// for a file.
- DIFile CreateFile(StringRef Filename, StringRef Directory);
+ DIFile createFile(StringRef Filename, StringRef Directory);
- /// CreateEnumerator - Create a single enumerator value.
- DIEnumerator CreateEnumerator(StringRef Name, uint64_t Val);
+ /// createEnumerator - Create a single enumerator value.
+ DIEnumerator createEnumerator(StringRef Name, uint64_t Val);
- /// CreateBasicType - Create debugging information entry for a basic
+ /// createBasicType - Create debugging information entry for a basic
/// type.
/// @param Name Type name.
/// @param SizeInBits Size of the type.
/// @param AlignInBits Type alignment.
/// @param Encoding DWARF encoding code, e.g. dwarf::DW_ATE_float.
- DIType CreateBasicType(StringRef Name, uint64_t SizeInBits,
+ DIType createBasicType(StringRef Name, uint64_t SizeInBits,
uint64_t AlignInBits, unsigned Encoding);
- /// CreateQualifiedType - Create debugging information entry for a qualified
+ /// createQualifiedType - Create debugging information entry for a qualified
/// type, e.g. 'const int'.
/// @param Tag Tag identifing type, e.g. dwarf::TAG_volatile_type
/// @param FromTy Base Type.
- DIType CreateQualifiedType(unsigned Tag, DIType FromTy);
+ DIType createQualifiedType(unsigned Tag, DIType FromTy);
- /// CreatePointerType - Create debugging information entry for a pointer.
+ /// createPointerType - Create debugging information entry for a pointer.
/// @param PointeeTy Type pointed by this pointer.
/// @param SizeInBits Size.
/// @param AlignInBits Alignment. (optional)
/// @param Name Pointer type name. (optional)
- DIType CreatePointerType(DIType PointeeTy, uint64_t SizeInBits,
+ DIType createPointerType(DIType PointeeTy, uint64_t SizeInBits,
uint64_t AlignInBits = 0,
StringRef Name = StringRef());
- /// CreateReferenceType - Create debugging information entry for a c++
+ /// createReferenceType - Create debugging information entry for a c++
/// style reference.
- DIType CreateReferenceType(DIType RTy);
+ DIType createReferenceType(DIType RTy);
- /// CreateTypedef - Create debugging information entry for a typedef.
+ /// createTypedef - Create debugging information entry for a typedef.
/// @param Ty Original type.
/// @param Name Typedef name.
/// @param File File where this type is defined.
/// @param LineNo Line number.
- DIType CreateTypedef(DIType Ty, StringRef Name, DIFile File,
+ DIType createTypedef(DIType Ty, StringRef Name, DIFile File,
unsigned LineNo);
- /// CreateFriend - Create debugging information entry for a 'friend'.
- DIType CreateFriend(DIType Ty, DIType FriendTy);
+ /// createFriend - Create debugging information entry for a 'friend'.
+ DIType createFriend(DIType Ty, DIType FriendTy);
- /// CreateInheritance - Create debugging information entry to establish
+ /// createInheritance - Create debugging information entry to establish
/// inheritance relationship between two types.
/// @param Ty Original type.
/// @param BaseTy Base type. Ty is inherits from base.
/// @param BaseOffset Base offset.
/// @param Flags Flags to describe inheritance attribute,
/// e.g. private
- DIType CreateInheritance(DIType Ty, DIType BaseTy, uint64_t BaseOffset,
+ DIType createInheritance(DIType Ty, DIType BaseTy, uint64_t BaseOffset,
unsigned Flags);
- /// CreateMemberType - Create debugging information entry for a member.
+ /// createMemberType - Create debugging information entry for a member.
/// @param Name Member name.
/// @param File File where this member is defined.
/// @param LineNo Line number.
@@ -141,12 +141,12 @@ namespace llvm {
/// @param OffsetInBits Member offset.
/// @param Flags Flags to encode member attribute, e.g. private
/// @param Ty Parent type.
- DIType CreateMemberType(StringRef Name, DIFile File,
+ DIType createMemberType(StringRef Name, DIFile File,
unsigned LineNo, uint64_t SizeInBits,
uint64_t AlignInBits, uint64_t OffsetInBits,
unsigned Flags, DIType Ty);
- /// CreateClassType - Create debugging information entry for a class.
+ /// createClassType - Create debugging information entry for a class.
/// @param Scope Scope in which this class is defined.
/// @param Name class name.
/// @param File File where this member is defined.
@@ -161,14 +161,14 @@ namespace llvm {
/// DW_AT_containing_type. See DWARF documentation
/// for more info.
/// @param TemplateParms Template type parameters.
- DIType CreateClassType(DIDescriptor Scope, StringRef Name, DIFile File,
+ DIType createClassType(DIDescriptor Scope, StringRef Name, DIFile File,
unsigned LineNumber, uint64_t SizeInBits,
uint64_t AlignInBits, uint64_t OffsetInBits,
unsigned Flags, DIType DerivedFrom,
DIArray Elements, MDNode *VTableHolder = 0,
MDNode *TemplateParms = 0);
- /// CreateStructType - Create debugging information entry for a struct.
+ /// createStructType - Create debugging information entry for a struct.
/// @param Scope Scope in which this struct is defined.
/// @param Name Struct name.
/// @param File File where this member is defined.
@@ -178,12 +178,12 @@ namespace llvm {
/// @param Flags Flags to encode member attribute, e.g. private
/// @param Elements Struct elements.
/// @param RunTimeLang Optional parameter, Objective-C runtime version.
- DIType CreateStructType(DIDescriptor Scope, StringRef Name, DIFile File,
+ DIType createStructType(DIDescriptor Scope, StringRef Name, DIFile File,
unsigned LineNumber, uint64_t SizeInBits,
uint64_t AlignInBits, unsigned Flags,
DIArray Elements, unsigned RunTimeLang = 0);
- /// CreateUnionType - Create debugging information entry for an union.
+ /// createUnionType - Create debugging information entry for an union.
/// @param Scope Scope in which this union is defined.
/// @param Name Union name.
/// @param File File where this member is defined.
@@ -193,12 +193,12 @@ namespace llvm {
/// @param Flags Flags to encode member attribute, e.g. private
/// @param Elements Union elements.
/// @param RunTimeLang Optional parameter, Objective-C runtime version.
- DIType CreateUnionType(DIDescriptor Scope, StringRef Name, DIFile File,
+ DIType createUnionType(DIDescriptor Scope, StringRef Name, DIFile File,
unsigned LineNumber, uint64_t SizeInBits,
uint64_t AlignInBits, unsigned Flags,
DIArray Elements, unsigned RunTimeLang = 0);
- /// CreateTemplateTypeParameter - Create debugging information for template
+ /// createTemplateTypeParameter - Create debugging information for template
/// type parameter.
/// @param Scope Scope in which this type is defined.
/// @param Name Type parameter name.
@@ -207,11 +207,11 @@ namespace llvm {
/// @param LineNo Line number.
/// @param ColumnNo Column Number.
DITemplateTypeParameter
- CreateTemplateTypeParameter(DIDescriptor Scope, StringRef Name, DIType Ty,
+ createTemplateTypeParameter(DIDescriptor Scope, StringRef Name, DIType Ty,
MDNode *File = 0, unsigned LineNo = 0,
unsigned ColumnNo = 0);
- /// CreateTemplateValueParameter - Create debugging information for template
+ /// createTemplateValueParameter - Create debugging information for template
/// value parameter.
/// @param Scope Scope in which this type is defined.
/// @param Name Value parameter name.
@@ -221,28 +221,28 @@ namespace llvm {
/// @param LineNo Line number.
/// @param ColumnNo Column Number.
DITemplateValueParameter
- CreateTemplateValueParameter(DIDescriptor Scope, StringRef Name, DIType Ty,
+ createTemplateValueParameter(DIDescriptor Scope, StringRef Name, DIType Ty,
uint64_t Value,
MDNode *File = 0, unsigned LineNo = 0,
unsigned ColumnNo = 0);
- /// CreateArrayType - Create debugging information entry for an array.
+ /// createArrayType - Create debugging information entry for an array.
/// @param Size Array size.
/// @param AlignInBits Alignment.
/// @param Ty Element type.
/// @param Subscripts Subscripts.
- DIType CreateArrayType(uint64_t Size, uint64_t AlignInBits,
+ DIType createArrayType(uint64_t Size, uint64_t AlignInBits,
DIType Ty, DIArray Subscripts);
- /// CreateVectorType - Create debugging information entry for a vector type.
+ /// createVectorType - Create debugging information entry for a vector type.
/// @param Size Array size.
/// @param AlignInBits Alignment.
/// @param Ty Element type.
/// @param Subscripts Subscripts.
- DIType CreateVectorType(uint64_t Size, uint64_t AlignInBits,
+ DIType createVectorType(uint64_t Size, uint64_t AlignInBits,
DIType Ty, DIArray Subscripts);
- /// CreateEnumerationType - Create debugging information entry for an
+ /// createEnumerationType - Create debugging information entry for an
/// enumeration.
/// @param Scope Scope in which this enumeration is defined.
/// @param Name Union name.
@@ -251,40 +251,40 @@ namespace llvm {
/// @param SizeInBits Member size.
/// @param AlignInBits Member alignment.
/// @param Elements Enumeration elements.
- DIType CreateEnumerationType(DIDescriptor Scope, StringRef Name,
+ DIType createEnumerationType(DIDescriptor Scope, StringRef Name,
DIFile File, unsigned LineNumber,
uint64_t SizeInBits,
uint64_t AlignInBits, DIArray Elements);
- /// CreateSubroutineType - Create subroutine type.
+ /// createSubroutineType - Create subroutine type.
/// @param File File in which this subroutine is defined.
/// @param ParamterTypes An array of subroutine parameter types. This
/// includes return type at 0th index.
- DIType CreateSubroutineType(DIFile File, DIArray ParameterTypes);
+ DIType createSubroutineType(DIFile File, DIArray ParameterTypes);
- /// CreateArtificialType - Create a new DIType with "artificial" flag set.
- DIType CreateArtificialType(DIType Ty);
+ /// createArtificialType - Create a new DIType with "artificial" flag set.
+ DIType createArtificialType(DIType Ty);
- /// CreateTemporaryType - Create a temporary forward-declared type.
- DIType CreateTemporaryType();
- DIType CreateTemporaryType(DIFile F);
+ /// createTemporaryType - Create a temporary forward-declared type.
+ DIType createTemporaryType();
+ DIType createTemporaryType(DIFile F);
- /// RetainType - Retain DIType in a module even if it is not referenced
+ /// retainType - Retain DIType in a module even if it is not referenced
/// through debug info anchors.
- void RetainType(DIType T);
+ void retainType(DIType T);
- /// CreateUnspecifiedParameter - Create unspeicified type descriptor
+ /// createUnspecifiedParameter - Create unspeicified type descriptor
/// for a subroutine type.
- DIDescriptor CreateUnspecifiedParameter();
+ DIDescriptor createUnspecifiedParameter();
- /// GetOrCreateArray - Get a DIArray, create one if required.
- DIArray GetOrCreateArray(Value *const *Elements, unsigned NumElements);
+ /// getOrCreateArray - Get a DIArray, create one if required.
+ DIArray getOrCreateArray(Value *const *Elements, unsigned NumElements);
- /// GetOrCreateSubrange - Create a descriptor for a value range. This
+ /// getOrCreateSubrange - Create a descriptor for a value range. This
/// implicitly uniques the values returned.
- DISubrange GetOrCreateSubrange(int64_t Lo, int64_t Hi);
+ DISubrange getOrCreateSubrange(int64_t Lo, int64_t Hi);
- /// CreateGlobalVariable - Create a new descriptor for the specified global.
+ /// createGlobalVariable - Create a new descriptor for the specified global.
/// @param Name Name of the variable.
/// @param File File where this variable is defined.
/// @param LineNo Line number.
@@ -293,11 +293,11 @@ namespace llvm {
/// externally visible or not.
/// @param Val llvm::Value of the variable.
DIGlobalVariable
- CreateGlobalVariable(StringRef Name, DIFile File, unsigned LineNo,
+ createGlobalVariable(StringRef Name, DIFile File, unsigned LineNo,
DIType Ty, bool isLocalToUnit, llvm::Value *Val);
- /// CreateStaticVariable - Create a new descriptor for the specified
+ /// createStaticVariable - Create a new descriptor for the specified
/// variable.
/// @param Conext Variable scope.
/// @param Name Name of the variable.
@@ -309,12 +309,12 @@ namespace llvm {
/// externally visible or not.
/// @param Val llvm::Value of the variable.
DIGlobalVariable
- CreateStaticVariable(DIDescriptor Context, StringRef Name,
+ createStaticVariable(DIDescriptor Context, StringRef Name,
StringRef LinkageName, DIFile File, unsigned LineNo,
DIType Ty, bool isLocalToUnit, llvm::Value *Val);
- /// CreateLocalVariable - Create a new descriptor for the specified
+ /// createLocalVariable - Create a new descriptor for the specified
/// local variable.
/// @param Tag Dwarf TAG. Usually DW_TAG_auto_variable or
/// DW_TAG_arg_variable.
@@ -326,14 +326,14 @@ namespace llvm {
/// @param AlwaysPreserve Boolean. Set to true if debug info for this
/// variable should be preserved in optimized build.
/// @param Flags Flags, e.g. artificial variable.
- DIVariable CreateLocalVariable(unsigned Tag, DIDescriptor Scope,
+ DIVariable createLocalVariable(unsigned Tag, DIDescriptor Scope,
StringRef Name,
DIFile File, unsigned LineNo,
DIType Ty, bool AlwaysPreserve = false,
unsigned Flags = 0);
- /// CreateComplexVariable - Create a new descriptor for the specified
+ /// createComplexVariable - Create a new descriptor for the specified
/// variable which has a complex address expression for its address.
/// @param Tag Dwarf TAG. Usually DW_TAG_auto_variable or
/// DW_TAG_arg_variable.
@@ -344,12 +344,12 @@ namespace llvm {
/// @param Ty Variable Type
/// @param Addr A pointer to a vector of complex address operations.
/// @param NumAddr Num of address operations in the vector.
- DIVariable CreateComplexVariable(unsigned Tag, DIDescriptor Scope,
+ DIVariable createComplexVariable(unsigned Tag, DIDescriptor Scope,
StringRef Name, DIFile F, unsigned LineNo,
DIType Ty, Value *const *Addr,
unsigned NumAddr);
- /// CreateFunction - Create a new descriptor for the specified subprogram.
+ /// createFunction - Create a new descriptor for the specified subprogram.
/// See comments in DISubprogram for descriptions of these fields.
/// @param Scope Function scope.
/// @param Name Function name.
@@ -363,7 +363,7 @@ namespace llvm {
/// This flags are used to emit dwarf attributes.
/// @param isOptimized True if optimization is ON.
/// @param Fn llvm::Function pointer.
- DISubprogram CreateFunction(DIDescriptor Scope, StringRef Name,
+ DISubprogram createFunction(DIDescriptor Scope, StringRef Name,
StringRef LinkageName,
DIFile File, unsigned LineNo,
DIType Ty, bool isLocalToUnit,
@@ -372,7 +372,7 @@ namespace llvm {
bool isOptimized = false,
Function *Fn = 0);
- /// CreateMethod - Create a new descriptor for the specified C++ method.
+ /// createMethod - Create a new descriptor for the specified C++ method.
/// See comments in DISubprogram for descriptions of these fields.
/// @param Scope Function scope.
/// @param Name Function name.
@@ -390,7 +390,7 @@ namespace llvm {
/// This flags are used to emit dwarf attributes.
/// @param isOptimized True if optimization is ON.
/// @param Fn llvm::Function pointer.
- DISubprogram CreateMethod(DIDescriptor Scope, StringRef Name,
+ DISubprogram createMethod(DIDescriptor Scope, StringRef Name,
StringRef LinkageName,
DIFile File, unsigned LineNo,
DIType Ty, bool isLocalToUnit,
@@ -401,55 +401,55 @@ namespace llvm {
bool isOptimized = false,
Function *Fn = 0);
- /// CreateNameSpace - This creates new descriptor for a namespace
+ /// createNameSpace - This creates new descriptor for a namespace
/// with the specified parent scope.
/// @param Scope Namespace scope
/// @param Name Name of this namespace
/// @param File Source file
/// @param LineNo Line number
- DINameSpace CreateNameSpace(DIDescriptor Scope, StringRef Name,
+ DINameSpace createNameSpace(DIDescriptor Scope, StringRef Name,
DIFile File, unsigned LineNo);
- /// CreateLexicalBlock - This creates a descriptor for a lexical block
+ /// createLexicalBlock - This creates a descriptor for a lexical block
/// with the specified parent context.
/// @param Scope Parent lexical scope.
/// @param File Source file
/// @param Line Line number
/// @param Col Column number
- DILexicalBlock CreateLexicalBlock(DIDescriptor Scope, DIFile File,
+ DILexicalBlock createLexicalBlock(DIDescriptor Scope, DIFile File,
unsigned Line, unsigned Col);
- /// InsertDeclare - Insert a new llvm.dbg.declare intrinsic call.
+ /// insertDeclare - Insert a new llvm.dbg.declare intrinsic call.
/// @param Storage llvm::Value of the variable
/// @param VarInfo Variable's debug info descriptor.
/// @param InsertAtEnd Location for the new intrinsic.
- Instruction *InsertDeclare(llvm::Value *Storage, DIVariable VarInfo,
+ Instruction *insertDeclare(llvm::Value *Storage, DIVariable VarInfo,
BasicBlock *InsertAtEnd);
- /// InsertDeclare - Insert a new llvm.dbg.declare intrinsic call.
+ /// insertDeclare - Insert a new llvm.dbg.declare intrinsic call.
/// @param Storage llvm::Value of the variable
/// @param VarInfo Variable's debug info descriptor.
/// @param InsertBefore Location for the new intrinsic.
- Instruction *InsertDeclare(llvm::Value *Storage, DIVariable VarInfo,
+ Instruction *insertDeclare(llvm::Value *Storage, DIVariable VarInfo,
Instruction *InsertBefore);
- /// InsertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call.
+ /// insertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call.
/// @param Val llvm::Value of the variable
/// @param Offset Offset
/// @param VarInfo Variable's debug info descriptor.
/// @param InsertAtEnd Location for the new intrinsic.
- Instruction *InsertDbgValueIntrinsic(llvm::Value *Val, uint64_t Offset,
+ Instruction *insertDbgValueIntrinsic(llvm::Value *Val, uint64_t Offset,
DIVariable VarInfo,
BasicBlock *InsertAtEnd);
- /// InsertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call.
+ /// insertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call.
/// @param Val llvm::Value of the variable
/// @param Offset Offset
/// @param VarInfo Variable's debug info descriptor.
/// @param InsertBefore Location for the new intrinsic.
- Instruction *InsertDbgValueIntrinsic(llvm::Value *Val, uint64_t Offset,
+ Instruction *insertDbgValueIntrinsic(llvm::Value *Val, uint64_t Offset,
DIVariable VarInfo,
Instruction *InsertBefore);
diff --git a/contrib/llvm/include/llvm/CodeGen/AsmPrinter.h b/contrib/llvm/include/llvm/CodeGen/AsmPrinter.h
index 357b933..a071feb 100644
--- a/contrib/llvm/include/llvm/CodeGen/AsmPrinter.h
+++ b/contrib/llvm/include/llvm/CodeGen/AsmPrinter.h
@@ -445,7 +445,8 @@ namespace llvm {
/// EmitVisibility - This emits visibility information about symbol, if
/// this is suported by the target.
- void EmitVisibility(MCSymbol *Sym, unsigned Visibility) const;
+ void EmitVisibility(MCSymbol *Sym, unsigned Visibility,
+ bool IsDefinition = true) const;
void EmitLinkage(unsigned Linkage, MCSymbol *GVSym) const;
diff --git a/contrib/llvm/include/llvm/CodeGen/FunctionLoweringInfo.h b/contrib/llvm/include/llvm/CodeGen/FunctionLoweringInfo.h
index 27631b7..b41f30d 100644
--- a/contrib/llvm/include/llvm/CodeGen/FunctionLoweringInfo.h
+++ b/contrib/llvm/include/llvm/CodeGen/FunctionLoweringInfo.h
@@ -101,13 +101,16 @@ public:
#endif
struct LiveOutInfo {
- unsigned NumSignBits;
+ unsigned NumSignBits : 31;
+ bool IsValid : 1;
APInt KnownOne, KnownZero;
- LiveOutInfo() : NumSignBits(0), KnownOne(1, 0), KnownZero(1, 0) {}
+ LiveOutInfo() : NumSignBits(0), IsValid(true), KnownOne(1, 0),
+ KnownZero(1, 0) {}
};
-
- /// LiveOutRegInfo - Information about live out vregs.
- IndexedMap<LiveOutInfo, VirtReg2IndexFunctor> LiveOutRegInfo;
+
+ /// VisitedBBs - The set of basic blocks visited thus far by instruction
+ /// selection.
+ DenseSet<const BasicBlock*> VisitedBBs;
/// PHINodesToUpdate - A list of phi instructions whose operand list will
/// be updated after processing the current basic block.
@@ -143,12 +146,62 @@ public:
return R = CreateRegs(V->getType());
}
+ /// GetLiveOutRegInfo - Gets LiveOutInfo for a register, returning NULL if the
+ /// register is a PHI destination and the PHI's LiveOutInfo is not valid.
+ const LiveOutInfo *GetLiveOutRegInfo(unsigned Reg) {
+ if (!LiveOutRegInfo.inBounds(Reg))
+ return NULL;
+
+ const LiveOutInfo *LOI = &LiveOutRegInfo[Reg];
+ if (!LOI->IsValid)
+ return NULL;
+
+ return LOI;
+ }
+
+ /// GetLiveOutRegInfo - Gets LiveOutInfo for a register, returning NULL if the
+ /// register is a PHI destination and the PHI's LiveOutInfo is not valid. If
+ /// the register's LiveOutInfo is for a smaller bit width, it is extended to
+ /// the larger bit width by zero extension. The bit width must be no smaller
+ /// than the LiveOutInfo's existing bit width.
+ const LiveOutInfo *GetLiveOutRegInfo(unsigned Reg, unsigned BitWidth);
+
+ /// AddLiveOutRegInfo - Adds LiveOutInfo for a register.
+ void AddLiveOutRegInfo(unsigned Reg, unsigned NumSignBits,
+ const APInt &KnownZero, const APInt &KnownOne) {
+ // Only install this information if it tells us something.
+ if (NumSignBits == 1 && KnownZero == 0 && KnownOne == 0)
+ return;
+
+ LiveOutRegInfo.grow(Reg);
+ LiveOutInfo &LOI = LiveOutRegInfo[Reg];
+ LOI.NumSignBits = NumSignBits;
+ LOI.KnownOne = KnownOne;
+ LOI.KnownZero = KnownZero;
+ }
+
+ /// ComputePHILiveOutRegInfo - Compute LiveOutInfo for a PHI's destination
+ /// register based on the LiveOutInfo of its operands.
+ void ComputePHILiveOutRegInfo(const PHINode*);
+
+ /// InvalidatePHILiveOutRegInfo - Invalidates a PHI's LiveOutInfo, to be
+ /// called when a block is visited before all of its predecessors.
+ void InvalidatePHILiveOutRegInfo(const PHINode *PN) {
+ unsigned Reg = ValueMap[PN];
+ LiveOutRegInfo.grow(Reg);
+ LiveOutRegInfo[Reg].IsValid = false;
+ }
+
/// setByValArgumentFrameIndex - Record frame index for the byval
/// argument.
void setByValArgumentFrameIndex(const Argument *A, int FI);
/// getByValArgumentFrameIndex - Get frame index for the byval argument.
int getByValArgumentFrameIndex(const Argument *A);
+
+private:
+ /// LiveOutRegInfo - Information about live out vregs.
+ IndexedMap<LiveOutInfo, VirtReg2IndexFunctor> LiveOutRegInfo;
};
/// AddCatchInfo - Extract the personality and type infos from an eh.selector
diff --git a/contrib/llvm/include/llvm/CodeGen/MachineConstantPool.h b/contrib/llvm/include/llvm/CodeGen/MachineConstantPool.h
index 498f815..5727321 100644
--- a/contrib/llvm/include/llvm/CodeGen/MachineConstantPool.h
+++ b/contrib/llvm/include/llvm/CodeGen/MachineConstantPool.h
@@ -16,6 +16,7 @@
#ifndef LLVM_CODEGEN_MACHINECONSTANTPOOL_H
#define LLVM_CODEGEN_MACHINECONSTANTPOOL_H
+#include "llvm/ADT/DenseSet.h"
#include <cassert>
#include <climits>
#include <vector>
@@ -130,6 +131,8 @@ class MachineConstantPool {
const TargetData *TD; ///< The machine's TargetData.
unsigned PoolAlignment; ///< The alignment for the pool.
std::vector<MachineConstantPoolEntry> Constants; ///< The pool of constants.
+ /// MachineConstantPoolValues that use an existing MachineConstantPoolEntry.
+ DenseSet<MachineConstantPoolValue*> MachineCPVsSharingEntries;
public:
/// @brief The only constructor.
explicit MachineConstantPool(const TargetData *td)
diff --git a/contrib/llvm/include/llvm/CodeGen/MachineFunction.h b/contrib/llvm/include/llvm/CodeGen/MachineFunction.h
index abeaa4f..f56c053 100644
--- a/contrib/llvm/include/llvm/CodeGen/MachineFunction.h
+++ b/contrib/llvm/include/llvm/CodeGen/MachineFunction.h
@@ -281,7 +281,7 @@ public:
/// addLiveIn - Add the specified physical register as a live-in value and
/// create a corresponding virtual register for it.
- unsigned addLiveIn(unsigned PReg, const TargetRegisterClass *RC, DebugLoc DL);
+ unsigned addLiveIn(unsigned PReg, const TargetRegisterClass *RC);
//===--------------------------------------------------------------------===//
// BasicBlock accessor functions.
diff --git a/contrib/llvm/include/llvm/CodeGen/MachineRegisterInfo.h b/contrib/llvm/include/llvm/CodeGen/MachineRegisterInfo.h
index 79ff714..74df8da 100644
--- a/contrib/llvm/include/llvm/CodeGen/MachineRegisterInfo.h
+++ b/contrib/llvm/include/llvm/CodeGen/MachineRegisterInfo.h
@@ -17,8 +17,6 @@
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/IndexedMap.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/Support/DebugLoc.h"
#include <vector>
namespace llvm {
@@ -66,10 +64,7 @@ class MachineRegisterInfo {
/// stored in the second element.
std::vector<std::pair<unsigned, unsigned> > LiveIns;
std::vector<unsigned> LiveOuts;
-
- /// LiveInLocs - Keep track of location livein registers.
- DenseMap<unsigned, DebugLoc> LiveInLocs;
-
+
MachineRegisterInfo(const MachineRegisterInfo&); // DO NOT IMPLEMENT
void operator=(const MachineRegisterInfo&); // DO NOT IMPLEMENT
public:
@@ -276,12 +271,7 @@ public:
LiveIns.push_back(std::make_pair(Reg, vreg));
}
void addLiveOut(unsigned Reg) { LiveOuts.push_back(Reg); }
-
- /// addLiveInLoc - Keep track of location info for live in reg.
- void addLiveInLoc(unsigned VReg, DebugLoc DL) {
- LiveInLocs[VReg] = DL;
- }
-
+
// Iteration support for live in/out sets. These sets are kept in sorted
// order by their register number.
typedef std::vector<std::pair<unsigned,unsigned> >::const_iterator
diff --git a/contrib/llvm/include/llvm/IntrinsicsXCore.td b/contrib/llvm/include/llvm/IntrinsicsXCore.td
index 97bac1d..944120f 100644
--- a/contrib/llvm/include/llvm/IntrinsicsXCore.td
+++ b/contrib/llvm/include/llvm/IntrinsicsXCore.td
@@ -33,4 +33,23 @@ let TargetPrefix = "xcore" in { // All intrinsics start with "llvm.xcore.".
[NoCapture<0>]>;
def int_xcore_setc : Intrinsic<[],[llvm_anyptr_ty, llvm_i32_ty],
[NoCapture<0>]>;
+ def int_xcore_inshr : Intrinsic<[llvm_i32_ty],[llvm_anyptr_ty, llvm_i32_ty],
+ [NoCapture<0>]>;
+ def int_xcore_outshr : Intrinsic<[llvm_i32_ty],[llvm_anyptr_ty, llvm_i32_ty],
+ [NoCapture<0>]>;
+ def int_xcore_setpt : Intrinsic<[],[llvm_anyptr_ty, llvm_i32_ty],
+ [NoCapture<0>]>;
+ def int_xcore_getts : Intrinsic<[llvm_i32_ty],[llvm_anyptr_ty],
+ [NoCapture<0>]>;
+ def int_xcore_syncr : Intrinsic<[],[llvm_anyptr_ty],
+ [NoCapture<0>]>;
+ def int_xcore_settw : Intrinsic<[],[llvm_anyptr_ty, llvm_i32_ty],
+ [NoCapture<0>]>;
+ def int_xcore_setv : Intrinsic<[],[llvm_anyptr_ty, llvm_ptr_ty],
+ [NoCapture<0>]>;
+ def int_xcore_eeu : Intrinsic<[],[llvm_anyptr_ty], [NoCapture<0>]>;
+
+ // Intrinsics for events.
+ def int_xcore_waitevent : Intrinsic<[llvm_ptr_ty],[], [IntrReadMem]>;
+ def int_xcore_clre : Intrinsic<[],[],[]>;
}
diff --git a/contrib/llvm/include/llvm/MC/MCAsmInfo.h b/contrib/llvm/include/llvm/MC/MCAsmInfo.h
index 9cfd004..0bf364a 100644
--- a/contrib/llvm/include/llvm/MC/MCAsmInfo.h
+++ b/contrib/llvm/include/llvm/MC/MCAsmInfo.h
@@ -246,6 +246,11 @@ namespace llvm {
/// declare a symbol as having hidden visibility.
MCSymbolAttr HiddenVisibilityAttr; // Defaults to MCSA_Hidden.
+ /// HiddenDeclarationVisibilityAttr - This attribute, if not MCSA_Invalid,
+ /// is used to declare an undefined symbol as having hidden visibility.
+ MCSymbolAttr HiddenDeclarationVisibilityAttr; // Defaults to MCSA_Hidden.
+
+
/// ProtectedVisibilityAttr - This attribute, if not MCSA_Invalid, is used
/// to declare a symbol as having protected visibility.
MCSymbolAttr ProtectedVisibilityAttr; // Defaults to MCSA_Protected
@@ -425,6 +430,9 @@ namespace llvm {
const char *getLinkOnceDirective() const { return LinkOnceDirective; }
MCSymbolAttr getHiddenVisibilityAttr() const { return HiddenVisibilityAttr;}
+ MCSymbolAttr getHiddenDeclarationVisibilityAttr() const {
+ return HiddenDeclarationVisibilityAttr;
+ }
MCSymbolAttr getProtectedVisibilityAttr() const {
return ProtectedVisibilityAttr;
}
diff --git a/contrib/llvm/include/llvm/MC/MCParser/MCAsmParserExtension.h b/contrib/llvm/include/llvm/MC/MCParser/MCAsmParserExtension.h
index 95184cd..ceb57f5 100644
--- a/contrib/llvm/include/llvm/MC/MCParser/MCAsmParserExtension.h
+++ b/contrib/llvm/include/llvm/MC/MCParser/MCAsmParserExtension.h
@@ -38,6 +38,8 @@ protected:
return (Obj->*Handler)(Directive, DirectiveLoc);
}
+ bool BracketExpressionsSupported;
+
public:
virtual ~MCAsmParserExtension();
@@ -68,6 +70,8 @@ public:
const AsmToken &getTok() { return getParser().getTok(); }
+ bool HasBracketExpressions() const { return BracketExpressionsSupported; }
+
/// @}
};
diff --git a/contrib/llvm/include/llvm/MC/MCStreamer.h b/contrib/llvm/include/llvm/MC/MCStreamer.h
index fc2451f..4451199 100644
--- a/contrib/llvm/include/llvm/MC/MCStreamer.h
+++ b/contrib/llvm/include/llvm/MC/MCStreamer.h
@@ -57,13 +57,10 @@ namespace llvm {
MCDwarfFrameInfo *getCurrentFrameInfo();
void EnsureValidFrame();
- /// CurSectionStack - This is stack of CurSection values saved by
- /// PushSection.
- SmallVector<const MCSection *, 4> CurSectionStack;
-
- /// PrevSectionStack - This is stack of PrevSection values saved by
- /// PushSection.
- SmallVector<const MCSection *, 4> PrevSectionStack;
+ /// SectionStack - This is stack of current and previous section
+ /// values saved by PushSection.
+ SmallVector<std::pair<const MCSection *,
+ const MCSection *>, 4> SectionStack;
protected:
MCStreamer(MCContext &Ctx);
@@ -117,16 +114,16 @@ namespace llvm {
/// getCurrentSection - Return the current section that the streamer is
/// emitting code to.
const MCSection *getCurrentSection() const {
- if (!CurSectionStack.empty())
- return CurSectionStack.back();
+ if (!SectionStack.empty())
+ return SectionStack.back().first;
return NULL;
}
/// getPreviousSection - Return the previous section that the streamer is
/// emitting code to.
const MCSection *getPreviousSection() const {
- if (!PrevSectionStack.empty())
- return PrevSectionStack.back();
+ if (!SectionStack.empty())
+ return SectionStack.back().second;
return NULL;
}
@@ -139,8 +136,8 @@ namespace llvm {
/// pushSection - Save the current and previous section on the
/// section stack.
void PushSection() {
- PrevSectionStack.push_back(getPreviousSection());
- CurSectionStack.push_back(getCurrentSection());
+ SectionStack.push_back(std::make_pair(getCurrentSection(),
+ getPreviousSection()));
}
/// popSection - Restore the current and previous section from
@@ -148,12 +145,10 @@ namespace llvm {
///
/// Returns false if the stack was empty.
bool PopSection() {
- if (PrevSectionStack.size() <= 1)
+ if (SectionStack.size() <= 1)
return false;
- assert(CurSectionStack.size() > 1);
- PrevSectionStack.pop_back();
- const MCSection *oldSection = CurSectionStack.pop_back_val();
- const MCSection *curSection = CurSectionStack.back();
+ const MCSection *oldSection = SectionStack.pop_back_val().first;
+ const MCSection *curSection = SectionStack.back().first;
if (oldSection != curSection)
ChangeSection(curSection);
@@ -166,10 +161,10 @@ namespace llvm {
/// This corresponds to assembler directives like .section, .text, etc.
void SwitchSection(const MCSection *Section) {
assert(Section && "Cannot switch to a null section!");
- const MCSection *curSection = CurSectionStack.back();
- PrevSectionStack.back() = curSection;
+ const MCSection *curSection = SectionStack.back().first;
+ SectionStack.back().second = curSection;
if (Section != curSection) {
- CurSectionStack.back() = Section;
+ SectionStack.back().first = Section;
ChangeSection(Section);
}
}
diff --git a/contrib/llvm/include/llvm/Support/NoFolder.h b/contrib/llvm/include/llvm/Support/NoFolder.h
index d7b5b42..92a9fd6 100644
--- a/contrib/llvm/include/llvm/Support/NoFolder.h
+++ b/contrib/llvm/include/llvm/Support/NoFolder.h
@@ -38,8 +38,12 @@ public:
// Binary Operators
//===--------------------------------------------------------------------===//
- Instruction *CreateAdd(Constant *LHS, Constant *RHS) const {
- return BinaryOperator::CreateAdd(LHS, RHS);
+ Instruction *CreateAdd(Constant *LHS, Constant *RHS,
+ bool HasNUW = false, bool HasNSW = false) const {
+ BinaryOperator *BO = BinaryOperator::CreateAdd(LHS, RHS);
+ if (HasNUW) BO->setHasNoUnsignedWrap();
+ if (HasNSW) BO->setHasNoSignedWrap();
+ return BO;
}
Instruction *CreateNSWAdd(Constant *LHS, Constant *RHS) const {
return BinaryOperator::CreateNSWAdd(LHS, RHS);
@@ -50,8 +54,12 @@ public:
Instruction *CreateFAdd(Constant *LHS, Constant *RHS) const {
return BinaryOperator::CreateFAdd(LHS, RHS);
}
- Instruction *CreateSub(Constant *LHS, Constant *RHS) const {
- return BinaryOperator::CreateSub(LHS, RHS);
+ Instruction *CreateSub(Constant *LHS, Constant *RHS,
+ bool HasNUW = false, bool HasNSW = false) const {
+ BinaryOperator *BO = BinaryOperator::CreateSub(LHS, RHS);
+ if (HasNUW) BO->setHasNoUnsignedWrap();
+ if (HasNSW) BO->setHasNoSignedWrap();
+ return BO;
}
Instruction *CreateNSWSub(Constant *LHS, Constant *RHS) const {
return BinaryOperator::CreateNSWSub(LHS, RHS);
@@ -62,8 +70,12 @@ public:
Instruction *CreateFSub(Constant *LHS, Constant *RHS) const {
return BinaryOperator::CreateFSub(LHS, RHS);
}
- Instruction *CreateMul(Constant *LHS, Constant *RHS) const {
- return BinaryOperator::CreateMul(LHS, RHS);
+ Instruction *CreateMul(Constant *LHS, Constant *RHS,
+ bool HasNUW = false, bool HasNSW = false) const {
+ BinaryOperator *BO = BinaryOperator::CreateMul(LHS, RHS);
+ if (HasNUW) BO->setHasNoUnsignedWrap();
+ if (HasNSW) BO->setHasNoSignedWrap();
+ return BO;
}
Instruction *CreateNSWMul(Constant *LHS, Constant *RHS) const {
return BinaryOperator::CreateNSWMul(LHS, RHS);
@@ -74,14 +86,20 @@ public:
Instruction *CreateFMul(Constant *LHS, Constant *RHS) const {
return BinaryOperator::CreateFMul(LHS, RHS);
}
- Instruction *CreateUDiv(Constant *LHS, Constant *RHS) const {
- return BinaryOperator::CreateUDiv(LHS, RHS);
+ Instruction *CreateUDiv(Constant *LHS, Constant *RHS,
+ bool isExact = false) const {
+ if (!isExact)
+ return BinaryOperator::CreateUDiv(LHS, RHS);
+ return BinaryOperator::CreateExactUDiv(LHS, RHS);
}
Instruction *CreateExactUDiv(Constant *LHS, Constant *RHS) const {
return BinaryOperator::CreateExactUDiv(LHS, RHS);
}
- Instruction *CreateSDiv(Constant *LHS, Constant *RHS) const {
- return BinaryOperator::CreateSDiv(LHS, RHS);
+ Instruction *CreateSDiv(Constant *LHS, Constant *RHS,
+ bool isExact = false) const {
+ if (!isExact)
+ return BinaryOperator::CreateSDiv(LHS, RHS);
+ return BinaryOperator::CreateExactSDiv(LHS, RHS);
}
Instruction *CreateExactSDiv(Constant *LHS, Constant *RHS) const {
return BinaryOperator::CreateExactSDiv(LHS, RHS);
@@ -98,14 +116,24 @@ public:
Instruction *CreateFRem(Constant *LHS, Constant *RHS) const {
return BinaryOperator::CreateFRem(LHS, RHS);
}
- Instruction *CreateShl(Constant *LHS, Constant *RHS) const {
- return BinaryOperator::CreateShl(LHS, RHS);
- }
- Instruction *CreateLShr(Constant *LHS, Constant *RHS) const {
- return BinaryOperator::CreateLShr(LHS, RHS);
- }
- Instruction *CreateAShr(Constant *LHS, Constant *RHS) const {
- return BinaryOperator::CreateAShr(LHS, RHS);
+ Instruction *CreateShl(Constant *LHS, Constant *RHS, bool HasNUW = false,
+ bool HasNSW = false) const {
+ BinaryOperator *BO = BinaryOperator::CreateShl(LHS, RHS);
+ if (HasNUW) BO->setHasNoUnsignedWrap();
+ if (HasNSW) BO->setHasNoSignedWrap();
+ return BO;
+ }
+ Instruction *CreateLShr(Constant *LHS, Constant *RHS,
+ bool isExact = false) const {
+ if (!isExact)
+ return BinaryOperator::CreateLShr(LHS, RHS);
+ return BinaryOperator::CreateExactLShr(LHS, RHS);
+ }
+ Instruction *CreateAShr(Constant *LHS, Constant *RHS,
+ bool isExact = false) const {
+ if (!isExact)
+ return BinaryOperator::CreateAShr(LHS, RHS);
+ return BinaryOperator::CreateExactAShr(LHS, RHS);
}
Instruction *CreateAnd(Constant *LHS, Constant *RHS) const {
return BinaryOperator::CreateAnd(LHS, RHS);
@@ -126,8 +154,12 @@ public:
// Unary Operators
//===--------------------------------------------------------------------===//
- Instruction *CreateNeg(Constant *C) const {
- return BinaryOperator::CreateNeg(C);
+ Instruction *CreateNeg(Constant *C,
+ bool HasNUW = false, bool HasNSW = false) const {
+ BinaryOperator *BO = BinaryOperator::CreateNeg(C);
+ if (HasNUW) BO->setHasNoUnsignedWrap();
+ if (HasNSW) BO->setHasNoSignedWrap();
+ return BO;
}
Instruction *CreateNSWNeg(Constant *C) const {
return BinaryOperator::CreateNSWNeg(C);
diff --git a/contrib/llvm/include/llvm/Support/PathV1.h b/contrib/llvm/include/llvm/Support/PathV1.h
index a1c3f6a..d7753a3 100644
--- a/contrib/llvm/include/llvm/Support/PathV1.h
+++ b/contrib/llvm/include/llvm/Support/PathV1.h
@@ -312,9 +312,9 @@ namespace sys {
/// This function determines if the path name is absolute, as opposed to
/// relative.
/// @brief Determine if the path is absolute.
-//FIXME: LLVM_ATTRIBUTE_DEPRECATED(
- bool isAbsolute() const;
-//FIXME: LLVMV_PATH_DEPRECATED_MSG(path::is_absolute));
+ LLVM_ATTRIBUTE_DEPRECATED(
+ bool isAbsolute() const,
+ LLVM_PATH_DEPRECATED_MSG(path::is_absolute));
/// This function determines if the path name is absolute, as opposed to
/// relative.
diff --git a/contrib/llvm/include/llvm/Target/TargetLowering.h b/contrib/llvm/include/llvm/Target/TargetLowering.h
index 5141b7b..ba7574d 100644
--- a/contrib/llvm/include/llvm/Target/TargetLowering.h
+++ b/contrib/llvm/include/llvm/Target/TargetLowering.h
@@ -111,7 +111,7 @@ public:
bool isBigEndian() const { return !IsLittleEndian; }
bool isLittleEndian() const { return IsLittleEndian; }
MVT getPointerTy() const { return PointerTy; }
- MVT getShiftAmountTy() const { return ShiftAmountTy; }
+ virtual MVT getShiftAmountTy(EVT LHSTy) const;
/// isSelectExpensive - Return true if the select operation is expensive for
/// this target.
@@ -210,7 +210,7 @@ public:
/// ValueTypeActions - For each value type, keep a LegalizeAction enum
/// that indicates how instruction selection should deal with the type.
uint8_t ValueTypeActions[MVT::LAST_VALUETYPE];
-
+
LegalizeAction getExtendedTypeAction(EVT VT) const {
// Handle non-vector integers.
if (!VT.isVector()) {
@@ -221,42 +221,56 @@ public:
return Promote;
return Expand;
}
-
- // If this is a type smaller than a legal vector type, promote to that
- // type, e.g. <2 x float> -> <4 x float>.
- if (VT.getVectorElementType().isSimple() &&
- VT.getVectorNumElements() != 1) {
- MVT EltType = VT.getVectorElementType().getSimpleVT();
- unsigned NumElts = VT.getVectorNumElements();
- while (1) {
- // Round up to the nearest power of 2.
- NumElts = (unsigned)NextPowerOf2(NumElts);
-
- MVT LargerVector = MVT::getVectorVT(EltType, NumElts);
- if (LargerVector == MVT()) break;
-
- // If this the larger type is legal, promote to it.
- if (getTypeAction(LargerVector) == Legal) return Promote;
- }
+
+ // Vectors with only one element are always scalarized.
+ if (VT.getVectorNumElements() == 1)
+ return Expand;
+
+ // Vectors with a number of elements that is not a power of two are always
+ // widened, for example <3 x float> -> <4 x float>.
+ if (!VT.isPow2VectorType())
+ return Promote;
+
+ // Vectors with a crazy element type are always expanded, for example
+ // <4 x i2> is expanded into two vectors of type <2 x i2>.
+ if (!VT.getVectorElementType().isSimple())
+ return Expand;
+
+ // If this type is smaller than a legal vector type then widen it,
+ // otherwise expand it. E.g. <2 x float> -> <4 x float>.
+ MVT EltType = VT.getVectorElementType().getSimpleVT();
+ unsigned NumElts = VT.getVectorNumElements();
+ while (1) {
+ // Round up to the next power of 2.
+ NumElts = (unsigned)NextPowerOf2(NumElts);
+
+ // If there is no simple vector type with this many elements then there
+ // cannot be a larger legal vector type. Note that this assumes that
+ // there are no skipped intermediate vector types in the simple types.
+ MVT LargerVector = MVT::getVectorVT(EltType, NumElts);
+ if (LargerVector == MVT())
+ return Expand;
+
+ // If this type is legal then widen the vector.
+ if (getTypeAction(LargerVector) == Legal)
+ return Promote;
}
-
- return VT.isPow2VectorType() ? Expand : Promote;
- }
+ }
public:
ValueTypeActionImpl() {
std::fill(ValueTypeActions, array_endof(ValueTypeActions), 0);
}
-
+
LegalizeAction getTypeAction(EVT VT) const {
if (!VT.isExtended())
return getTypeAction(VT.getSimpleVT());
return getExtendedTypeAction(VT);
}
-
+
LegalizeAction getTypeAction(MVT VT) const {
return (LegalizeAction)ValueTypeActions[VT.SimpleTy];
}
-
+
void setTypeAction(EVT VT, LegalizeAction Action) {
unsigned I = VT.getSimpleVT().SimpleTy;
ValueTypeActions[I] = Action;
@@ -277,7 +291,7 @@ public:
LegalizeAction getTypeAction(MVT VT) const {
return ValueTypeActions.getTypeAction(VT);
}
-
+
/// getTypeToTransformTo - For types supported by the target, this is an
/// identity function. For types that must be promoted to larger types, this
/// returns the larger type to promote to. For integer types that are larger
@@ -310,7 +324,7 @@ public:
EVT NVT = VT.getRoundIntegerType(Context);
if (NVT == VT) // Size is a power of two - expand to half the size.
return EVT::getIntegerVT(Context, VT.getSizeInBits() / 2);
-
+
// Promote to a power of two size, avoiding multi-step promotion.
return getTypeAction(NVT) == Promote ?
getTypeToTransformTo(Context, NVT) : NVT;
@@ -983,10 +997,6 @@ public:
//
protected:
- /// setShiftAmountType - Describe the type that should be used for shift
- /// amounts. This type defaults to the pointer type.
- void setShiftAmountType(MVT VT) { ShiftAmountTy = VT; }
-
/// setBooleanContents - Specify how the target extends the result of a
/// boolean value from i1 to a wider type. See getBooleanContents.
void setBooleanContents(BooleanContent Ty) { BooleanContents = Ty; }
@@ -1033,12 +1043,12 @@ protected:
/// SelectIsExpensive - Tells the code generator not to expand operations
/// into sequences that use the select operations if possible.
- void setSelectIsExpensive(bool isExpensive = true) {
- SelectIsExpensive = isExpensive;
+ void setSelectIsExpensive(bool isExpensive = true) {
+ SelectIsExpensive = isExpensive;
}
- /// JumpIsExpensive - Tells the code generator not to expand sequence of
- /// operations into a seperate sequences that increases the amount of
+ /// JumpIsExpensive - Tells the code generator not to expand sequence of
+ /// operations into a seperate sequences that increases the amount of
/// flow control.
void setJumpIsExpensive(bool isExpensive = true) {
JumpIsExpensive = isExpensive;
@@ -1355,7 +1365,7 @@ public:
CW_Good = 1, // Good weight.
CW_Better = 2, // Better weight.
CW_Best = 3, // Best weight.
-
+
// Well-known weights.
CW_SpecificReg = CW_Okay, // Specific register operands.
CW_Register = CW_Good, // Register operands.
@@ -1408,21 +1418,21 @@ public:
CallOperandVal(0), ConstraintVT(MVT::Other) {
}
};
-
+
typedef std::vector<AsmOperandInfo> AsmOperandInfoVector;
-
+
/// ParseConstraints - Split up the constraint string from the inline
/// assembly value into the specific constraints and their prefixes,
/// and also tie in the associated operand values.
/// If this returns an empty vector, and if the constraint string itself
/// isn't empty, there was an error parsing.
virtual AsmOperandInfoVector ParseConstraints(ImmutableCallSite CS) const;
-
+
/// Examine constraint type and operand type and determine a weight value.
/// The operand object must already have been set up with the operand type.
virtual ConstraintWeight getMultipleConstraintMatchWeight(
AsmOperandInfo &info, int maIndex) const;
-
+
/// Examine constraint string and operand type and determine a weight value.
/// The operand object must already have been set up with the operand type.
virtual ConstraintWeight getSingleConstraintMatchWeight(
@@ -1432,7 +1442,7 @@ public:
/// type to use for the specific AsmOperandInfo, setting
/// OpInfo.ConstraintCode and OpInfo.ConstraintType. If the actual operand
/// being passed in is available, it can be passed in as Op, otherwise an
- /// empty SDValue can be passed.
+ /// empty SDValue can be passed.
virtual void ComputeConstraintToUse(AsmOperandInfo &OpInfo,
SDValue Op,
SelectionDAG *DAG = 0) const;
@@ -1646,10 +1656,6 @@ private:
/// llvm.longjmp. Defaults to false.
bool UseUnderscoreLongJmp;
- /// ShiftAmountTy - The type to use for shift amounts, usually i8 or whatever
- /// PointerTy is.
- MVT ShiftAmountTy;
-
/// BooleanContents - Information about the contents of the high-bits in
/// boolean values held in a type wider than i1. See getBooleanContents.
BooleanContent BooleanContents;
diff --git a/contrib/llvm/include/llvm/Transforms/Utils/Local.h b/contrib/llvm/include/llvm/Transforms/Utils/Local.h
index 26b5dd8..2823fbb 100644
--- a/contrib/llvm/include/llvm/Transforms/Utils/Local.h
+++ b/contrib/llvm/include/llvm/Transforms/Utils/Local.h
@@ -60,7 +60,7 @@ bool RecursivelyDeleteTriviallyDeadInstructions(Value *V);
/// dead PHI node, due to being a def-use chain of single-use nodes that
/// either forms a cycle or is terminated by a trivially dead instruction,
/// delete it. If that makes any of its operands trivially dead, delete them
-/// too, recursively. Return true if the PHI node is actually deleted.
+/// too, recursively. Return true if a change was made.
bool RecursivelyDeleteDeadPHINode(PHINode *PN);
diff --git a/contrib/llvm/lib/Analysis/DIBuilder.cpp b/contrib/llvm/lib/Analysis/DIBuilder.cpp
index c1072df..590a9c1 100644
--- a/contrib/llvm/lib/Analysis/DIBuilder.cpp
+++ b/contrib/llvm/lib/Analysis/DIBuilder.cpp
@@ -31,9 +31,9 @@ static Constant *GetTagConstant(LLVMContext &VMContext, unsigned Tag) {
DIBuilder::DIBuilder(Module &m)
: M(m), VMContext(M.getContext()), TheCU(0), DeclareFn(0), ValueFn(0) {}
-/// CreateCompileUnit - A CompileUnit provides an anchor for all debugging
+/// createCompileUnit - A CompileUnit provides an anchor for all debugging
/// information generated during this instance of compilation.
-void DIBuilder::CreateCompileUnit(unsigned Lang, StringRef Filename,
+void DIBuilder::createCompileUnit(unsigned Lang, StringRef Filename,
StringRef Directory, StringRef Producer,
bool isOptimized, StringRef Flags,
unsigned RunTimeVer) {
@@ -53,9 +53,9 @@ void DIBuilder::CreateCompileUnit(unsigned Lang, StringRef Filename,
TheCU = DICompileUnit(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts)));
}
-/// CreateFile - Create a file descriptor to hold debugging information
+/// createFile - Create a file descriptor to hold debugging information
/// for a file.
-DIFile DIBuilder::CreateFile(StringRef Filename, StringRef Directory) {
+DIFile DIBuilder::createFile(StringRef Filename, StringRef Directory) {
assert(TheCU && "Unable to create DW_TAG_file_type without CompileUnit");
Value *Elts[] = {
GetTagConstant(VMContext, dwarf::DW_TAG_file_type),
@@ -66,8 +66,8 @@ DIFile DIBuilder::CreateFile(StringRef Filename, StringRef Directory) {
return DIFile(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts)));
}
-/// CreateEnumerator - Create a single enumerator value.
-DIEnumerator DIBuilder::CreateEnumerator(StringRef Name, uint64_t Val) {
+/// createEnumerator - Create a single enumerator value.
+DIEnumerator DIBuilder::createEnumerator(StringRef Name, uint64_t Val) {
Value *Elts[] = {
GetTagConstant(VMContext, dwarf::DW_TAG_enumerator),
MDString::get(VMContext, Name),
@@ -76,9 +76,9 @@ DIEnumerator DIBuilder::CreateEnumerator(StringRef Name, uint64_t Val) {
return DIEnumerator(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts)));
}
-/// CreateBasicType - Create debugging information entry for a basic
+/// createBasicType - Create debugging information entry for a basic
/// type, e.g 'char'.
-DIType DIBuilder::CreateBasicType(StringRef Name, uint64_t SizeInBits,
+DIType DIBuilder::createBasicType(StringRef Name, uint64_t SizeInBits,
uint64_t AlignInBits,
unsigned Encoding) {
// Basic types are encoded in DIBasicType format. Line number, filename,
@@ -98,9 +98,9 @@ DIType DIBuilder::CreateBasicType(StringRef Name, uint64_t SizeInBits,
return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts)));
}
-/// CreateQaulifiedType - Create debugging information entry for a qualified
+/// createQaulifiedType - Create debugging information entry for a qualified
/// type, e.g. 'const int'.
-DIType DIBuilder::CreateQualifiedType(unsigned Tag, DIType FromTy) {
+DIType DIBuilder::createQualifiedType(unsigned Tag, DIType FromTy) {
// Qualified types are encoded in DIDerivedType format.
Value *Elts[] = {
GetTagConstant(VMContext, Tag),
@@ -117,8 +117,8 @@ DIType DIBuilder::CreateQualifiedType(unsigned Tag, DIType FromTy) {
return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts)));
}
-/// CreatePointerType - Create debugging information entry for a pointer.
-DIType DIBuilder::CreatePointerType(DIType PointeeTy, uint64_t SizeInBits,
+/// createPointerType - Create debugging information entry for a pointer.
+DIType DIBuilder::createPointerType(DIType PointeeTy, uint64_t SizeInBits,
uint64_t AlignInBits, StringRef Name) {
// Pointer types are encoded in DIDerivedType format.
Value *Elts[] = {
@@ -136,8 +136,8 @@ DIType DIBuilder::CreatePointerType(DIType PointeeTy, uint64_t SizeInBits,
return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts)));
}
-/// CreateReferenceType - Create debugging information entry for a reference.
-DIType DIBuilder::CreateReferenceType(DIType RTy) {
+/// createReferenceType - Create debugging information entry for a reference.
+DIType DIBuilder::createReferenceType(DIType RTy) {
// References are encoded in DIDerivedType format.
Value *Elts[] = {
GetTagConstant(VMContext, dwarf::DW_TAG_reference_type),
@@ -154,8 +154,8 @@ DIType DIBuilder::CreateReferenceType(DIType RTy) {
return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts)));
}
-/// CreateTypedef - Create debugging information entry for a typedef.
-DIType DIBuilder::CreateTypedef(DIType Ty, StringRef Name, DIFile File,
+/// createTypedef - Create debugging information entry for a typedef.
+DIType DIBuilder::createTypedef(DIType Ty, StringRef Name, DIFile File,
unsigned LineNo) {
// typedefs are encoded in DIDerivedType format.
assert(Ty.Verify() && "Invalid typedef type!");
@@ -174,8 +174,8 @@ DIType DIBuilder::CreateTypedef(DIType Ty, StringRef Name, DIFile File,
return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts)));
}
-/// CreateFriend - Create debugging information entry for a 'friend'.
-DIType DIBuilder::CreateFriend(DIType Ty, DIType FriendTy) {
+/// createFriend - Create debugging information entry for a 'friend'.
+DIType DIBuilder::createFriend(DIType Ty, DIType FriendTy) {
// typedefs are encoded in DIDerivedType format.
assert(Ty.Verify() && "Invalid type!");
assert(FriendTy.Verify() && "Invalid friend type!");
@@ -194,9 +194,9 @@ DIType DIBuilder::CreateFriend(DIType Ty, DIType FriendTy) {
return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts)));
}
-/// CreateInheritance - Create debugging information entry to establish
+/// createInheritance - Create debugging information entry to establish
/// inheritnace relationship between two types.
-DIType DIBuilder::CreateInheritance(DIType Ty, DIType BaseTy,
+DIType DIBuilder::createInheritance(DIType Ty, DIType BaseTy,
uint64_t BaseOffset, unsigned Flags) {
// TAG_inheritance is encoded in DIDerivedType format.
Value *Elts[] = {
@@ -214,8 +214,8 @@ DIType DIBuilder::CreateInheritance(DIType Ty, DIType BaseTy,
return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts)));
}
-/// CreateMemberType - Create debugging information entry for a member.
-DIType DIBuilder::CreateMemberType(StringRef Name,
+/// createMemberType - Create debugging information entry for a member.
+DIType DIBuilder::createMemberType(StringRef Name,
DIFile File, unsigned LineNumber,
uint64_t SizeInBits, uint64_t AlignInBits,
uint64_t OffsetInBits, unsigned Flags,
@@ -236,8 +236,8 @@ DIType DIBuilder::CreateMemberType(StringRef Name,
return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts)));
}
-/// CreateClassType - Create debugging information entry for a class.
-DIType DIBuilder::CreateClassType(DIDescriptor Context, StringRef Name,
+/// createClassType - Create debugging information entry for a class.
+DIType DIBuilder::createClassType(DIDescriptor Context, StringRef Name,
DIFile File, unsigned LineNumber,
uint64_t SizeInBits, uint64_t AlignInBits,
uint64_t OffsetInBits, unsigned Flags,
@@ -263,10 +263,10 @@ DIType DIBuilder::CreateClassType(DIDescriptor Context, StringRef Name,
return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts)));
}
-/// CreateTemplateTypeParameter - Create debugging information for template
+/// createTemplateTypeParameter - Create debugging information for template
/// type parameter.
DITemplateTypeParameter
-DIBuilder::CreateTemplateTypeParameter(DIDescriptor Context, StringRef Name,
+DIBuilder::createTemplateTypeParameter(DIDescriptor Context, StringRef Name,
DIType Ty, MDNode *File, unsigned LineNo,
unsigned ColumnNo) {
Value *Elts[] = {
@@ -282,10 +282,10 @@ DIBuilder::CreateTemplateTypeParameter(DIDescriptor Context, StringRef Name,
array_lengthof(Elts)));
}
-/// CreateTemplateValueParameter - Create debugging information for template
+/// createTemplateValueParameter - Create debugging information for template
/// value parameter.
DITemplateValueParameter
-DIBuilder::CreateTemplateValueParameter(DIDescriptor Context, StringRef Name,
+DIBuilder::createTemplateValueParameter(DIDescriptor Context, StringRef Name,
DIType Ty, uint64_t Val,
MDNode *File, unsigned LineNo,
unsigned ColumnNo) {
@@ -303,8 +303,8 @@ DIBuilder::CreateTemplateValueParameter(DIDescriptor Context, StringRef Name,
array_lengthof(Elts)));
}
-/// CreateStructType - Create debugging information entry for a struct.
-DIType DIBuilder::CreateStructType(DIDescriptor Context, StringRef Name,
+/// createStructType - Create debugging information entry for a struct.
+DIType DIBuilder::createStructType(DIDescriptor Context, StringRef Name,
DIFile File, unsigned LineNumber,
uint64_t SizeInBits, uint64_t AlignInBits,
unsigned Flags, DIArray Elements,
@@ -328,8 +328,8 @@ DIType DIBuilder::CreateStructType(DIDescriptor Context, StringRef Name,
return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts)));
}
-/// CreateUnionType - Create debugging information entry for an union.
-DIType DIBuilder::CreateUnionType(DIDescriptor Scope, StringRef Name,
+/// createUnionType - Create debugging information entry for an union.
+DIType DIBuilder::createUnionType(DIDescriptor Scope, StringRef Name,
DIFile File,
unsigned LineNumber, uint64_t SizeInBits,
uint64_t AlignInBits, unsigned Flags,
@@ -353,8 +353,8 @@ DIType DIBuilder::CreateUnionType(DIDescriptor Scope, StringRef Name,
return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts)));
}
-/// CreateSubroutineType - Create subroutine type.
-DIType DIBuilder::CreateSubroutineType(DIFile File, DIArray ParameterTypes) {
+/// createSubroutineType - Create subroutine type.
+DIType DIBuilder::createSubroutineType(DIFile File, DIArray ParameterTypes) {
// TAG_subroutine_type is encoded in DICompositeType format.
Value *Elts[] = {
GetTagConstant(VMContext, dwarf::DW_TAG_subroutine_type),
@@ -374,9 +374,9 @@ DIType DIBuilder::CreateSubroutineType(DIFile File, DIArray ParameterTypes) {
return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts)));
}
-/// CreateEnumerationType - Create debugging information entry for an
+/// createEnumerationType - Create debugging information entry for an
/// enumeration.
-DIType DIBuilder::CreateEnumerationType(DIDescriptor Scope, StringRef Name,
+DIType DIBuilder::createEnumerationType(DIDescriptor Scope, StringRef Name,
DIFile File, unsigned LineNumber,
uint64_t SizeInBits,
uint64_t AlignInBits, DIArray Elements) {
@@ -402,8 +402,8 @@ DIType DIBuilder::CreateEnumerationType(DIDescriptor Scope, StringRef Name,
return DIType(Node);
}
-/// CreateArrayType - Create debugging information entry for an array.
-DIType DIBuilder::CreateArrayType(uint64_t Size, uint64_t AlignInBits,
+/// createArrayType - Create debugging information entry for an array.
+DIType DIBuilder::createArrayType(uint64_t Size, uint64_t AlignInBits,
DIType Ty, DIArray Subscripts) {
// TAG_array_type is encoded in DICompositeType format.
Value *Elts[] = {
@@ -424,8 +424,8 @@ DIType DIBuilder::CreateArrayType(uint64_t Size, uint64_t AlignInBits,
return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts)));
}
-/// CreateVectorType - Create debugging information entry for a vector.
-DIType DIBuilder::CreateVectorType(uint64_t Size, uint64_t AlignInBits,
+/// createVectorType - Create debugging information entry for a vector.
+DIType DIBuilder::createVectorType(uint64_t Size, uint64_t AlignInBits,
DIType Ty, DIArray Subscripts) {
// TAG_vector_type is encoded in DICompositeType format.
Value *Elts[] = {
@@ -446,8 +446,8 @@ DIType DIBuilder::CreateVectorType(uint64_t Size, uint64_t AlignInBits,
return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts)));
}
-/// CreateArtificialType - Create a new DIType with "artificial" flag set.
-DIType DIBuilder::CreateArtificialType(DIType Ty) {
+/// createArtificialType - Create a new DIType with "artificial" flag set.
+DIType DIBuilder::createArtificialType(DIType Ty) {
if (Ty.isArtificial())
return Ty;
@@ -470,24 +470,24 @@ DIType DIBuilder::CreateArtificialType(DIType Ty) {
return DIType(MDNode::get(VMContext, Elts.data(), Elts.size()));
}
-/// RetainType - Retain DIType in a module even if it is not referenced
+/// retainType - Retain DIType in a module even if it is not referenced
/// through debug info anchors.
-void DIBuilder::RetainType(DIType T) {
+void DIBuilder::retainType(DIType T) {
NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.ty");
NMD->addOperand(T);
}
-/// CreateUnspecifiedParameter - Create unspeicified type descriptor
+/// createUnspecifiedParameter - Create unspeicified type descriptor
/// for the subroutine type.
-DIDescriptor DIBuilder::CreateUnspecifiedParameter() {
+DIDescriptor DIBuilder::createUnspecifiedParameter() {
Value *Elts[] = {
GetTagConstant(VMContext, dwarf::DW_TAG_unspecified_parameters)
};
return DIDescriptor(MDNode::get(VMContext, &Elts[0], 1));
}
-/// CreateTemporaryType - Create a temporary forward-declared type.
-DIType DIBuilder::CreateTemporaryType() {
+/// createTemporaryType - Create a temporary forward-declared type.
+DIType DIBuilder::createTemporaryType() {
// Give the temporary MDNode a tag. It doesn't matter what tag we
// use here as long as DIType accepts it.
Value *Elts[] = { GetTagConstant(VMContext, DW_TAG_base_type) };
@@ -495,8 +495,8 @@ DIType DIBuilder::CreateTemporaryType() {
return DIType(Node);
}
-/// CreateTemporaryType - Create a temporary forward-declared type.
-DIType DIBuilder::CreateTemporaryType(DIFile F) {
+/// createTemporaryType - Create a temporary forward-declared type.
+DIType DIBuilder::createTemporaryType(DIFile F) {
// Give the temporary MDNode a tag. It doesn't matter what tag we
// use here as long as DIType accepts it.
Value *Elts[] = {
@@ -509,8 +509,8 @@ DIType DIBuilder::CreateTemporaryType(DIFile F) {
return DIType(Node);
}
-/// GetOrCreateArray - Get a DIArray, create one if required.
-DIArray DIBuilder::GetOrCreateArray(Value *const *Elements, unsigned NumElements) {
+/// getOrCreateArray - Get a DIArray, create one if required.
+DIArray DIBuilder::getOrCreateArray(Value *const *Elements, unsigned NumElements) {
if (NumElements == 0) {
Value *Null = llvm::Constant::getNullValue(Type::getInt32Ty(VMContext));
return DIArray(MDNode::get(VMContext, &Null, 1));
@@ -518,9 +518,9 @@ DIArray DIBuilder::GetOrCreateArray(Value *const *Elements, unsigned NumElements
return DIArray(MDNode::get(VMContext, Elements, NumElements));
}
-/// GetOrCreateSubrange - Create a descriptor for a value range. This
+/// getOrCreateSubrange - Create a descriptor for a value range. This
/// implicitly uniques the values returned.
-DISubrange DIBuilder::GetOrCreateSubrange(int64_t Lo, int64_t Hi) {
+DISubrange DIBuilder::getOrCreateSubrange(int64_t Lo, int64_t Hi) {
Value *Elts[] = {
GetTagConstant(VMContext, dwarf::DW_TAG_subrange_type),
ConstantInt::get(Type::getInt64Ty(VMContext), Lo),
@@ -530,9 +530,9 @@ DISubrange DIBuilder::GetOrCreateSubrange(int64_t Lo, int64_t Hi) {
return DISubrange(MDNode::get(VMContext, &Elts[0], 3));
}
-/// CreateGlobalVariable - Create a new descriptor for the specified global.
+/// createGlobalVariable - Create a new descriptor for the specified global.
DIGlobalVariable DIBuilder::
-CreateGlobalVariable(StringRef Name, DIFile F, unsigned LineNumber,
+createGlobalVariable(StringRef Name, DIFile F, unsigned LineNumber,
DIType Ty, bool isLocalToUnit, llvm::Value *Val) {
Value *Elts[] = {
GetTagConstant(VMContext, dwarf::DW_TAG_variable),
@@ -555,10 +555,10 @@ CreateGlobalVariable(StringRef Name, DIFile F, unsigned LineNumber,
return DIGlobalVariable(Node);
}
-/// CreateStaticVariable - Create a new descriptor for the specified static
+/// createStaticVariable - Create a new descriptor for the specified static
/// variable.
DIGlobalVariable DIBuilder::
-CreateStaticVariable(DIDescriptor Context, StringRef Name,
+createStaticVariable(DIDescriptor Context, StringRef Name,
StringRef LinkageName, DIFile F, unsigned LineNumber,
DIType Ty, bool isLocalToUnit, llvm::Value *Val) {
Value *Elts[] = {
@@ -582,8 +582,8 @@ CreateStaticVariable(DIDescriptor Context, StringRef Name,
return DIGlobalVariable(Node);
}
-/// CreateVariable - Create a new descriptor for the specified variable.
-DIVariable DIBuilder::CreateLocalVariable(unsigned Tag, DIDescriptor Scope,
+/// createVariable - Create a new descriptor for the specified variable.
+DIVariable DIBuilder::createLocalVariable(unsigned Tag, DIDescriptor Scope,
StringRef Name, DIFile File,
unsigned LineNo, DIType Ty,
bool AlwaysPreserve, unsigned Flags) {
@@ -614,9 +614,9 @@ DIVariable DIBuilder::CreateLocalVariable(unsigned Tag, DIDescriptor Scope,
return DIVariable(Node);
}
-/// CreateComplexVariable - Create a new descriptor for the specified variable
+/// createComplexVariable - Create a new descriptor for the specified variable
/// which has a complex address expression for its address.
-DIVariable DIBuilder::CreateComplexVariable(unsigned Tag, DIDescriptor Scope,
+DIVariable DIBuilder::createComplexVariable(unsigned Tag, DIDescriptor Scope,
StringRef Name, DIFile F,
unsigned LineNo,
DIType Ty, Value *const *Addr,
@@ -633,8 +633,8 @@ DIVariable DIBuilder::CreateComplexVariable(unsigned Tag, DIDescriptor Scope,
return DIVariable(MDNode::get(VMContext, Elts.data(), Elts.size()));
}
-/// CreateFunction - Create a new descriptor for the specified function.
-DISubprogram DIBuilder::CreateFunction(DIDescriptor Context,
+/// createFunction - Create a new descriptor for the specified function.
+DISubprogram DIBuilder::createFunction(DIDescriptor Context,
StringRef Name,
StringRef LinkageName,
DIFile File, unsigned LineNo,
@@ -670,8 +670,8 @@ DISubprogram DIBuilder::CreateFunction(DIDescriptor Context,
return DISubprogram(Node);
}
-/// CreateMethod - Create a new descriptor for the specified C++ method.
-DISubprogram DIBuilder::CreateMethod(DIDescriptor Context,
+/// createMethod - Create a new descriptor for the specified C++ method.
+DISubprogram DIBuilder::createMethod(DIDescriptor Context,
StringRef Name,
StringRef LinkageName,
DIFile F,
@@ -710,9 +710,9 @@ DISubprogram DIBuilder::CreateMethod(DIDescriptor Context,
return DISubprogram(Node);
}
-/// CreateNameSpace - This creates new descriptor for a namespace
+/// createNameSpace - This creates new descriptor for a namespace
/// with the specified parent scope.
-DINameSpace DIBuilder::CreateNameSpace(DIDescriptor Scope, StringRef Name,
+DINameSpace DIBuilder::createNameSpace(DIDescriptor Scope, StringRef Name,
DIFile File, unsigned LineNo) {
Value *Elts[] = {
GetTagConstant(VMContext, dwarf::DW_TAG_namespace),
@@ -724,7 +724,7 @@ DINameSpace DIBuilder::CreateNameSpace(DIDescriptor Scope, StringRef Name,
return DINameSpace(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts)));
}
-DILexicalBlock DIBuilder::CreateLexicalBlock(DIDescriptor Scope, DIFile File,
+DILexicalBlock DIBuilder::createLexicalBlock(DIDescriptor Scope, DIFile File,
unsigned Line, unsigned Col) {
// Defeat MDNode uniqing for lexical blocks by using unique id.
static unsigned int unique_id = 0;
@@ -739,8 +739,8 @@ DILexicalBlock DIBuilder::CreateLexicalBlock(DIDescriptor Scope, DIFile File,
return DILexicalBlock(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts)));
}
-/// InsertDeclare - Insert a new llvm.dbg.declare intrinsic call.
-Instruction *DIBuilder::InsertDeclare(Value *Storage, DIVariable VarInfo,
+/// insertDeclare - Insert a new llvm.dbg.declare intrinsic call.
+Instruction *DIBuilder::insertDeclare(Value *Storage, DIVariable VarInfo,
Instruction *InsertBefore) {
assert(Storage && "no storage passed to dbg.declare");
assert(VarInfo.Verify() && "empty DIVariable passed to dbg.declare");
@@ -751,8 +751,8 @@ Instruction *DIBuilder::InsertDeclare(Value *Storage, DIVariable VarInfo,
return CallInst::Create(DeclareFn, Args, Args+2, "", InsertBefore);
}
-/// InsertDeclare - Insert a new llvm.dbg.declare intrinsic call.
-Instruction *DIBuilder::InsertDeclare(Value *Storage, DIVariable VarInfo,
+/// insertDeclare - Insert a new llvm.dbg.declare intrinsic call.
+Instruction *DIBuilder::insertDeclare(Value *Storage, DIVariable VarInfo,
BasicBlock *InsertAtEnd) {
assert(Storage && "no storage passed to dbg.declare");
assert(VarInfo.Verify() && "invalid DIVariable passed to dbg.declare");
@@ -769,8 +769,8 @@ Instruction *DIBuilder::InsertDeclare(Value *Storage, DIVariable VarInfo,
return CallInst::Create(DeclareFn, Args, Args+2, "", InsertAtEnd);
}
-/// InsertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call.
-Instruction *DIBuilder::InsertDbgValueIntrinsic(Value *V, uint64_t Offset,
+/// insertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call.
+Instruction *DIBuilder::insertDbgValueIntrinsic(Value *V, uint64_t Offset,
DIVariable VarInfo,
Instruction *InsertBefore) {
assert(V && "no value passed to dbg.value");
@@ -784,8 +784,8 @@ Instruction *DIBuilder::InsertDbgValueIntrinsic(Value *V, uint64_t Offset,
return CallInst::Create(ValueFn, Args, Args+3, "", InsertBefore);
}
-/// InsertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call.
-Instruction *DIBuilder::InsertDbgValueIntrinsic(Value *V, uint64_t Offset,
+/// insertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call.
+Instruction *DIBuilder::insertDbgValueIntrinsic(Value *V, uint64_t Offset,
DIVariable VarInfo,
BasicBlock *InsertAtEnd) {
assert(V && "no value passed to dbg.value");
diff --git a/contrib/llvm/lib/Analysis/InstructionSimplify.cpp b/contrib/llvm/lib/Analysis/InstructionSimplify.cpp
index a2f9862..982dacb 100644
--- a/contrib/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/contrib/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -1161,6 +1161,16 @@ static Value *SimplifyOrInst(Value *Op0, Value *Op1, const TargetData *TD,
(A == Op0 || B == Op0))
return Op0;
+ // ~(A & ?) | A = -1
+ if (match(Op0, m_Not(m_And(m_Value(A), m_Value(B)))) &&
+ (A == Op1 || B == Op1))
+ return Constant::getAllOnesValue(Op1->getType());
+
+ // A | ~(A & ?) = -1
+ if (match(Op1, m_Not(m_And(m_Value(A), m_Value(B)))) &&
+ (A == Op0 || B == Op0))
+ return Constant::getAllOnesValue(Op0->getType());
+
// Try some generic simplifications for associative operations.
if (Value *V = SimplifyAssociativeBinOp(Instruction::Or, Op0, Op1, TD, DT,
MaxRecurse))
diff --git a/contrib/llvm/lib/CodeGen/AllocationOrder.h b/contrib/llvm/lib/CodeGen/AllocationOrder.h
index 3db4b69..61fd8f8 100644
--- a/contrib/llvm/lib/CodeGen/AllocationOrder.h
+++ b/contrib/llvm/lib/CodeGen/AllocationOrder.h
@@ -47,6 +47,8 @@ public:
/// rewind - Start over from the beginning.
void rewind() { Pos = 0; }
+ /// isHint - Return true if PhysReg is a preferred register.
+ bool isHint(unsigned PhysReg) const { return PhysReg == Hint; }
};
} // end namespace llvm
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 43e8990..9cb882e 100644
--- a/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -764,7 +764,7 @@ bool AsmPrinter::doFinalization(Module &M) {
continue;
MCSymbol *Name = Mang->getSymbol(&F);
- EmitVisibility(Name, V);
+ EmitVisibility(Name, V, false);
}
// Finalize debug and EH information.
@@ -1820,13 +1820,17 @@ void AsmPrinter::EmitBasicBlockStart(const MachineBasicBlock *MBB) const {
}
}
-void AsmPrinter::EmitVisibility(MCSymbol *Sym, unsigned Visibility) const {
+void AsmPrinter::EmitVisibility(MCSymbol *Sym, unsigned Visibility,
+ bool IsDefinition) const {
MCSymbolAttr Attr = MCSA_Invalid;
switch (Visibility) {
default: break;
case GlobalValue::HiddenVisibility:
- Attr = MAI->getHiddenVisibilityAttr();
+ if (IsDefinition)
+ Attr = MAI->getHiddenVisibilityAttr();
+ else
+ Attr = MAI->getHiddenDeclarationVisibilityAttr();
break;
case GlobalValue::ProtectedVisibility:
Attr = MAI->getProtectedVisibilityAttr();
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index 5106d57..780fa40 100644
--- a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -31,6 +31,7 @@
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Analysis/DebugInfo.h"
+#include "llvm/Analysis/DIBuilder.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
@@ -644,12 +645,12 @@ void DwarfDebug::addComplexAddress(DbgVariable *&DV, DIE *Die,
for (unsigned i = 0, N = DV->getNumAddrElements(); i < N; ++i) {
uint64_t Element = DV->getAddrElement(i);
- if (Element == DIFactory::OpPlus) {
+ if (Element == DIBuilder::OpPlus) {
addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst);
addUInt(Block, 0, dwarf::DW_FORM_udata, DV->getAddrElement(++i));
- } else if (Element == DIFactory::OpDeref) {
+ } else if (Element == DIBuilder::OpDeref) {
addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_deref);
- } else llvm_unreachable("unknown DIFactory Opcode");
+ } else llvm_unreachable("unknown DIBuilder Opcode");
}
// Now attach the location information to the DIE.
@@ -1894,7 +1895,7 @@ void DwarfDebug::constructCompileUnit(const MDNode *N) {
DIE *Die = new DIE(dwarf::DW_TAG_compile_unit);
addString(Die, dwarf::DW_AT_producer, dwarf::DW_FORM_string,
DIUnit.getProducer());
- addUInt(Die, dwarf::DW_AT_language, dwarf::DW_FORM_data1,
+ addUInt(Die, dwarf::DW_AT_language, dwarf::DW_FORM_data2,
DIUnit.getLanguage());
addString(Die, dwarf::DW_AT_name, dwarf::DW_FORM_string, FN);
// Use DW_AT_entry_pc instead of DW_AT_low_pc/DW_AT_high_pc pair. This
diff --git a/contrib/llvm/lib/CodeGen/BranchFolding.cpp b/contrib/llvm/lib/CodeGen/BranchFolding.cpp
index cb81aa3..78a8743 100644
--- a/contrib/llvm/lib/CodeGen/BranchFolding.cpp
+++ b/contrib/llvm/lib/CodeGen/BranchFolding.cpp
@@ -501,10 +501,11 @@ static bool ProfitableToMerge(MachineBasicBlock *MBB1,
MachineBasicBlock *SuccBB,
MachineBasicBlock *PredBB) {
CommonTailLen = ComputeCommonTailLength(MBB1, MBB2, I1, I2);
- MachineFunction *MF = MBB1->getParent();
-
if (CommonTailLen == 0)
return false;
+ DEBUG(dbgs() << "Common tail length of BB#" << MBB1->getNumber()
+ << " and BB#" << MBB2->getNumber() << " is " << CommonTailLen
+ << '\n');
// It's almost always profitable to merge any number of non-terminator
// instructions with the block that falls through into the common successor.
@@ -541,6 +542,7 @@ static bool ProfitableToMerge(MachineBasicBlock *MBB1,
// we don't have to split a block. At worst we will be introducing 1 new
// branch instruction, which is likely to be smaller than the 2
// instructions that would be deleted in the merge.
+ MachineFunction *MF = MBB1->getParent();
if (EffectiveTailLen >= 2 &&
MF->getFunction()->hasFnAttr(Attribute::OptimizeForSize) &&
(I1 == MBB1->begin() || I2 == MBB2->begin()))
diff --git a/contrib/llvm/lib/CodeGen/InlineSpiller.cpp b/contrib/llvm/lib/CodeGen/InlineSpiller.cpp
index a1bd972..38e6c85 100644
--- a/contrib/llvm/lib/CodeGen/InlineSpiller.cpp
+++ b/contrib/llvm/lib/CodeGen/InlineSpiller.cpp
@@ -102,8 +102,7 @@ Spiller *createInlineSpiller(MachineFunctionPass &pass,
}
}
-/// reMaterializeFor - Attempt to rematerialize edit_->getReg() before MI instead of
-/// reloading it.
+/// reMaterializeFor - Attempt to rematerialize before MI instead of reloading.
bool InlineSpiller::reMaterializeFor(MachineBasicBlock::iterator MI) {
SlotIndex UseIdx = lis_.getInstructionIndex(MI).getUseIndex();
VNInfo *OrigVNI = edit_->getParent().getVNInfoAt(UseIdx);
@@ -346,7 +345,8 @@ void InlineSpiller::spill(LiveRangeEdit &edit) {
&& "Trying to spill a stack slot.");
DEBUG(dbgs() << "Inline spilling "
<< mri_.getRegClass(edit.getReg())->getName()
- << ':' << edit.getParent() << "\n");
+ << ':' << edit.getParent() << "\nFrom original "
+ << PrintReg(vrm_.getOriginal(edit.getReg())) << '\n');
assert(edit.getParent().isSpillable() &&
"Attempting to spill already spilled value.");
@@ -357,12 +357,20 @@ void InlineSpiller::spill(LiveRangeEdit &edit) {
return;
rc_ = mri_.getRegClass(edit.getReg());
- stackSlot_ = vrm_.assignVirt2StackSlot(edit_->getReg());
+
+ // Share a stack slot among all descendants of Orig.
+ unsigned Orig = vrm_.getOriginal(edit.getReg());
+ stackSlot_ = vrm_.getStackSlot(Orig);
+ if (stackSlot_ == VirtRegMap::NO_STACK_SLOT)
+ stackSlot_ = vrm_.assignVirt2StackSlot(Orig);
+
+ if (Orig != edit.getReg())
+ vrm_.assignVirt2StackSlot(edit.getReg(), stackSlot_);
// Update LiveStacks now that we are committed to spilling.
LiveInterval &stacklvr = lss_.getOrCreateInterval(stackSlot_, rc_);
- assert(stacklvr.empty() && "Just created stack slot not empty");
- stacklvr.getNextValue(SlotIndex(), 0, lss_.getVNInfoAllocator());
+ if (!stacklvr.hasAtLeastOneValue())
+ stacklvr.getNextValue(SlotIndex(), 0, lss_.getVNInfoAllocator());
stacklvr.MergeRangesInAsValue(edit_->getParent(), stacklvr.getValNumInfo(0));
// Iterate over instructions using register.
diff --git a/contrib/llvm/lib/CodeGen/LowerSubregs.cpp b/contrib/llvm/lib/CodeGen/LowerSubregs.cpp
index ad1c537..7871ba9 100644
--- a/contrib/llvm/lib/CodeGen/LowerSubregs.cpp
+++ b/contrib/llvm/lib/CodeGen/LowerSubregs.cpp
@@ -37,7 +37,7 @@ namespace {
public:
static char ID; // Pass identification, replacement for typeid
LowerSubregsInstructionPass() : MachineFunctionPass(ID) {}
-
+
const char *getPassName() const {
return "Subregister lowering instruction pass";
}
@@ -64,8 +64,8 @@ namespace {
char LowerSubregsInstructionPass::ID = 0;
}
-FunctionPass *llvm::createLowerSubregsPass() {
- return new LowerSubregsInstructionPass();
+FunctionPass *llvm::createLowerSubregsPass() {
+ return new LowerSubregsInstructionPass();
}
/// TransferDeadFlag - MI is a pseudo-instruction with DstReg dead,
@@ -192,9 +192,9 @@ bool LowerSubregsInstructionPass::LowerCopy(MachineInstr *MI) {
/// copies.
///
bool LowerSubregsInstructionPass::runOnMachineFunction(MachineFunction &MF) {
- DEBUG(dbgs() << "Machine Function\n"
+ DEBUG(dbgs() << "Machine Function\n"
<< "********** LOWERING SUBREG INSTRS **********\n"
- << "********** Function: "
+ << "********** Function: "
<< MF.getFunction()->getName() << '\n');
TRI = MF.getTarget().getRegisterInfo();
TII = MF.getTarget().getInstrInfo();
diff --git a/contrib/llvm/lib/CodeGen/MachineFunction.cpp b/contrib/llvm/lib/CodeGen/MachineFunction.cpp
index 8553240..d81e4a1 100644
--- a/contrib/llvm/lib/CodeGen/MachineFunction.cpp
+++ b/contrib/llvm/lib/CodeGen/MachineFunction.cpp
@@ -396,8 +396,7 @@ void MachineFunction::viewCFGOnly() const
/// addLiveIn - Add the specified physical register as a live-in value and
/// create a corresponding virtual register for it.
unsigned MachineFunction::addLiveIn(unsigned PReg,
- const TargetRegisterClass *RC,
- DebugLoc DL) {
+ const TargetRegisterClass *RC) {
MachineRegisterInfo &MRI = getRegInfo();
unsigned VReg = MRI.getLiveInVirtReg(PReg);
if (VReg) {
@@ -406,7 +405,6 @@ unsigned MachineFunction::addLiveIn(unsigned PReg,
}
VReg = MRI.createVirtualRegister(RC);
MRI.addLiveIn(PReg, VReg);
- MRI.addLiveInLoc(VReg, DL);
return VReg;
}
@@ -646,6 +644,10 @@ MachineConstantPool::~MachineConstantPool() {
for (unsigned i = 0, e = Constants.size(); i != e; ++i)
if (Constants[i].isMachineConstantPoolEntry())
delete Constants[i].Val.MachineCPVal;
+ for (DenseSet<MachineConstantPoolValue*>::iterator I =
+ MachineCPVsSharingEntries.begin(), E = MachineCPVsSharingEntries.end();
+ I != E; ++I)
+ delete *I;
}
/// CanShareConstantPoolEntry - Test whether the given two constants
@@ -723,8 +725,10 @@ unsigned MachineConstantPool::getConstantPoolIndex(MachineConstantPoolValue *V,
//
// FIXME, this could be made much more efficient for large constant pools.
int Idx = V->getExistingMachineCPValue(this, Alignment);
- if (Idx != -1)
+ if (Idx != -1) {
+ MachineCPVsSharingEntries.insert(V);
return (unsigned)Idx;
+ }
Constants.push_back(MachineConstantPoolEntry(V, Alignment));
return Constants.size()-1;
diff --git a/contrib/llvm/lib/CodeGen/MachineRegisterInfo.cpp b/contrib/llvm/lib/CodeGen/MachineRegisterInfo.cpp
index b3fb337..7244d5f 100644
--- a/contrib/llvm/lib/CodeGen/MachineRegisterInfo.cpp
+++ b/contrib/llvm/lib/CodeGen/MachineRegisterInfo.cpp
@@ -210,15 +210,8 @@ MachineRegisterInfo::EmitLiveInCopies(MachineBasicBlock *EntryMBB,
LiveIns.erase(LiveIns.begin() + i);
--i; --e;
} else {
- DebugLoc DL;
- // If there is a location for this live in then use it.
- DenseMap<unsigned, DebugLoc>::iterator DLI =
- LiveInLocs.find(LiveIns[i].second);
- if (DLI != LiveInLocs.end())
- DL = DLI->second;
-
// Emit a copy.
- BuildMI(*EntryMBB, EntryMBB->begin(), DL,
+ BuildMI(*EntryMBB, EntryMBB->begin(), DebugLoc(),
TII.get(TargetOpcode::COPY), LiveIns[i].second)
.addReg(LiveIns[i].first);
diff --git a/contrib/llvm/lib/CodeGen/RegAllocBase.h b/contrib/llvm/lib/CodeGen/RegAllocBase.h
index 8c7e5f5..5af0ce7 100644
--- a/contrib/llvm/lib/CodeGen/RegAllocBase.h
+++ b/contrib/llvm/lib/CodeGen/RegAllocBase.h
@@ -39,7 +39,6 @@
#include "llvm/ADT/OwningPtr.h"
#include "LiveIntervalUnion.h"
-#include <queue>
namespace llvm {
@@ -58,8 +57,8 @@ class LiveVirtRegQueue;
/// be extended to add interesting heuristics.
///
/// Register allocators must override the selectOrSplit() method to implement
-/// live range splitting. They may also override getPriority() which otherwise
-/// defaults to the spill weight computed by CalculateSpillWeights.
+/// live range splitting. They must also override enqueue/dequeue to provide an
+/// assignment order.
class RegAllocBase {
LiveIntervalUnion::Allocator UnionAllocator;
protected:
@@ -120,9 +119,11 @@ protected:
// Get a temporary reference to a Spiller instance.
virtual Spiller &spiller() = 0;
- // getPriority - Calculate the allocation priority for VirtReg.
- // Virtual registers with higher priorities are allocated first.
- virtual float getPriority(LiveInterval *LI) = 0;
+ /// enqueue - Add VirtReg to the priority queue of unassigned registers.
+ virtual void enqueue(LiveInterval *LI) = 0;
+
+ /// dequeue - Return the next unassigned register, or NULL.
+ virtual LiveInterval *dequeue() = 0;
// A RegAlloc pass should override this to provide the allocation heuristics.
// Each call must guarantee forward progess by returning an available PhysReg
@@ -170,7 +171,7 @@ public:
static bool VerifyEnabled;
private:
- void seedLiveVirtRegs(std::priority_queue<std::pair<float, unsigned> >&);
+ void seedLiveRegs();
void spillReg(LiveInterval &VirtReg, unsigned PhysReg,
SmallVectorImpl<LiveInterval*> &SplitVRegs);
diff --git a/contrib/llvm/lib/CodeGen/RegAllocBasic.cpp b/contrib/llvm/lib/CodeGen/RegAllocBasic.cpp
index 045c8db..6923908 100644
--- a/contrib/llvm/lib/CodeGen/RegAllocBasic.cpp
+++ b/contrib/llvm/lib/CodeGen/RegAllocBasic.cpp
@@ -45,6 +45,7 @@
#include "llvm/Support/Timer.h"
#include <cstdlib>
+#include <queue>
using namespace llvm;
@@ -65,6 +66,14 @@ const char *RegAllocBase::TimerGroupName = "Register Allocation";
bool RegAllocBase::VerifyEnabled = false;
namespace {
+ struct CompSpillWeight {
+ bool operator()(LiveInterval *A, LiveInterval *B) const {
+ return A->weight < B->weight;
+ }
+ };
+}
+
+namespace {
/// RABasic provides a minimal implementation of the basic register allocation
/// algorithm. It prioritizes live virtual registers by spill weight and spills
/// whenever a register is unavailable. This is not practical in production but
@@ -82,7 +91,8 @@ class RABasic : public MachineFunctionPass, public RegAllocBase
// state
std::auto_ptr<Spiller> SpillerInstance;
-
+ std::priority_queue<LiveInterval*, std::vector<LiveInterval*>,
+ CompSpillWeight> Queue;
public:
RABasic();
@@ -100,6 +110,18 @@ public:
virtual float getPriority(LiveInterval *LI) { return LI->weight; }
+ virtual void enqueue(LiveInterval *LI) {
+ Queue.push(LI);
+ }
+
+ virtual LiveInterval *dequeue() {
+ if (Queue.empty())
+ return 0;
+ LiveInterval *LI = Queue.top();
+ Queue.pop();
+ return LI;
+ }
+
virtual unsigned selectOrSplit(LiveInterval &VirtReg,
SmallVectorImpl<LiveInterval*> &SplitVRegs);
@@ -227,18 +249,17 @@ void RegAllocBase::releaseMemory() {
PhysReg2LiveUnion.clear();
}
-// Visit all the live virtual registers. If they are already assigned to a
-// physical register, unify them with the corresponding LiveIntervalUnion,
-// otherwise push them on the priority queue for later assignment.
-void RegAllocBase::
-seedLiveVirtRegs(std::priority_queue<std::pair<float, unsigned> > &VirtRegQ) {
+// Visit all the live registers. If they are already assigned to a physical
+// register, unify them with the corresponding LiveIntervalUnion, otherwise push
+// them on the priority queue for later assignment.
+void RegAllocBase::seedLiveRegs() {
for (LiveIntervals::iterator I = LIS->begin(), E = LIS->end(); I != E; ++I) {
unsigned RegNum = I->first;
LiveInterval &VirtReg = *I->second;
if (TargetRegisterInfo::isPhysicalRegister(RegNum))
PhysReg2LiveUnion[RegNum].unify(VirtReg);
else
- VirtRegQ.push(std::make_pair(getPriority(&VirtReg), RegNum));
+ enqueue(&VirtReg);
}
}
@@ -263,38 +284,31 @@ void RegAllocBase::unassign(LiveInterval &VirtReg, unsigned PhysReg) {
// Top-level driver to manage the queue of unassigned VirtRegs and call the
// selectOrSplit implementation.
void RegAllocBase::allocatePhysRegs() {
-
- // Push each vreg onto a queue or "precolor" by adding it to a physreg union.
- std::priority_queue<std::pair<float, unsigned> > VirtRegQ;
- seedLiveVirtRegs(VirtRegQ);
+ seedLiveRegs();
// Continue assigning vregs one at a time to available physical registers.
- while (!VirtRegQ.empty()) {
- // Pop the highest priority vreg.
- LiveInterval &VirtReg = LIS->getInterval(VirtRegQ.top().second);
- VirtRegQ.pop();
-
+ while (LiveInterval *VirtReg = dequeue()) {
// selectOrSplit requests the allocator to return an available physical
// register if possible and populate a list of new live intervals that
// result from splitting.
- DEBUG(dbgs() << "\nselectOrSplit " << MRI->getRegClass(VirtReg.reg)->getName()
- << ':' << VirtReg << '\n');
+ DEBUG(dbgs() << "\nselectOrSplit "
+ << MRI->getRegClass(VirtReg->reg)->getName()
+ << ':' << *VirtReg << '\n');
typedef SmallVector<LiveInterval*, 4> VirtRegVec;
VirtRegVec SplitVRegs;
- unsigned AvailablePhysReg = selectOrSplit(VirtReg, SplitVRegs);
+ unsigned AvailablePhysReg = selectOrSplit(*VirtReg, SplitVRegs);
if (AvailablePhysReg)
- assign(VirtReg, AvailablePhysReg);
+ assign(*VirtReg, AvailablePhysReg);
for (VirtRegVec::iterator I = SplitVRegs.begin(), E = SplitVRegs.end();
I != E; ++I) {
- LiveInterval* SplitVirtReg = *I;
+ LiveInterval *SplitVirtReg = *I;
if (SplitVirtReg->empty()) continue;
DEBUG(dbgs() << "queuing new interval: " << *SplitVirtReg << "\n");
assert(TargetRegisterInfo::isVirtualRegister(SplitVirtReg->reg) &&
"expect split value in virtual register");
- VirtRegQ.push(std::make_pair(getPriority(SplitVirtReg),
- SplitVirtReg->reg));
+ enqueue(SplitVirtReg);
++NumNewQueued;
}
}
diff --git a/contrib/llvm/lib/CodeGen/RegAllocGreedy.cpp b/contrib/llvm/lib/CodeGen/RegAllocGreedy.cpp
index c1372cd..406485a 100644
--- a/contrib/llvm/lib/CodeGen/RegAllocGreedy.cpp
+++ b/contrib/llvm/lib/CodeGen/RegAllocGreedy.cpp
@@ -43,6 +43,8 @@
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Timer.h"
+#include <queue>
+
using namespace llvm;
STATISTIC(NumGlobalSplits, "Number of split global live ranges");
@@ -71,6 +73,8 @@ class RAGreedy : public MachineFunctionPass, public RegAllocBase {
// state
std::auto_ptr<Spiller> SpillerInstance;
std::auto_ptr<SplitAnalysis> SA;
+ std::priority_queue<std::pair<unsigned, unsigned> > Queue;
+ IndexedMap<unsigned, VirtReg2IndexFunctor> Generation;
// splitting state.
@@ -91,13 +95,10 @@ public:
/// RAGreedy analysis usage.
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
-
virtual void releaseMemory();
-
virtual Spiller &spiller() { return *SpillerInstance; }
-
- virtual float getPriority(LiveInterval *LI);
-
+ virtual void enqueue(LiveInterval *LI);
+ virtual LiveInterval *dequeue();
virtual unsigned selectOrSplit(LiveInterval&,
SmallVectorImpl<LiveInterval*>&);
@@ -119,9 +120,12 @@ private:
SlotIndex getPrevMappedIndex(const MachineInstr*);
void calcPrevSlots();
unsigned nextSplitPoint(unsigned);
+ bool canEvictInterference(LiveInterval&, unsigned, unsigned, float&);
- unsigned tryReassignOrEvict(LiveInterval&, AllocationOrder&,
+ unsigned tryReassign(LiveInterval&, AllocationOrder&,
SmallVectorImpl<LiveInterval*>&);
+ unsigned tryEvict(LiveInterval&, AllocationOrder&,
+ SmallVectorImpl<LiveInterval*>&);
unsigned tryRegionSplit(LiveInterval&, AllocationOrder&,
SmallVectorImpl<LiveInterval*>&);
unsigned tryLocalSplit(LiveInterval&, AllocationOrder&,
@@ -183,25 +187,42 @@ void RAGreedy::getAnalysisUsage(AnalysisUsage &AU) const {
void RAGreedy::releaseMemory() {
SpillerInstance.reset(0);
+ Generation.clear();
RegAllocBase::releaseMemory();
}
-float RAGreedy::getPriority(LiveInterval *LI) {
- float Priority = LI->weight;
-
- // Prioritize hinted registers so they are allocated first.
- std::pair<unsigned, unsigned> Hint;
- if (Hint.first || Hint.second) {
- // The hint can be target specific, a virtual register, or a physreg.
- Priority *= 2;
-
- // Prefer physreg hints above anything else.
- if (Hint.first == 0 && TargetRegisterInfo::isPhysicalRegister(Hint.second))
- Priority *= 2;
- }
- return Priority;
+void RAGreedy::enqueue(LiveInterval *LI) {
+ // Prioritize live ranges by size, assigning larger ranges first.
+ // The queue holds (size, reg) pairs.
+ const unsigned Size = LI->getSize();
+ const unsigned Reg = LI->reg;
+ assert(TargetRegisterInfo::isVirtualRegister(Reg) &&
+ "Can only enqueue virtual registers");
+ const unsigned Hint = VRM->getRegAllocPref(Reg);
+ unsigned Prio;
+
+ Generation.grow(Reg);
+ if (++Generation[Reg] == 1)
+ // 1st generation ranges are handled first, long -> short.
+ Prio = (1u << 31) + Size;
+ else
+ // Repeat offenders are handled second, short -> long
+ Prio = (1u << 30) - Size;
+
+ // Boost ranges that have a physical register hint.
+ if (TargetRegisterInfo::isPhysicalRegister(Hint))
+ Prio |= (1u << 30);
+
+ Queue.push(std::make_pair(Prio, Reg));
}
+LiveInterval *RAGreedy::dequeue() {
+ if (Queue.empty())
+ return 0;
+ LiveInterval *LI = &LIS->getInterval(Queue.top().second);
+ Queue.pop();
+ return LI;
+}
//===----------------------------------------------------------------------===//
// Register Reassignment
@@ -230,8 +251,7 @@ LiveInterval *RAGreedy::getSingleInterference(LiveInterval &VirtReg,
if (Q.checkInterference()) {
if (Interference)
return 0;
- Q.collectInterferingVRegs(1);
- if (!Q.seenAllInterferences())
+ if (Q.collectInterferingVRegs(2) > 1)
return 0;
Interference = Q.interferingVRegs().front();
}
@@ -276,21 +296,14 @@ bool RAGreedy::reassignVReg(LiveInterval &InterferingVReg,
return false;
}
-/// tryReassignOrEvict - Try to reassign a single interferences to a different
-/// physreg, or evict a single interference with a lower spill weight.
+/// tryReassign - Try to reassign a single interference to a different physreg.
/// @param VirtReg Currently unassigned virtual register.
/// @param Order Physregs to try.
/// @return Physreg to assign VirtReg, or 0.
-unsigned RAGreedy::tryReassignOrEvict(LiveInterval &VirtReg,
- AllocationOrder &Order,
- SmallVectorImpl<LiveInterval*> &NewVRegs){
+unsigned RAGreedy::tryReassign(LiveInterval &VirtReg, AllocationOrder &Order,
+ SmallVectorImpl<LiveInterval*> &NewVRegs){
NamedRegionTimer T("Reassign", TimerGroupName, TimePassesIsEnabled);
- // Keep track of the lightest single interference seen so far.
- float BestWeight = VirtReg.weight;
- LiveInterval *BestVirt = 0;
- unsigned BestPhys = 0;
-
Order.rewind();
while (unsigned PhysReg = Order.next()) {
LiveInterval *InterferingVReg = getSingleInterference(VirtReg, PhysReg);
@@ -300,25 +313,92 @@ unsigned RAGreedy::tryReassignOrEvict(LiveInterval &VirtReg,
continue;
if (reassignVReg(*InterferingVReg, PhysReg))
return PhysReg;
+ }
+ return 0;
+}
+
+
+//===----------------------------------------------------------------------===//
+// Interference eviction
+//===----------------------------------------------------------------------===//
+
+/// canEvict - Return true if all interferences between VirtReg and PhysReg can
+/// be evicted. Set maxWeight to the maximal spill weight of an interference.
+bool RAGreedy::canEvictInterference(LiveInterval &VirtReg, unsigned PhysReg,
+ unsigned Size, float &MaxWeight) {
+ float Weight = 0;
+ for (const unsigned *AliasI = TRI->getOverlaps(PhysReg); *AliasI; ++AliasI) {
+ LiveIntervalUnion::Query &Q = query(VirtReg, *AliasI);
+ // If there is 10 or more interferences, chances are one is smaller.
+ if (Q.collectInterferingVRegs(10) >= 10)
+ return false;
- // Cannot reassign, is this an eviction candidate?
- if (InterferingVReg->weight < BestWeight) {
- BestVirt = InterferingVReg;
- BestPhys = PhysReg;
- BestWeight = InterferingVReg->weight;
+ // CHeck if any interfering live range is shorter than VirtReg.
+ for (unsigned i = 0, e = Q.interferingVRegs().size(); i != e; ++i) {
+ LiveInterval *Intf = Q.interferingVRegs()[i];
+ if (TargetRegisterInfo::isPhysicalRegister(Intf->reg))
+ return false;
+ if (Intf->getSize() <= Size)
+ return false;
+ Weight = std::max(Weight, Intf->weight);
}
}
+ MaxWeight = Weight;
+ return true;
+}
+
+/// tryEvict - Try to evict all interferences for a physreg.
+/// @param VirtReg Currently unassigned virtual register.
+/// @param Order Physregs to try.
+/// @return Physreg to assign VirtReg, or 0.
+unsigned RAGreedy::tryEvict(LiveInterval &VirtReg,
+ AllocationOrder &Order,
+ SmallVectorImpl<LiveInterval*> &NewVRegs){
+ NamedRegionTimer T("Evict", TimerGroupName, TimePassesIsEnabled);
+
+ // We can only evict interference if all interfering registers are virtual and
+ // longer than VirtReg.
+ const unsigned Size = VirtReg.getSize();
+
+ // Keep track of the lightest single interference seen so far.
+ float BestWeight = 0;
+ unsigned BestPhys = 0;
- // Nothing reassigned, can we evict a lighter single interference?
- if (BestVirt) {
- DEBUG(dbgs() << "evicting lighter " << *BestVirt << '\n');
- unassign(*BestVirt, VRM->getPhys(BestVirt->reg));
- ++NumEvicted;
- NewVRegs.push_back(BestVirt);
- return BestPhys;
+ Order.rewind();
+ while (unsigned PhysReg = Order.next()) {
+ float Weight = 0;
+ if (!canEvictInterference(VirtReg, PhysReg, Size, Weight))
+ continue;
+
+ // This is an eviction candidate.
+ DEBUG(dbgs() << "max " << PrintReg(PhysReg, TRI) << " interference = "
+ << Weight << '\n');
+ if (BestPhys && Weight >= BestWeight)
+ continue;
+
+ // Best so far.
+ BestPhys = PhysReg;
+ BestWeight = Weight;
+ // Stop if the hint can be used.
+ if (Order.isHint(PhysReg))
+ break;
}
- return 0;
+ if (!BestPhys)
+ return 0;
+
+ DEBUG(dbgs() << "evicting " << PrintReg(BestPhys, TRI) << " interference\n");
+ for (const unsigned *AliasI = TRI->getOverlaps(BestPhys); *AliasI; ++AliasI) {
+ LiveIntervalUnion::Query &Q = query(VirtReg, *AliasI);
+ assert(Q.seenAllInterferences() && "Didn't check all interfererences.");
+ for (unsigned i = 0, e = Q.interferingVRegs().size(); i != e; ++i) {
+ LiveInterval *Intf = Q.interferingVRegs()[i];
+ unassign(*Intf, VRM->getPhys(Intf->reg));
+ ++NumEvicted;
+ NewVRegs.push_back(Intf);
+ }
+ }
+ return BestPhys;
}
@@ -426,8 +506,13 @@ float RAGreedy::calcInterferenceInfo(LiveInterval &VirtReg, unsigned PhysReg) {
if (!IntI.valid())
break;
// Not live in, but before the first use.
- if (IntI.start() < BI.FirstUse)
+ if (IntI.start() < BI.FirstUse) {
BC.Entry = SpillPlacement::PrefSpill;
+ // If the block contains a kill from an earlier split, never split
+ // again in the same block.
+ if (!BI.LiveThrough && !SA->isOriginalEndpoint(BI.Kill))
+ BC.Entry = SpillPlacement::MustSpill;
+ }
}
// Does interference overlap the uses in the entry segment
@@ -458,8 +543,12 @@ float RAGreedy::calcInterferenceInfo(LiveInterval &VirtReg, unsigned PhysReg) {
IntI.advanceTo(BI.LastUse);
if (!IntI.valid())
break;
- if (IntI.start() < Stop)
+ if (IntI.start() < Stop) {
BC.Exit = SpillPlacement::PrefSpill;
+ // Avoid splitting twice in the same block.
+ if (!BI.LiveThrough && !SA->isOriginalEndpoint(BI.Def))
+ BC.Exit = SpillPlacement::MustSpill;
+ }
}
}
}
@@ -1221,12 +1310,22 @@ unsigned RAGreedy::selectOrSplit(LiveInterval &VirtReg,
return PhysReg;
}
- // Try to reassign interferences.
- if (unsigned PhysReg = tryReassignOrEvict(VirtReg, Order, NewVRegs))
+ if (unsigned PhysReg = tryReassign(VirtReg, Order, NewVRegs))
+ return PhysReg;
+
+ if (unsigned PhysReg = tryEvict(VirtReg, Order, NewVRegs))
return PhysReg;
assert(NewVRegs.empty() && "Cannot append to existing NewVRegs");
+ // The first time we see a live range, don't try to split or spill.
+ // Wait until the second time, when all smaller ranges have been allocated.
+ // This gives a better picture of the interference to split around.
+ if (Generation[VirtReg.reg] == 1) {
+ NewVRegs.push_back(&VirtReg);
+ return 0;
+ }
+
// Try splitting VirtReg or interferences.
unsigned PhysReg = trySplit(VirtReg, Order, NewVRegs);
if (PhysReg || !NewVRegs.empty())
diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/contrib/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 9035602..9cc70a3 100644
--- a/contrib/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/contrib/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -279,8 +279,8 @@ namespace {
/// getShiftAmountTy - Returns a type large enough to hold any valid
/// shift amount - before type legalization these can be huge.
- EVT getShiftAmountTy() {
- return LegalTypes ? TLI.getShiftAmountTy() : TLI.getPointerTy();
+ EVT getShiftAmountTy(EVT LHSTy) {
+ return LegalTypes ? TLI.getShiftAmountTy(LHSTy) : TLI.getPointerTy();
}
/// isTypeLegal - This method returns true if we are running before type
@@ -670,7 +670,7 @@ SDValue DAGCombiner::PromoteOperand(SDValue Op, EVT PVT, bool &Replace) {
if (LoadSDNode *LD = dyn_cast<LoadSDNode>(Op)) {
EVT MemVT = LD->getMemoryVT();
ISD::LoadExtType ExtType = ISD::isNON_EXTLoad(LD)
- ? (TLI.isLoadExtLegal(ISD::ZEXTLOAD, MemVT) ? ISD::ZEXTLOAD
+ ? (TLI.isLoadExtLegal(ISD::ZEXTLOAD, MemVT) ? ISD::ZEXTLOAD
: ISD::EXTLOAD)
: LD->getExtensionType();
Replace = true;
@@ -894,7 +894,7 @@ bool DAGCombiner::PromoteLoad(SDValue Op) {
LoadSDNode *LD = cast<LoadSDNode>(N);
EVT MemVT = LD->getMemoryVT();
ISD::LoadExtType ExtType = ISD::isNON_EXTLoad(LD)
- ? (TLI.isLoadExtLegal(ISD::ZEXTLOAD, MemVT) ? ISD::ZEXTLOAD
+ ? (TLI.isLoadExtLegal(ISD::ZEXTLOAD, MemVT) ? ISD::ZEXTLOAD
: ISD::EXTLOAD)
: LD->getExtensionType();
SDValue NewLD = DAG.getExtLoad(ExtType, dl, PVT,
@@ -1521,7 +1521,7 @@ SDValue DAGCombiner::visitADDE(SDNode *N) {
// Since it may not be valid to emit a fold to zero for vector initializers
// check if we can before folding.
static SDValue tryFoldToZero(DebugLoc DL, const TargetLowering &TLI, EVT VT,
- SelectionDAG &DAG, bool LegalOperations) {
+ SelectionDAG &DAG, bool LegalOperations) {
if (!VT.isVector()) {
return DAG.getConstant(0, VT);
} else if (!LegalOperations || TLI.isOperationLegal(ISD::BUILD_VECTOR, VT)) {
@@ -1647,7 +1647,7 @@ SDValue DAGCombiner::visitMUL(SDNode *N) {
if (N1C && N1C->getAPIntValue().isPowerOf2())
return DAG.getNode(ISD::SHL, N->getDebugLoc(), VT, N0,
DAG.getConstant(N1C->getAPIntValue().logBase2(),
- getShiftAmountTy()));
+ getShiftAmountTy(N0.getValueType())));
// fold (mul x, -(1 << c)) -> -(x << c) or (-x) << c
if (N1C && (-N1C->getAPIntValue()).isPowerOf2()) {
unsigned Log2Val = (-N1C->getAPIntValue()).logBase2();
@@ -1656,7 +1656,8 @@ SDValue DAGCombiner::visitMUL(SDNode *N) {
return DAG.getNode(ISD::SUB, N->getDebugLoc(), VT,
DAG.getConstant(0, VT),
DAG.getNode(ISD::SHL, N->getDebugLoc(), VT, N0,
- DAG.getConstant(Log2Val, getShiftAmountTy())));
+ DAG.getConstant(Log2Val,
+ getShiftAmountTy(N0.getValueType()))));
}
// (mul (shl X, c1), c2) -> (mul X, c2 << c1)
if (N1C && N0.getOpcode() == ISD::SHL &&
@@ -1753,18 +1754,18 @@ SDValue DAGCombiner::visitSDIV(SDNode *N) {
// Splat the sign bit into the register
SDValue SGN = DAG.getNode(ISD::SRA, N->getDebugLoc(), VT, N0,
DAG.getConstant(VT.getSizeInBits()-1,
- getShiftAmountTy()));
+ getShiftAmountTy(N0.getValueType())));
AddToWorkList(SGN.getNode());
// Add (N0 < 0) ? abs2 - 1 : 0;
SDValue SRL = DAG.getNode(ISD::SRL, N->getDebugLoc(), VT, SGN,
DAG.getConstant(VT.getSizeInBits() - lg2,
- getShiftAmountTy()));
+ getShiftAmountTy(SGN.getValueType())));
SDValue ADD = DAG.getNode(ISD::ADD, N->getDebugLoc(), VT, N0, SRL);
AddToWorkList(SRL.getNode());
AddToWorkList(ADD.getNode()); // Divide by pow2
SDValue SRA = DAG.getNode(ISD::SRA, N->getDebugLoc(), VT, ADD,
- DAG.getConstant(lg2, getShiftAmountTy()));
+ DAG.getConstant(lg2, getShiftAmountTy(ADD.getValueType())));
// If we're dividing by a positive value, we're done. Otherwise, we must
// negate the result.
@@ -1814,7 +1815,7 @@ SDValue DAGCombiner::visitUDIV(SDNode *N) {
if (N1C && N1C->getAPIntValue().isPowerOf2())
return DAG.getNode(ISD::SRL, N->getDebugLoc(), VT, N0,
DAG.getConstant(N1C->getAPIntValue().logBase2(),
- getShiftAmountTy()));
+ getShiftAmountTy(N0.getValueType())));
// fold (udiv x, (shl c, y)) -> x >>u (log2(c)+y) iff c is power of 2
if (N1.getOpcode() == ISD::SHL) {
if (ConstantSDNode *SHC = dyn_cast<ConstantSDNode>(N1.getOperand(0))) {
@@ -1955,7 +1956,7 @@ SDValue DAGCombiner::visitMULHS(SDNode *N) {
if (N1C && N1C->getAPIntValue() == 1)
return DAG.getNode(ISD::SRA, N->getDebugLoc(), N0.getValueType(), N0,
DAG.getConstant(N0.getValueType().getSizeInBits() - 1,
- getShiftAmountTy()));
+ getShiftAmountTy(N0.getValueType())));
// fold (mulhs x, undef) -> 0
if (N0.getOpcode() == ISD::UNDEF || N1.getOpcode() == ISD::UNDEF)
return DAG.getConstant(0, VT);
@@ -1971,11 +1972,11 @@ SDValue DAGCombiner::visitMULHS(SDNode *N) {
N1 = DAG.getNode(ISD::SIGN_EXTEND, DL, NewVT, N1);
N1 = DAG.getNode(ISD::MUL, DL, NewVT, N0, N1);
N1 = DAG.getNode(ISD::SRL, DL, NewVT, N1,
- DAG.getConstant(SimpleSize, getShiftAmountTy()));
+ DAG.getConstant(SimpleSize, getShiftAmountTy(N1.getValueType())));
return DAG.getNode(ISD::TRUNCATE, DL, VT, N1);
}
}
-
+
return SDValue();
}
@@ -2007,11 +2008,11 @@ SDValue DAGCombiner::visitMULHU(SDNode *N) {
N1 = DAG.getNode(ISD::ZERO_EXTEND, DL, NewVT, N1);
N1 = DAG.getNode(ISD::MUL, DL, NewVT, N0, N1);
N1 = DAG.getNode(ISD::SRL, DL, NewVT, N1,
- DAG.getConstant(SimpleSize, getShiftAmountTy()));
+ DAG.getConstant(SimpleSize, getShiftAmountTy(N1.getValueType())));
return DAG.getNode(ISD::TRUNCATE, DL, VT, N1);
}
}
-
+
return SDValue();
}
@@ -2090,14 +2091,14 @@ SDValue DAGCombiner::visitSMUL_LOHI(SDNode *N) {
Lo = DAG.getNode(ISD::MUL, DL, NewVT, Lo, Hi);
// Compute the high part as N1.
Hi = DAG.getNode(ISD::SRL, DL, NewVT, Lo,
- DAG.getConstant(SimpleSize, getShiftAmountTy()));
+ DAG.getConstant(SimpleSize, getShiftAmountTy(Lo.getValueType())));
Hi = DAG.getNode(ISD::TRUNCATE, DL, VT, Hi);
// Compute the low part as N0.
Lo = DAG.getNode(ISD::TRUNCATE, DL, VT, Lo);
return CombineTo(N, Lo, Hi);
}
}
-
+
return SDValue();
}
@@ -2107,7 +2108,7 @@ SDValue DAGCombiner::visitUMUL_LOHI(SDNode *N) {
EVT VT = N->getValueType(0);
DebugLoc DL = N->getDebugLoc();
-
+
// If the type twice as wide is legal, transform the mulhu to a wider multiply
// plus a shift.
if (VT.isSimple() && !VT.isVector()) {
@@ -2120,14 +2121,14 @@ SDValue DAGCombiner::visitUMUL_LOHI(SDNode *N) {
Lo = DAG.getNode(ISD::MUL, DL, NewVT, Lo, Hi);
// Compute the high part as N1.
Hi = DAG.getNode(ISD::SRL, DL, NewVT, Lo,
- DAG.getConstant(SimpleSize, getShiftAmountTy()));
+ DAG.getConstant(SimpleSize, getShiftAmountTy(Lo.getValueType())));
Hi = DAG.getNode(ISD::TRUNCATE, DL, VT, Hi);
// Compute the low part as N0.
Lo = DAG.getNode(ISD::TRUNCATE, DL, VT, Lo);
return CombineTo(N, Lo, Hi);
}
}
-
+
return SDValue();
}
@@ -3004,7 +3005,7 @@ SDValue DAGCombiner::visitSHL(SDNode *N) {
N0.getOpcode() == ISD::SIGN_EXTEND) &&
N0.getOperand(0).getOpcode() == ISD::SHL &&
isa<ConstantSDNode>(N0.getOperand(0)->getOperand(1))) {
- uint64_t c1 =
+ uint64_t c1 =
cast<ConstantSDNode>(N0.getOperand(0)->getOperand(1))->getZExtValue();
uint64_t c2 = N1C->getZExtValue();
EVT InnerShiftVT = N0.getOperand(0).getValueType();
@@ -3133,7 +3134,8 @@ SDValue DAGCombiner::visitSRA(SDNode *N) {
TLI.isOperationLegalOrCustom(ISD::TRUNCATE, VT) &&
TLI.isTruncateFree(VT, TruncVT)) {
- SDValue Amt = DAG.getConstant(ShiftAmt, getShiftAmountTy());
+ SDValue Amt = DAG.getConstant(ShiftAmt,
+ getShiftAmountTy(N0.getOperand(0).getValueType()));
SDValue Shift = DAG.getNode(ISD::SRL, N0.getDebugLoc(), VT,
N0.getOperand(0), Amt);
SDValue Trunc = DAG.getNode(ISD::TRUNCATE, N0.getDebugLoc(), TruncVT,
@@ -3180,7 +3182,7 @@ SDValue DAGCombiner::visitSRA(SDNode *N) {
LargeShiftAmt->getZExtValue()) {
SDValue Amt =
DAG.getConstant(LargeShiftAmt->getZExtValue() + N1C->getZExtValue(),
- getShiftAmountTy());
+ getShiftAmountTy(N0.getOperand(0).getOperand(0).getValueType()));
SDValue SRA = DAG.getNode(ISD::SRA, N->getDebugLoc(), LargeVT,
N0.getOperand(0).getOperand(0), Amt);
return DAG.getNode(ISD::TRUNCATE, N->getDebugLoc(), VT, SRA);
@@ -3245,7 +3247,7 @@ SDValue DAGCombiner::visitSRL(SDNode *N) {
if (N1C && N0.getOpcode() == ISD::TRUNCATE &&
N0.getOperand(0).getOpcode() == ISD::SRL &&
isa<ConstantSDNode>(N0.getOperand(0)->getOperand(1))) {
- uint64_t c1 =
+ uint64_t c1 =
cast<ConstantSDNode>(N0.getOperand(0)->getOperand(1))->getZExtValue();
uint64_t c2 = N1C->getZExtValue();
EVT InnerShiftVT = N0.getOperand(0).getValueType();
@@ -3256,7 +3258,7 @@ SDValue DAGCombiner::visitSRL(SDNode *N) {
if (c1 + c2 >= InnerShiftSize)
return DAG.getConstant(0, VT);
return DAG.getNode(ISD::TRUNCATE, N0->getDebugLoc(), VT,
- DAG.getNode(ISD::SRL, N0->getDebugLoc(), InnerShiftVT,
+ DAG.getNode(ISD::SRL, N0->getDebugLoc(), InnerShiftVT,
N0.getOperand(0)->getOperand(0),
DAG.getConstant(c1 + c2, ShiftCountVT)));
}
@@ -3320,7 +3322,7 @@ SDValue DAGCombiner::visitSRL(SDNode *N) {
if (ShAmt) {
Op = DAG.getNode(ISD::SRL, N0.getDebugLoc(), VT, Op,
- DAG.getConstant(ShAmt, getShiftAmountTy()));
+ DAG.getConstant(ShAmt, getShiftAmountTy(Op.getValueType())));
AddToWorkList(Op.getNode());
}
@@ -3685,7 +3687,9 @@ SDValue DAGCombiner::visitSIGN_EXTEND(SDNode *N) {
}
// fold (sext (load x)) -> (sext (truncate (sextload x)))
- if (ISD::isNON_EXTLoad(N0.getNode()) &&
+ // None of the supported targets knows how to perform load and sign extend
+ // in one instruction. We only perform this transformation on scalars.
+ if (ISD::isNON_EXTLoad(N0.getNode()) && !VT.isVector() &&
((!LegalOperations && !cast<LoadSDNode>(N0)->isVolatile()) ||
TLI.isLoadExtLegal(ISD::SEXTLOAD, N0.getValueType()))) {
bool DoXform = true;
@@ -3887,7 +3891,9 @@ SDValue DAGCombiner::visitZERO_EXTEND(SDNode *N) {
}
// fold (zext (load x)) -> (zext (truncate (zextload x)))
- if (ISD::isNON_EXTLoad(N0.getNode()) &&
+ // None of the supported targets knows how to perform load and vector_zext
+ // in one instruction. We only perform this transformation on scalar zext.
+ if (ISD::isNON_EXTLoad(N0.getNode()) && !VT.isVector() &&
((!LegalOperations && !cast<LoadSDNode>(N0)->isVolatile()) ||
TLI.isLoadExtLegal(ISD::ZEXTLOAD, N0.getValueType()))) {
bool DoXform = true;
@@ -4021,11 +4027,11 @@ SDValue DAGCombiner::visitZERO_EXTEND(SDNode *N) {
}
DebugLoc DL = N->getDebugLoc();
-
- // Ensure that the shift amount is wide enough for the shifted value.
+
+ // Ensure that the shift amount is wide enough for the shifted value.
if (VT.getSizeInBits() >= 256)
ShAmt = DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i32, ShAmt);
-
+
return DAG.getNode(N0.getOpcode(), DL, VT,
DAG.getNode(ISD::ZERO_EXTEND, DL, VT, N0.getOperand(0)),
ShAmt);
@@ -4094,7 +4100,9 @@ SDValue DAGCombiner::visitANY_EXTEND(SDNode *N) {
}
// fold (aext (load x)) -> (aext (truncate (extload x)))
- if (ISD::isNON_EXTLoad(N0.getNode()) &&
+ // None of the supported targets knows how to perform load and any_ext
+ // in one instruction. We only perform this transformation on scalars.
+ if (ISD::isNON_EXTLoad(N0.getNode()) && !VT.isVector() &&
((!LegalOperations && !cast<LoadSDNode>(N0)->isVolatile()) ||
TLI.isLoadExtLegal(ISD::EXTLOAD, N0.getValueType()))) {
bool DoXform = true;
@@ -4272,12 +4280,12 @@ SDValue DAGCombiner::ReduceLoadWidth(SDNode *N) {
return SDValue();
unsigned EVTBits = ExtVT.getSizeInBits();
-
+
// Do not generate loads of non-round integer types since these can
// be expensive (and would be wrong if the type is not byte sized).
if (!ExtVT.isRound())
return SDValue();
-
+
unsigned ShAmt = 0;
if (N0.getOpcode() == ISD::SRL && N0.hasOneUse()) {
if (ConstantSDNode *N01 = dyn_cast<ConstantSDNode>(N0.getOperand(1))) {
@@ -4292,7 +4300,7 @@ SDValue DAGCombiner::ReduceLoadWidth(SDNode *N) {
// At this point, we must have a load or else we can't do the transform.
if (!isa<LoadSDNode>(N0)) return SDValue();
-
+
// If the shift amount is larger than the input type then we're not
// accessing any of the loaded bytes. If the load was a zextload/extload
// then the result of the shift+trunc is zero/undef (handled elsewhere).
@@ -4313,18 +4321,18 @@ SDValue DAGCombiner::ReduceLoadWidth(SDNode *N) {
N0 = N0.getOperand(0);
}
}
-
+
// If we haven't found a load, we can't narrow it. Don't transform one with
// multiple uses, this would require adding a new load.
if (!isa<LoadSDNode>(N0) || !N0.hasOneUse() ||
// Don't change the width of a volatile load.
cast<LoadSDNode>(N0)->isVolatile())
return SDValue();
-
+
// Verify that we are actually reducing a load width here.
if (cast<LoadSDNode>(N0)->getMemoryVT().getSizeInBits() < EVTBits)
return SDValue();
-
+
LoadSDNode *LN0 = cast<LoadSDNode>(N0);
EVT PtrType = N0.getOperand(1).getValueType();
@@ -4362,7 +4370,7 @@ SDValue DAGCombiner::ReduceLoadWidth(SDNode *N) {
// Shift the result left, if we've swallowed a left shift.
SDValue Result = Load;
if (ShLeftAmt != 0) {
- EVT ShImmTy = getShiftAmountTy();
+ EVT ShImmTy = getShiftAmountTy(Result.getValueType());
if (!isUIntN(ShImmTy.getSizeInBits(), ShLeftAmt))
ShImmTy = VT;
Result = DAG.getNode(ISD::SHL, N0.getDebugLoc(), VT,
@@ -4504,14 +4512,17 @@ SDValue DAGCombiner::visitTRUNCATE(SDNode *N) {
}
// See if we can simplify the input to this truncate through knowledge that
- // only the low bits are being used. For example "trunc (or (shl x, 8), y)"
- // -> trunc y
- SDValue Shorter =
- GetDemandedBits(N0, APInt::getLowBitsSet(N0.getValueSizeInBits(),
- VT.getSizeInBits()));
- if (Shorter.getNode())
- return DAG.getNode(ISD::TRUNCATE, N->getDebugLoc(), VT, Shorter);
-
+ // only the low bits are being used.
+ // For example "trunc (or (shl x, 8), y)" // -> trunc y
+ // Currenly we only perform this optimization on scalars because vectors
+ // may have different active low bits.
+ if (!VT.isVector()) {
+ SDValue Shorter =
+ GetDemandedBits(N0, APInt::getLowBitsSet(N0.getValueSizeInBits(),
+ VT.getSizeInBits()));
+ if (Shorter.getNode())
+ return DAG.getNode(ISD::TRUNCATE, N->getDebugLoc(), VT, Shorter);
+ }
// fold (truncate (load x)) -> (smaller load x)
// fold (truncate (srl (load x), c)) -> (smaller load (x+c/evtbits))
if (!LegalTypes || TLI.isTypeDesirableForOp(N0.getOpcode(), VT)) {
@@ -5975,7 +5986,8 @@ ShrinkLoadReplaceStoreWithStore(const std::pair<unsigned, unsigned> &MaskInfo,
// shifted by ByteShift and truncated down to NumBytes.
if (ByteShift)
IVal = DAG.getNode(ISD::SRL, IVal->getDebugLoc(), IVal.getValueType(), IVal,
- DAG.getConstant(ByteShift*8, DC->getShiftAmountTy()));
+ DAG.getConstant(ByteShift*8,
+ DC->getShiftAmountTy(IVal.getValueType())));
// Figure out the offset for the store and the alignment of the access.
unsigned StOffset;
@@ -6390,7 +6402,7 @@ SDValue DAGCombiner::visitINSERT_VECTOR_ELT(SDNode *N) {
EVT VT = InVec.getValueType();
- // If we can't generate a legal BUILD_VECTOR, exit
+ // If we can't generate a legal BUILD_VECTOR, exit
if (LegalOperations && !TLI.isOperationLegal(ISD::BUILD_VECTOR, VT))
return SDValue();
@@ -7098,7 +7110,8 @@ SDValue DAGCombiner::SimplifySelectCC(DebugLoc DL, SDValue N0, SDValue N1,
if (N2C && ((N2C->getAPIntValue() & (N2C->getAPIntValue()-1)) == 0)) {
unsigned ShCtV = N2C->getAPIntValue().logBase2();
ShCtV = XType.getSizeInBits()-ShCtV-1;
- SDValue ShCt = DAG.getConstant(ShCtV, getShiftAmountTy());
+ SDValue ShCt = DAG.getConstant(ShCtV,
+ getShiftAmountTy(N0.getValueType()));
SDValue Shift = DAG.getNode(ISD::SRL, N0.getDebugLoc(),
XType, N0, ShCt);
AddToWorkList(Shift.getNode());
@@ -7114,7 +7127,7 @@ SDValue DAGCombiner::SimplifySelectCC(DebugLoc DL, SDValue N0, SDValue N1,
SDValue Shift = DAG.getNode(ISD::SRA, N0.getDebugLoc(),
XType, N0,
DAG.getConstant(XType.getSizeInBits()-1,
- getShiftAmountTy()));
+ getShiftAmountTy(N0.getValueType())));
AddToWorkList(Shift.getNode());
if (XType.bitsGT(AType)) {
@@ -7142,13 +7155,15 @@ SDValue DAGCombiner::SimplifySelectCC(DebugLoc DL, SDValue N0, SDValue N1,
// Shift the tested bit over the sign bit.
APInt AndMask = ConstAndRHS->getAPIntValue();
SDValue ShlAmt =
- DAG.getConstant(AndMask.countLeadingZeros(), getShiftAmountTy());
+ DAG.getConstant(AndMask.countLeadingZeros(),
+ getShiftAmountTy(AndLHS.getValueType()));
SDValue Shl = DAG.getNode(ISD::SHL, N0.getDebugLoc(), VT, AndLHS, ShlAmt);
// Now arithmetic right shift it all the way over, so the result is either
// all-ones, or zero.
SDValue ShrAmt =
- DAG.getConstant(AndMask.getBitWidth()-1, getShiftAmountTy());
+ DAG.getConstant(AndMask.getBitWidth()-1,
+ getShiftAmountTy(Shl.getValueType()));
SDValue Shr = DAG.getNode(ISD::SRA, N0.getDebugLoc(), VT, Shl, ShrAmt);
return DAG.getNode(ISD::AND, DL, VT, Shr, N3);
@@ -7192,7 +7207,7 @@ SDValue DAGCombiner::SimplifySelectCC(DebugLoc DL, SDValue N0, SDValue N1,
// shl setcc result by log2 n2c
return DAG.getNode(ISD::SHL, DL, N2.getValueType(), Temp,
DAG.getConstant(N2C->getAPIntValue().logBase2(),
- getShiftAmountTy()));
+ getShiftAmountTy(Temp.getValueType())));
}
// Check to see if this is the equivalent of setcc
@@ -7215,7 +7230,7 @@ SDValue DAGCombiner::SimplifySelectCC(DebugLoc DL, SDValue N0, SDValue N1,
SDValue Ctlz = DAG.getNode(ISD::CTLZ, N0.getDebugLoc(), XType, N0);
return DAG.getNode(ISD::SRL, DL, XType, Ctlz,
DAG.getConstant(Log2_32(XType.getSizeInBits()),
- getShiftAmountTy()));
+ getShiftAmountTy(Ctlz.getValueType())));
}
// fold (setgt X, 0) -> (srl (and (-X, ~X), size(X)-1))
if (N1C && N1C->isNullValue() && CC == ISD::SETGT) {
@@ -7225,13 +7240,13 @@ SDValue DAGCombiner::SimplifySelectCC(DebugLoc DL, SDValue N0, SDValue N1,
return DAG.getNode(ISD::SRL, DL, XType,
DAG.getNode(ISD::AND, DL, XType, NegN0, NotN0),
DAG.getConstant(XType.getSizeInBits()-1,
- getShiftAmountTy()));
+ getShiftAmountTy(XType)));
}
// fold (setgt X, -1) -> (xor (srl (X, size(X)-1), 1))
if (N1C && N1C->isAllOnesValue() && CC == ISD::SETGT) {
SDValue Sign = DAG.getNode(ISD::SRL, N0.getDebugLoc(), XType, N0,
DAG.getConstant(XType.getSizeInBits()-1,
- getShiftAmountTy()));
+ getShiftAmountTy(N0.getValueType())));
return DAG.getNode(ISD::XOR, DL, XType, Sign, DAG.getConstant(1, XType));
}
}
@@ -7258,7 +7273,7 @@ SDValue DAGCombiner::SimplifySelectCC(DebugLoc DL, SDValue N0, SDValue N1,
SDValue Shift = DAG.getNode(ISD::SRA, N0.getDebugLoc(), XType,
N0,
DAG.getConstant(XType.getSizeInBits()-1,
- getShiftAmountTy()));
+ getShiftAmountTy(N0.getValueType())));
SDValue Add = DAG.getNode(ISD::ADD, N0.getDebugLoc(),
XType, N0, Shift);
AddToWorkList(Shift.getNode());
diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp b/contrib/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
index 98582ba..2ae3286 100644
--- a/contrib/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
+++ b/contrib/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
@@ -219,6 +219,7 @@ void FunctionLoweringInfo::clear() {
CatchInfoFound.clear();
#endif
LiveOutRegInfo.clear();
+ VisitedBBs.clear();
ArgDbgValues.clear();
ByValArgFrameIndexMap.clear();
RegFixups.clear();
@@ -254,6 +255,123 @@ unsigned FunctionLoweringInfo::CreateRegs(const Type *Ty) {
return FirstReg;
}
+/// GetLiveOutRegInfo - Gets LiveOutInfo for a register, returning NULL if the
+/// register is a PHI destination and the PHI's LiveOutInfo is not valid. If
+/// the register's LiveOutInfo is for a smaller bit width, it is extended to
+/// the larger bit width by zero extension. The bit width must be no smaller
+/// than the LiveOutInfo's existing bit width.
+const FunctionLoweringInfo::LiveOutInfo *
+FunctionLoweringInfo::GetLiveOutRegInfo(unsigned Reg, unsigned BitWidth) {
+ if (!LiveOutRegInfo.inBounds(Reg))
+ return NULL;
+
+ LiveOutInfo *LOI = &LiveOutRegInfo[Reg];
+ if (!LOI->IsValid)
+ return NULL;
+
+ if (BitWidth > LOI->KnownZero.getBitWidth()) {
+ LOI->NumSignBits = 1;
+ LOI->KnownZero = LOI->KnownZero.zextOrTrunc(BitWidth);
+ LOI->KnownOne = LOI->KnownOne.zextOrTrunc(BitWidth);
+ }
+
+ return LOI;
+}
+
+/// ComputePHILiveOutRegInfo - Compute LiveOutInfo for a PHI's destination
+/// register based on the LiveOutInfo of its operands.
+void FunctionLoweringInfo::ComputePHILiveOutRegInfo(const PHINode *PN) {
+ const Type *Ty = PN->getType();
+ if (!Ty->isIntegerTy() || Ty->isVectorTy())
+ return;
+
+ SmallVector<EVT, 1> ValueVTs;
+ ComputeValueVTs(TLI, Ty, ValueVTs);
+ assert(ValueVTs.size() == 1 &&
+ "PHIs with non-vector integer types should have a single VT.");
+ EVT IntVT = ValueVTs[0];
+
+ if (TLI.getNumRegisters(PN->getContext(), IntVT) != 1)
+ return;
+ IntVT = TLI.getTypeToTransformTo(PN->getContext(), IntVT);
+ unsigned BitWidth = IntVT.getSizeInBits();
+
+ unsigned DestReg = ValueMap[PN];
+ if (!TargetRegisterInfo::isVirtualRegister(DestReg))
+ return;
+ LiveOutRegInfo.grow(DestReg);
+ LiveOutInfo &DestLOI = LiveOutRegInfo[DestReg];
+
+ Value *V = PN->getIncomingValue(0);
+ if (isa<UndefValue>(V) || isa<ConstantExpr>(V)) {
+ DestLOI.NumSignBits = 1;
+ APInt Zero(BitWidth, 0);
+ DestLOI.KnownZero = Zero;
+ DestLOI.KnownOne = Zero;
+ return;
+ }
+
+ if (ConstantInt *CI = dyn_cast<ConstantInt>(V)) {
+ APInt Val = CI->getValue().zextOrTrunc(BitWidth);
+ DestLOI.NumSignBits = Val.getNumSignBits();
+ DestLOI.KnownZero = ~Val;
+ DestLOI.KnownOne = Val;
+ } else {
+ assert(ValueMap.count(V) && "V should have been placed in ValueMap when its"
+ "CopyToReg node was created.");
+ unsigned SrcReg = ValueMap[V];
+ if (!TargetRegisterInfo::isVirtualRegister(SrcReg)) {
+ DestLOI.IsValid = false;
+ return;
+ }
+ const LiveOutInfo *SrcLOI = GetLiveOutRegInfo(SrcReg, BitWidth);
+ if (!SrcLOI) {
+ DestLOI.IsValid = false;
+ return;
+ }
+ DestLOI = *SrcLOI;
+ }
+
+ assert(DestLOI.KnownZero.getBitWidth() == BitWidth &&
+ DestLOI.KnownOne.getBitWidth() == BitWidth &&
+ "Masks should have the same bit width as the type.");
+
+ for (unsigned i = 1, e = PN->getNumIncomingValues(); i != e; ++i) {
+ Value *V = PN->getIncomingValue(i);
+ if (isa<UndefValue>(V) || isa<ConstantExpr>(V)) {
+ DestLOI.NumSignBits = 1;
+ APInt Zero(BitWidth, 0);
+ DestLOI.KnownZero = Zero;
+ DestLOI.KnownOne = Zero;
+ return;
+ }
+
+ if (ConstantInt *CI = dyn_cast<ConstantInt>(V)) {
+ APInt Val = CI->getValue().zextOrTrunc(BitWidth);
+ DestLOI.NumSignBits = std::min(DestLOI.NumSignBits, Val.getNumSignBits());
+ DestLOI.KnownZero &= ~Val;
+ DestLOI.KnownOne &= Val;
+ continue;
+ }
+
+ assert(ValueMap.count(V) && "V should have been placed in ValueMap when "
+ "its CopyToReg node was created.");
+ unsigned SrcReg = ValueMap[V];
+ if (!TargetRegisterInfo::isVirtualRegister(SrcReg)) {
+ DestLOI.IsValid = false;
+ return;
+ }
+ const LiveOutInfo *SrcLOI = GetLiveOutRegInfo(SrcReg, BitWidth);
+ if (!SrcLOI) {
+ DestLOI.IsValid = false;
+ return;
+ }
+ DestLOI.NumSignBits = std::min(DestLOI.NumSignBits, SrcLOI->NumSignBits);
+ DestLOI.KnownZero &= SrcLOI->KnownZero;
+ DestLOI.KnownOne &= SrcLOI->KnownOne;
+ }
+}
+
/// setByValArgumentFrameIndex - Record frame index for the byval
/// argument. This overrides previous frame index entry for this argument,
/// if any.
diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
index 49c862c..f08528f 100644
--- a/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
+++ b/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
@@ -87,7 +87,7 @@ class SelectionDAGLegalize {
// If someone requests legalization of the new node, return itself.
if (From != To)
LegalizedNodes.insert(std::make_pair(To, To));
-
+
// Transfer SDDbgValues.
DAG.TransferDbgValues(From, To);
}
@@ -498,7 +498,8 @@ SDValue ExpandUnalignedStore(StoreSDNode *ST, SelectionDAG &DAG,
int IncrementSize = NumBits / 8;
// Divide the stored value in two parts.
- SDValue ShiftAmount = DAG.getConstant(NumBits, TLI.getShiftAmountTy());
+ SDValue ShiftAmount = DAG.getConstant(NumBits,
+ TLI.getShiftAmountTy(Val.getValueType()));
SDValue Lo = Val;
SDValue Hi = DAG.getNode(ISD::SRL, dl, VT, Val, ShiftAmount);
@@ -645,7 +646,8 @@ SDValue ExpandUnalignedLoad(LoadSDNode *LD, SelectionDAG &DAG,
}
// aggregate the two parts
- SDValue ShiftAmount = DAG.getConstant(NumBits, TLI.getShiftAmountTy());
+ SDValue ShiftAmount = DAG.getConstant(NumBits,
+ TLI.getShiftAmountTy(Hi.getValueType()));
SDValue Result = DAG.getNode(ISD::SHL, dl, VT, Hi, ShiftAmount);
Result = DAG.getNode(ISD::OR, dl, VT, Result, Lo);
@@ -1264,7 +1266,8 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) {
// Move the top bits to the right place.
Hi = DAG.getNode(ISD::SHL, dl, Hi.getValueType(), Hi,
- DAG.getConstant(RoundWidth, TLI.getShiftAmountTy()));
+ DAG.getConstant(RoundWidth,
+ TLI.getShiftAmountTy(Hi.getValueType())));
// Join the hi and lo parts.
Result = DAG.getNode(ISD::OR, dl, Node->getValueType(0), Lo, Hi);
@@ -1293,7 +1296,8 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) {
// Move the top bits to the right place.
Hi = DAG.getNode(ISD::SHL, dl, Hi.getValueType(), Hi,
- DAG.getConstant(ExtraWidth, TLI.getShiftAmountTy()));
+ DAG.getConstant(ExtraWidth,
+ TLI.getShiftAmountTy(Hi.getValueType())));
// Join the hi and lo parts.
Result = DAG.getNode(ISD::OR, dl, Node->getValueType(0), Lo, Hi);
@@ -1482,7 +1486,8 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) {
Tmp2 = DAG.getNode(ISD::ADD, dl, Tmp2.getValueType(), Tmp2,
DAG.getIntPtrConstant(IncrementSize));
Hi = DAG.getNode(ISD::SRL, dl, Tmp3.getValueType(), Tmp3,
- DAG.getConstant(RoundWidth, TLI.getShiftAmountTy()));
+ DAG.getConstant(RoundWidth,
+ TLI.getShiftAmountTy(Tmp3.getValueType())));
Hi = DAG.getTruncStore(Tmp1, dl, Hi, Tmp2,
ST->getPointerInfo().getWithOffset(IncrementSize),
ExtraVT, isVolatile, isNonTemporal,
@@ -1492,7 +1497,8 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) {
// TRUNCSTORE:i24 X -> TRUNCSTORE:i16 (srl X, 8), TRUNCSTORE@+2:i8 X
// Store the top RoundWidth bits.
Hi = DAG.getNode(ISD::SRL, dl, Tmp3.getValueType(), Tmp3,
- DAG.getConstant(ExtraWidth, TLI.getShiftAmountTy()));
+ DAG.getConstant(ExtraWidth,
+ TLI.getShiftAmountTy(Tmp3.getValueType())));
Hi = DAG.getTruncStore(Tmp1, dl, Hi, Tmp2, ST->getPointerInfo(),
RoundVT, isVolatile, isNonTemporal, Alignment);
@@ -1727,7 +1733,8 @@ SDValue SelectionDAGLegalize::ExpandFCOPYSIGN(SDNode* Node) {
assert(BitShift < LoadTy.getSizeInBits() && "Pointer advanced wrong?");
if (BitShift)
SignBit = DAG.getNode(ISD::SHL, dl, LoadTy, SignBit,
- DAG.getConstant(BitShift,TLI.getShiftAmountTy()));
+ DAG.getConstant(BitShift,
+ TLI.getShiftAmountTy(SignBit.getValueType())));
}
}
// Now get the sign bit proper, by seeing whether the value is negative.
@@ -2207,7 +2214,8 @@ SDValue SelectionDAGLegalize::ExpandLegalINT_TO_FP(bool isSigned,
if (!isSigned) {
SDValue Fast = DAG.getNode(ISD::SINT_TO_FP, dl, MVT::f32, Op0);
- SDValue ShiftConst = DAG.getConstant(1, TLI.getShiftAmountTy());
+ SDValue ShiftConst =
+ DAG.getConstant(1, TLI.getShiftAmountTy(Op0.getValueType()));
SDValue Shr = DAG.getNode(ISD::SRL, dl, MVT::i64, Op0, ShiftConst);
SDValue AndConst = DAG.getConstant(1, MVT::i64);
SDValue And = DAG.getNode(ISD::AND, dl, MVT::i64, Op0, AndConst);
@@ -2226,7 +2234,6 @@ SDValue SelectionDAGLegalize::ExpandLegalINT_TO_FP(bool isSigned,
}
// Otherwise, implement the fully general conversion.
- EVT SHVT = TLI.getShiftAmountTy();
SDValue And = DAG.getNode(ISD::AND, dl, MVT::i64, Op0,
DAG.getConstant(UINT64_C(0xfffffffffffff800), MVT::i64));
@@ -2241,6 +2248,7 @@ SDValue SelectionDAGLegalize::ExpandLegalINT_TO_FP(bool isSigned,
Op0, DAG.getConstant(UINT64_C(0x0020000000000000), MVT::i64),
ISD::SETUGE);
SDValue Sel2 = DAG.getNode(ISD::SELECT, dl, MVT::i64, Ge, Sel, Op0);
+ EVT SHVT = TLI.getShiftAmountTy(Sel2.getValueType());
SDValue Sh = DAG.getNode(ISD::SRL, dl, MVT::i64, Sel2,
DAG.getConstant(32, SHVT));
@@ -2387,7 +2395,7 @@ SDValue SelectionDAGLegalize::PromoteLegalFP_TO_INT(SDValue LegalOp,
///
SDValue SelectionDAGLegalize::ExpandBSWAP(SDValue Op, DebugLoc dl) {
EVT VT = Op.getValueType();
- EVT SHVT = TLI.getShiftAmountTy();
+ EVT SHVT = TLI.getShiftAmountTy(VT);
SDValue Tmp1, Tmp2, Tmp3, Tmp4, Tmp5, Tmp6, Tmp7, Tmp8;
switch (VT.getSimpleVT().SimpleTy) {
default: assert(0 && "Unhandled Expand type in BSWAP!");
@@ -2450,7 +2458,7 @@ SDValue SelectionDAGLegalize::ExpandBitCount(unsigned Opc, SDValue Op,
default: assert(0 && "Cannot expand this yet!");
case ISD::CTPOP: {
EVT VT = Op.getValueType();
- EVT ShVT = TLI.getShiftAmountTy();
+ EVT ShVT = TLI.getShiftAmountTy(VT);
unsigned Len = VT.getSizeInBits();
assert(VT.isInteger() && Len <= 128 && Len % 8 == 0 &&
@@ -2487,7 +2495,7 @@ SDValue SelectionDAGLegalize::ExpandBitCount(unsigned Opc, SDValue Op,
Op = DAG.getNode(ISD::SRL, dl, VT,
DAG.getNode(ISD::MUL, dl, VT, Op, Mask01),
DAG.getConstant(Len - 8, ShVT));
-
+
return Op;
}
case ISD::CTLZ: {
@@ -2501,7 +2509,7 @@ SDValue SelectionDAGLegalize::ExpandBitCount(unsigned Opc, SDValue Op,
//
// but see also: http://www.hackersdelight.org/HDcode/nlz.cc
EVT VT = Op.getValueType();
- EVT ShVT = TLI.getShiftAmountTy();
+ EVT ShVT = TLI.getShiftAmountTy(VT);
unsigned len = VT.getSizeInBits();
for (unsigned i = 0; (1U << i) <= (len / 2); ++i) {
SDValue Tmp3 = DAG.getConstant(1ULL << i, ShVT);
@@ -2737,7 +2745,7 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node,
// SAR. However, it is doubtful that any exist.
EVT ExtraVT = cast<VTSDNode>(Node->getOperand(1))->getVT();
EVT VT = Node->getValueType(0);
- EVT ShiftAmountTy = TLI.getShiftAmountTy();
+ EVT ShiftAmountTy = TLI.getShiftAmountTy(VT);
if (VT.isVector())
ShiftAmountTy = VT;
unsigned BitsDiff = VT.getScalarType().getSizeInBits() -
@@ -2901,7 +2909,7 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node,
// 1 -> Hi
Tmp1 = DAG.getNode(ISD::SRL, dl, OpTy, Node->getOperand(0),
DAG.getConstant(OpTy.getSizeInBits()/2,
- TLI.getShiftAmountTy()));
+ TLI.getShiftAmountTy(Node->getOperand(0).getValueType())));
Tmp1 = DAG.getNode(ISD::TRUNCATE, dl, Node->getValueType(0), Tmp1);
} else {
// 0 -> Lo
@@ -3260,7 +3268,7 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node,
assert(LC != RTLIB::UNKNOWN_LIBCALL && "Cannot expand this operation!");
LHS = DAG.getNode(Ops[isSigned][2], dl, WideVT, LHS);
RHS = DAG.getNode(Ops[isSigned][2], dl, WideVT, RHS);
-
+
SDValue Ret = ExpandLibCall(LC, Node, isSigned);
BottomHalf = DAG.getNode(ISD::TRUNCATE, dl, VT, Ret);
TopHalf = DAG.getNode(ISD::SRL, dl, Ret.getValueType(), Ret,
@@ -3268,7 +3276,8 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node,
TopHalf = DAG.getNode(ISD::TRUNCATE, dl, VT, TopHalf);
}
if (isSigned) {
- Tmp1 = DAG.getConstant(VT.getSizeInBits() - 1, TLI.getShiftAmountTy());
+ Tmp1 = DAG.getConstant(VT.getSizeInBits() - 1,
+ TLI.getShiftAmountTy(BottomHalf.getValueType()));
Tmp1 = DAG.getNode(ISD::SRA, dl, VT, BottomHalf, Tmp1);
TopHalf = DAG.getSetCC(dl, TLI.getSetCCResultType(VT), TopHalf, Tmp1,
ISD::SETNE);
@@ -3286,7 +3295,7 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node,
Tmp2 = DAG.getNode(ISD::ANY_EXTEND, dl, PairTy, Node->getOperand(1));
Tmp2 = DAG.getNode(ISD::SHL, dl, PairTy, Tmp2,
DAG.getConstant(PairTy.getSizeInBits()/2,
- TLI.getShiftAmountTy()));
+ TLI.getShiftAmountTy(PairTy)));
Results.push_back(DAG.getNode(ISD::OR, dl, PairTy, Tmp1, Tmp2));
break;
}
@@ -3464,7 +3473,7 @@ void SelectionDAGLegalize::PromoteNode(SDNode *Node,
Tmp1 = DAG.getNode(ISD::ZERO_EXTEND, dl, NVT, Node->getOperand(0));
Tmp1 = DAG.getNode(ISD::BSWAP, dl, NVT, Tmp1);
Tmp1 = DAG.getNode(ISD::SRL, dl, NVT, Tmp1,
- DAG.getConstant(DiffBits, TLI.getShiftAmountTy()));
+ DAG.getConstant(DiffBits, TLI.getShiftAmountTy(NVT)));
Results.push_back(Tmp1);
break;
}
diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp b/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
index 2775212..27a466b 100644
--- a/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
+++ b/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
@@ -177,25 +177,27 @@ SDValue DAGTypeLegalizer::SoftenFloatRes_FCOPYSIGN(SDNode *N) {
// First get the sign bit of second operand.
SDValue SignBit = DAG.getNode(ISD::SHL, dl, RVT, DAG.getConstant(1, RVT),
DAG.getConstant(RSize - 1,
- TLI.getShiftAmountTy()));
+ TLI.getShiftAmountTy(RVT)));
SignBit = DAG.getNode(ISD::AND, dl, RVT, RHS, SignBit);
// Shift right or sign-extend it if the two operands have different types.
int SizeDiff = RVT.getSizeInBits() - LVT.getSizeInBits();
if (SizeDiff > 0) {
SignBit = DAG.getNode(ISD::SRL, dl, RVT, SignBit,
- DAG.getConstant(SizeDiff, TLI.getShiftAmountTy()));
+ DAG.getConstant(SizeDiff,
+ TLI.getShiftAmountTy(SignBit.getValueType())));
SignBit = DAG.getNode(ISD::TRUNCATE, dl, LVT, SignBit);
} else if (SizeDiff < 0) {
SignBit = DAG.getNode(ISD::ANY_EXTEND, dl, LVT, SignBit);
SignBit = DAG.getNode(ISD::SHL, dl, LVT, SignBit,
- DAG.getConstant(-SizeDiff, TLI.getShiftAmountTy()));
+ DAG.getConstant(-SizeDiff,
+ TLI.getShiftAmountTy(SignBit.getValueType())));
}
// Clear the sign bit of the first operand.
SDValue Mask = DAG.getNode(ISD::SHL, dl, LVT, DAG.getConstant(1, LVT),
DAG.getConstant(LSize - 1,
- TLI.getShiftAmountTy()));
+ TLI.getShiftAmountTy(LVT)));
Mask = DAG.getNode(ISD::SUB, dl, LVT, Mask, DAG.getConstant(1, LVT));
LHS = DAG.getNode(ISD::AND, dl, LVT, LHS, Mask);
diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 2fb2f2d..9120288 100644
--- a/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -1420,7 +1420,7 @@ SDValue SelectionDAG::getMDNode(const MDNode *MD) {
/// the target's desired shift amount type.
SDValue SelectionDAG::getShiftAmountOperand(SDValue Op) {
EVT OpTy = Op.getValueType();
- MVT ShTy = TLI.getShiftAmountTy();
+ MVT ShTy = TLI.getShiftAmountTy(OpTy);
if (OpTy == ShTy || OpTy.isVector()) return Op;
ISD::NodeType Opcode = OpTy.bitsGT(ShTy) ? ISD::TRUNCATE : ISD::ZERO_EXTEND;
@@ -2048,7 +2048,7 @@ void SelectionDAG::ComputeMaskedBits(SDValue Op, const APInt &Mask,
return;
}
break;
-
+
default:
// Allow the target to implement this method for its nodes.
if (Op.getOpcode() >= ISD::BUILTIN_OP_END) {
@@ -2088,12 +2088,7 @@ unsigned SelectionDAG::ComputeNumSignBits(SDValue Op, unsigned Depth) const{
case ISD::Constant: {
const APInt &Val = cast<ConstantSDNode>(Op)->getAPIntValue();
- // If negative, return # leading ones.
- if (Val.isNegative())
- return Val.countLeadingOnes();
-
- // Return # leading zeros.
- return Val.countLeadingZeros();
+ return Val.getNumSignBits();
}
case ISD::SIGN_EXTEND:
@@ -2297,12 +2292,12 @@ bool SelectionDAG::isBaseWithConstantOffset(SDValue Op) const {
if ((Op.getOpcode() != ISD::ADD && Op.getOpcode() != ISD::OR) ||
!isa<ConstantSDNode>(Op.getOperand(1)))
return false;
-
- if (Op.getOpcode() == ISD::OR &&
+
+ if (Op.getOpcode() == ISD::OR &&
!MaskedValueIsZero(Op.getOperand(0),
cast<ConstantSDNode>(Op.getOperand(1))->getAPIntValue()))
return false;
-
+
return true;
}
@@ -2753,7 +2748,7 @@ SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, EVT VT,
// i8, which is easy to fall into in generic code that uses
// TLI.getShiftAmount().
assert(N2.getValueType().getSizeInBits() >=
- Log2_32_Ceil(N1.getValueType().getSizeInBits()) &&
+ Log2_32_Ceil(N1.getValueType().getSizeInBits()) &&
"Invalid use of small shift amount with oversized value!");
// Always fold shifts of i1 values so the code generator doesn't need to
diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 452f561..48d9bbb 100644
--- a/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -641,16 +641,17 @@ SDValue RegsForValue::getCopyFromRegs(SelectionDAG &DAG,
// If the source register was virtual and if we know something about it,
// add an assert node.
if (!TargetRegisterInfo::isVirtualRegister(Regs[Part+i]) ||
- !RegisterVT.isInteger() || RegisterVT.isVector() ||
- !FuncInfo.LiveOutRegInfo.inBounds(Regs[Part+i]))
+ !RegisterVT.isInteger() || RegisterVT.isVector())
+ continue;
+
+ const FunctionLoweringInfo::LiveOutInfo *LOI =
+ FuncInfo.GetLiveOutRegInfo(Regs[Part+i]);
+ if (!LOI)
continue;
-
- const FunctionLoweringInfo::LiveOutInfo &LOI =
- FuncInfo.LiveOutRegInfo[Regs[Part+i]];
unsigned RegSize = RegisterVT.getSizeInBits();
- unsigned NumSignBits = LOI.NumSignBits;
- unsigned NumZeroBits = LOI.KnownZero.countLeadingOnes();
+ unsigned NumSignBits = LOI->NumSignBits;
+ unsigned NumZeroBits = LOI->KnownZero.countLeadingOnes();
// FIXME: We capture more information than the dag can represent. For
// now, just use the tightest assertzext/assertsext possible.
@@ -908,7 +909,7 @@ void SelectionDAGBuilder::resolveDanglingDebugInfo(const Value *V,
Val.getResNo(), Offset, dl, DbgSDNodeOrder);
DAG.AddDbgValue(SDV, Val.getNode(), false);
}
- } else
+ } else
DEBUG(dbgs() << "Dropping debug info for " << DI);
DanglingDebugInfoMap[V] = DanglingDebugInfo();
}
@@ -1417,7 +1418,7 @@ void SelectionDAGBuilder::visitBr(const BranchInst &I) {
// jle foo
//
if (const BinaryOperator *BOp = dyn_cast<BinaryOperator>(CondVal)) {
- if (!TLI.isJumpExpensive() &&
+ if (!TLI.isJumpExpensive() &&
BOp->hasOneUse() &&
(BOp->getOpcode() == Instruction::And ||
BOp->getOpcode() == Instruction::Or)) {
@@ -1915,7 +1916,7 @@ bool SelectionDAGBuilder::handleJTSwitchCase(CaseRec& CR,
DEBUG(dbgs() << "Lowering jump table\n"
<< "First entry: " << First << ". Last entry: " << Last << '\n'
<< "Range: " << Range
- << "Size: " << TSize << ". Density: " << Density << "\n\n");
+ << ". Size: " << TSize << ". Density: " << Density << "\n\n");
// Get the MachineFunction which holds the current MBB. This is used when
// inserting any additional MBBs necessary to represent the switch.
@@ -2408,19 +2409,19 @@ void SelectionDAGBuilder::visitBinary(const User &I, unsigned OpCode) {
void SelectionDAGBuilder::visitShift(const User &I, unsigned Opcode) {
SDValue Op1 = getValue(I.getOperand(0));
SDValue Op2 = getValue(I.getOperand(1));
-
- MVT ShiftTy = TLI.getShiftAmountTy();
-
+
+ MVT ShiftTy = TLI.getShiftAmountTy(Op2.getValueType());
+
// Coerce the shift amount to the right type if we can.
if (!I.getType()->isVectorTy() && Op2.getValueType() != ShiftTy) {
unsigned ShiftSize = ShiftTy.getSizeInBits();
unsigned Op2Size = Op2.getValueType().getSizeInBits();
DebugLoc DL = getCurDebugLoc();
-
+
// If the operand is smaller than the shift count type, promote it.
if (ShiftSize > Op2Size)
Op2 = DAG.getNode(ISD::ZERO_EXTEND, DL, ShiftTy, Op2);
-
+
// If the operand is larger than the shift count type but the shift
// count type has enough bits to represent any shift value, truncate
// it now. This is a common case and it exposes the truncate to
diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h b/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
index a1a70c3..8f466d9 100644
--- a/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
+++ b/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
@@ -348,7 +348,7 @@ public:
SDValue getControlRoot();
DebugLoc getCurDebugLoc() const { return CurDebugLoc; }
- void setCurDebugLoc(DebugLoc dl){ CurDebugLoc = dl; }
+
unsigned getSDNodeOrder() const { return SDNodeOrder; }
void CopyValueToVirtualRegister(const Value *V, unsigned Reg);
diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
index 62ebc81..68ba966 100644
--- a/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -49,6 +49,7 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/ADT/Statistic.h"
#include <algorithm>
using namespace llvm;
@@ -479,16 +480,7 @@ void SelectionDAGISel::ComputeLiveOutVRegInfo() {
unsigned NumSignBits = CurDAG->ComputeNumSignBits(Src);
Mask = APInt::getAllOnesValue(SrcVT.getSizeInBits());
CurDAG->ComputeMaskedBits(Src, Mask, KnownZero, KnownOne);
-
- // Only install this information if it tells us something.
- if (NumSignBits != 1 || KnownZero != 0 || KnownOne != 0) {
- FuncInfo->LiveOutRegInfo.grow(DestReg);
- FunctionLoweringInfo::LiveOutInfo &LOI =
- FuncInfo->LiveOutRegInfo[DestReg];
- LOI.NumSignBits = NumSignBits;
- LOI.KnownOne = KnownOne;
- LOI.KnownZero = KnownZero;
- }
+ FuncInfo->AddLiveOutRegInfo(DestReg, NumSignBits, KnownZero, KnownOne);
} while (!Worklist.empty());
}
@@ -832,11 +824,39 @@ void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn) {
FastIS = TLI.createFastISel(*FuncInfo);
// Iterate over all basic blocks in the function.
- for (Function::const_iterator I = Fn.begin(), E = Fn.end(); I != E; ++I) {
- const BasicBlock *LLVMBB = &*I;
+ ReversePostOrderTraversal<const Function*> RPOT(&Fn);
+ for (ReversePostOrderTraversal<const Function*>::rpo_iterator
+ I = RPOT.begin(), E = RPOT.end(); I != E; ++I) {
+ const BasicBlock *LLVMBB = *I;
#ifndef NDEBUG
CheckLineNumbers(LLVMBB);
#endif
+
+ if (OptLevel != CodeGenOpt::None) {
+ bool AllPredsVisited = true;
+ for (const_pred_iterator PI = pred_begin(LLVMBB), PE = pred_end(LLVMBB);
+ PI != PE; ++PI) {
+ if (!FuncInfo->VisitedBBs.count(*PI)) {
+ AllPredsVisited = false;
+ break;
+ }
+ }
+
+ if (AllPredsVisited) {
+ for (BasicBlock::const_iterator I = LLVMBB->begin(), E = LLVMBB->end();
+ I != E && isa<PHINode>(I); ++I) {
+ FuncInfo->ComputePHILiveOutRegInfo(cast<PHINode>(I));
+ }
+ } else {
+ for (BasicBlock::const_iterator I = LLVMBB->begin(), E = LLVMBB->end();
+ I != E && isa<PHINode>(I); ++I) {
+ FuncInfo->InvalidatePHILiveOutRegInfo(cast<PHINode>(I));
+ }
+ }
+
+ FuncInfo->VisitedBBs.insert(LLVMBB);
+ }
+
FuncInfo->MBB = FuncInfo->MBBMap[LLVMBB];
FuncInfo->InsertPt = FuncInfo->MBB->getFirstNonPHI();
@@ -851,17 +871,8 @@ void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn) {
PrepareEHLandingPad();
// Lower any arguments needed in this block if this is the entry block.
- if (LLVMBB == &Fn.getEntryBlock()) {
- for (BasicBlock::const_iterator DBI = LLVMBB->begin(), DBE = LLVMBB->end();
- DBI != DBE; ++DBI) {
- if (const DbgInfoIntrinsic *DI = dyn_cast<DbgInfoIntrinsic>(DBI)) {
- const DebugLoc DL = DI->getDebugLoc();
- SDB->setCurDebugLoc(DL);
- break;
- }
- }
+ if (LLVMBB == &Fn.getEntryBlock())
LowerArguments(LLVMBB);
- }
// Before doing SelectionDAG ISel, see if FastISel has been requested.
if (FastIS) {
diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/contrib/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index 691390e..35b847c 100644
--- a/contrib/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/contrib/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -563,7 +563,7 @@ TargetLowering::TargetLowering(const TargetMachine &tm,
setOperationAction(ISD::TRAP, MVT::Other, Expand);
IsLittleEndian = TD->isLittleEndian();
- ShiftAmountTy = PointerTy = MVT::getIntegerVT(8*TD->getPointerSize());
+ PointerTy = MVT::getIntegerVT(8*TD->getPointerSize());
memset(RegClassForVT, 0,MVT::LAST_VALUETYPE*sizeof(TargetRegisterClass*));
memset(TargetDAGCombineArray, 0, array_lengthof(TargetDAGCombineArray));
maxStoresPerMemset = maxStoresPerMemcpy = maxStoresPerMemmove = 8;
@@ -596,6 +596,10 @@ TargetLowering::~TargetLowering() {
delete &TLOF;
}
+MVT TargetLowering::getShiftAmountTy(EVT LHSTy) const {
+ return MVT::getIntegerVT(8*TD->getPointerSize());
+}
+
/// canOpTrap - Returns true if the operation can trap for the value type.
/// VT must be a legal type.
bool TargetLowering::canOpTrap(unsigned Op, EVT VT) const {
@@ -1401,7 +1405,7 @@ bool TargetLowering::SimplifyDemandedBits(SDValue Op,
BitWidth - InnerVT.getSizeInBits()) &
DemandedMask) == 0 &&
isTypeDesirableForOp(ISD::SHL, InnerVT)) {
- EVT ShTy = getShiftAmountTy();
+ EVT ShTy = getShiftAmountTy(InnerVT);
if (!APInt(BitWidth, ShAmt).isIntN(ShTy.getSizeInBits()))
ShTy = InnerVT;
SDValue NarrowShl =
@@ -2188,7 +2192,7 @@ TargetLowering::SimplifySetCC(EVT VT, SDValue N0, SDValue N1,
if (ConstantSDNode *AndRHS =
dyn_cast<ConstantSDNode>(N0.getOperand(1))) {
EVT ShiftTy = DCI.isBeforeLegalize() ?
- getPointerTy() : getShiftAmountTy();
+ getPointerTy() : getShiftAmountTy(N0.getValueType());
if (Cond == ISD::SETNE && C1 == 0) {// (X & 8) != 0 --> (X & 8) >> 3
// Perform the xform if the AND RHS is a single bit.
if (AndRHS->getAPIntValue().isPowerOf2()) {
@@ -2359,7 +2363,7 @@ TargetLowering::SimplifySetCC(EVT VT, SDValue N0, SDValue N1,
// (Z-X) == X --> Z == X<<1
SDValue SH = DAG.getNode(ISD::SHL, dl, N1.getValueType(),
N1,
- DAG.getConstant(1, getShiftAmountTy()));
+ DAG.getConstant(1, getShiftAmountTy(N1.getValueType())));
if (!DCI.isCalledByLegalizer())
DCI.AddToWorklist(SH.getNode());
return DAG.getSetCC(dl, VT, N0.getOperand(0), SH, Cond);
@@ -2381,7 +2385,7 @@ TargetLowering::SimplifySetCC(EVT VT, SDValue N0, SDValue N1,
assert(N1.getOpcode() == ISD::SUB && "Unexpected operation!");
// X == (Z-X) --> X<<1 == Z
SDValue SH = DAG.getNode(ISD::SHL, dl, N1.getValueType(), N0,
- DAG.getConstant(1, getShiftAmountTy()));
+ DAG.getConstant(1, getShiftAmountTy(N0.getValueType())));
if (!DCI.isCalledByLegalizer())
DCI.AddToWorklist(SH.getNode());
return DAG.getSetCC(dl, VT, SH, N1.getOperand(0), Cond);
@@ -2493,7 +2497,7 @@ bool TargetLowering::isGAPlusOffset(SDNode *N, const GlobalValue *&GA,
}
}
}
-
+
return false;
}
@@ -3141,14 +3145,14 @@ SDValue TargetLowering::BuildSDIV(SDNode *N, SelectionDAG &DAG,
// Shift right algebraic if shift value is nonzero
if (magics.s > 0) {
Q = DAG.getNode(ISD::SRA, dl, VT, Q,
- DAG.getConstant(magics.s, getShiftAmountTy()));
+ DAG.getConstant(magics.s, getShiftAmountTy(Q.getValueType())));
if (Created)
Created->push_back(Q.getNode());
}
// Extract the sign bit and add it to the quotient
SDValue T =
DAG.getNode(ISD::SRL, dl, VT, Q, DAG.getConstant(VT.getSizeInBits()-1,
- getShiftAmountTy()));
+ getShiftAmountTy(Q.getValueType())));
if (Created)
Created->push_back(T.getNode());
return DAG.getNode(ISD::ADD, dl, VT, Q, T);
@@ -3192,19 +3196,19 @@ SDValue TargetLowering::BuildUDIV(SDNode *N, SelectionDAG &DAG,
assert(magics.s < N1C->getAPIntValue().getBitWidth() &&
"We shouldn't generate an undefined shift!");
return DAG.getNode(ISD::SRL, dl, VT, Q,
- DAG.getConstant(magics.s, getShiftAmountTy()));
+ DAG.getConstant(magics.s, getShiftAmountTy(Q.getValueType())));
} else {
SDValue NPQ = DAG.getNode(ISD::SUB, dl, VT, N->getOperand(0), Q);
if (Created)
Created->push_back(NPQ.getNode());
NPQ = DAG.getNode(ISD::SRL, dl, VT, NPQ,
- DAG.getConstant(1, getShiftAmountTy()));
+ DAG.getConstant(1, getShiftAmountTy(NPQ.getValueType())));
if (Created)
Created->push_back(NPQ.getNode());
NPQ = DAG.getNode(ISD::ADD, dl, VT, NPQ, Q);
if (Created)
Created->push_back(NPQ.getNode());
return DAG.getNode(ISD::SRL, dl, VT, NPQ,
- DAG.getConstant(magics.s-1, getShiftAmountTy()));
+ DAG.getConstant(magics.s-1, getShiftAmountTy(NPQ.getValueType())));
}
}
diff --git a/contrib/llvm/lib/CodeGen/SplitKit.cpp b/contrib/llvm/lib/CodeGen/SplitKit.cpp
index 5663936..fd5d50b 100644
--- a/contrib/llvm/lib/CodeGen/SplitKit.cpp
+++ b/contrib/llvm/lib/CodeGen/SplitKit.cpp
@@ -167,6 +167,20 @@ void SplitAnalysis::calcLiveBlockInfo() {
}
}
+bool SplitAnalysis::isOriginalEndpoint(SlotIndex Idx) const {
+ unsigned OrigReg = VRM.getOriginal(CurLI->reg);
+ const LiveInterval &Orig = LIS.getInterval(OrigReg);
+ assert(!Orig.empty() && "Splitting empty interval?");
+ LiveInterval::const_iterator I = Orig.find(Idx);
+
+ // Range containing Idx should begin at Idx.
+ if (I != Orig.end() && I->start <= Idx)
+ return I->start == Idx;
+
+ // Range does not contain Idx, previous must end at Idx.
+ return I != Orig.begin() && (--I)->end == Idx;
+}
+
void SplitAnalysis::print(const BlockPtrSet &B, raw_ostream &OS) const {
for (BlockPtrSet::const_iterator I = B.begin(), E = B.end(); I != E; ++I) {
unsigned count = UsingBlocks.lookup(*I);
@@ -947,10 +961,10 @@ void SplitEditor::splitSingleBlocks(const SplitAnalysis::BlockPtrSet &Blocks) {
openIntv();
SlotIndex SegStart = enterIntvBefore(BI.FirstUse);
- if (BI.LastUse < BI.LastSplitPoint) {
+ if (!BI.LiveOut || BI.LastUse < BI.LastSplitPoint) {
useIntv(SegStart, leaveIntvAfter(BI.LastUse));
} else {
- // THe last use os after tha last valid split point.
+ // The last use is after the last valid split point.
SlotIndex SegStop = leaveIntvBefore(BI.LastSplitPoint);
useIntv(SegStart, SegStop);
overlapIntv(SegStop, BI.LastUse);
diff --git a/contrib/llvm/lib/CodeGen/SplitKit.h b/contrib/llvm/lib/CodeGen/SplitKit.h
index 5c34afd..e02e629 100644
--- a/contrib/llvm/lib/CodeGen/SplitKit.h
+++ b/contrib/llvm/lib/CodeGen/SplitKit.h
@@ -125,6 +125,13 @@ public:
return UsingBlocks.lookup(MBB);
}
+ /// isOriginalEndpoint - Return true if the original live range was killed or
+ /// (re-)defined at Idx. Idx should be the 'def' slot for a normal kill/def,
+ /// and 'use' for an early-clobber def.
+ /// This can be used to recognize code inserted by earlier live range
+ /// splitting.
+ bool isOriginalEndpoint(SlotIndex Idx) const;
+
typedef SmallPtrSet<const MachineBasicBlock*, 16> BlockPtrSet;
// Print a set of blocks with use counts.
diff --git a/contrib/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/contrib/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
index 0b7bd98..fa311dc 100644
--- a/contrib/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
+++ b/contrib/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
@@ -178,6 +178,10 @@ const MCSection *TargetLoweringObjectFileELF::getEHFrameSection() const {
static SectionKind
getELFKindForNamedSection(StringRef Name, SectionKind K) {
+ // FIXME: Why is this here? Codegen is should not be in the business
+ // of figuring section flags. If the user wrote section(".eh_frame"),
+ // we should just pass that to MC which will defer to the assembly
+ // or use its default if producing an object file.
if (Name.empty() || Name[0] != '.') return K;
// Some lame default implementation based on some magic section names.
@@ -203,6 +207,9 @@ getELFKindForNamedSection(StringRef Name, SectionKind K) {
Name.startswith(".llvm.linkonce.tb."))
return SectionKind::getThreadBSS();
+ if (Name == ".eh_frame")
+ return SectionKind::getDataRel();
+
return K;
}
@@ -441,11 +448,15 @@ void TargetLoweringObjectFileMachO::Initialize(MCContext &Ctx,
Triple T(((LLVMTargetMachine&)TM).getTargetTriple());
if (T.getOS() == Triple::Darwin) {
- unsigned MajNum = T.getDarwinMajorNumber();
- if (MajNum == 7 || MajNum == 8) // 10.3 Panther, 10.4 Tiger
+ switch (T.getDarwinMajorNumber()) {
+ case 7: // 10.3 Panther.
+ case 8: // 10.4 Tiger.
CommDirectiveSupportsAlignment = false;
- if (MajNum > 9) // 10.6 SnowLeopard
- IsFunctionEHSymbolGlobal = false;
+ break;
+ case 9: // 10.5 Leopard.
+ case 10: // 10.6 SnowLeopard.
+ break;
+ }
}
TargetLoweringObjectFile::Initialize(Ctx, TM);
@@ -630,7 +641,7 @@ getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind,
Mangler *Mang, const TargetMachine &TM) const {
// Parse the section specifier and create it if valid.
StringRef Segment, Section;
- unsigned TAA, StubSize;
+ unsigned TAA = (unsigned)MCSectionMachO::SECTION_ATTRIBUTES, StubSize = 0;
std::string ErrorCode =
MCSectionMachO::ParseSectionSpecifier(GV->getSection(), Segment, Section,
TAA, StubSize);
@@ -643,10 +654,19 @@ getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind,
return DataSection;
}
+ bool TAAWasSet = (TAA != MCSectionMachO::SECTION_ATTRIBUTES);
+ if (!TAAWasSet)
+ TAA = 0; // Sensible default if this is a new section.
+
// Get the section.
const MCSectionMachO *S =
getContext().getMachOSection(Segment, Section, TAA, StubSize, Kind);
+ // If TAA wasn't set by ParseSectionSpecifier() above,
+ // use the value returned by getMachOSection() as a default.
+ if (!TAAWasSet)
+ TAA = S->getTypeAndAttributes();
+
// Okay, now that we got the section, verify that the TAA & StubSize agree.
// If the user declared multiple globals with different section flags, we need
// to reject it here.
diff --git a/contrib/llvm/lib/CodeGen/VirtRegRewriter.cpp b/contrib/llvm/lib/CodeGen/VirtRegRewriter.cpp
index 458a213..ec149dd 100644
--- a/contrib/llvm/lib/CodeGen/VirtRegRewriter.cpp
+++ b/contrib/llvm/lib/CodeGen/VirtRegRewriter.cpp
@@ -478,7 +478,8 @@ static void ResurrectConfirmedKill(unsigned Reg, const TargetRegisterInfo* TRI,
if (!RegKills[KReg])
return;
- assert(KillOps[KReg] == KillOp && "invalid superreg kill flags");
+ assert(KillOps[KReg]->getParent() == KillOp->getParent() &&
+ "invalid superreg kill flags");
KillOps[KReg] = NULL;
RegKills.reset(KReg);
@@ -487,7 +488,8 @@ static void ResurrectConfirmedKill(unsigned Reg, const TargetRegisterInfo* TRI,
for (const unsigned *SR = TRI->getSubRegisters(KReg); *SR; ++SR) {
DEBUG(dbgs() << " Resurrect subreg " << TRI->getName(*SR) << "\n");
- assert(KillOps[*SR] == KillOp && "invalid subreg kill flags");
+ assert(KillOps[*SR]->getParent() == KillOp->getParent() &&
+ "invalid subreg kill flags");
KillOps[*SR] = NULL;
RegKills.reset(*SR);
}
diff --git a/contrib/llvm/lib/MC/ELFObjectWriter.cpp b/contrib/llvm/lib/MC/ELFObjectWriter.cpp
index 8a00a16..ea1629d 100644
--- a/contrib/llvm/lib/MC/ELFObjectWriter.cpp
+++ b/contrib/llvm/lib/MC/ELFObjectWriter.cpp
@@ -833,7 +833,11 @@ static bool isInSymtab(const MCAssembler &Asm, const MCSymbolData &Data,
return true;
const MCSymbol &A = Symbol.AliasedSymbol();
- if (!A.isVariable() && A.isUndefined() && !Data.isCommon())
+ if (Symbol.isVariable() && !A.isVariable() && A.isUndefined())
+ return false;
+
+ bool IsGlobal = GetBinding(Data) == ELF::STB_GLOBAL;
+ if (!Symbol.isVariable() && Symbol.isUndefined() && !IsGlobal)
return false;
if (!Asm.isSymbolLinkerVisible(Symbol) && !Symbol.isUndefined())
@@ -1732,6 +1736,10 @@ unsigned X86ELFObjectWriter::GetRelocType(const MCValue &Target,
assert(Modifier == MCSymbolRefExpr::VK_None);
Type = ELF::R_X86_64_PC16;
break;
+ case FK_PCRel_1:
+ assert(Modifier == MCSymbolRefExpr::VK_None);
+ Type = ELF::R_X86_64_PC8;
+ break;
}
} else {
switch ((unsigned)Fixup.getKind()) {
diff --git a/contrib/llvm/lib/MC/MCAsmInfo.cpp b/contrib/llvm/lib/MC/MCAsmInfo.cpp
index cc1afbd..8199fb2 100644
--- a/contrib/llvm/lib/MC/MCAsmInfo.cpp
+++ b/contrib/llvm/lib/MC/MCAsmInfo.cpp
@@ -65,6 +65,7 @@ MCAsmInfo::MCAsmInfo() {
WeakDefDirective = 0;
LinkOnceDirective = 0;
HiddenVisibilityAttr = MCSA_Hidden;
+ HiddenDeclarationVisibilityAttr = MCSA_Hidden;
ProtectedVisibilityAttr = MCSA_Protected;
HasLEB128 = false;
SupportsDebugInformation = false;
diff --git a/contrib/llvm/lib/MC/MCAsmInfoDarwin.cpp b/contrib/llvm/lib/MC/MCAsmInfoDarwin.cpp
index 13776f0..526ad0d 100644
--- a/contrib/llvm/lib/MC/MCAsmInfoDarwin.cpp
+++ b/contrib/llvm/lib/MC/MCAsmInfoDarwin.cpp
@@ -45,6 +45,7 @@ MCAsmInfoDarwin::MCAsmInfoDarwin() {
HasAggressiveSymbolFolding = false;
HiddenVisibilityAttr = MCSA_PrivateExtern;
+ HiddenDeclarationVisibilityAttr = MCSA_Invalid;
// Doesn't support protected visibility.
ProtectedVisibilityAttr = MCSA_Global;
diff --git a/contrib/llvm/lib/MC/MCDisassembler/EDOperand.cpp b/contrib/llvm/lib/MC/MCDisassembler/EDOperand.cpp
index cfeb56f..2b0c73e 100644
--- a/contrib/llvm/lib/MC/MCDisassembler/EDOperand.cpp
+++ b/contrib/llvm/lib/MC/MCDisassembler/EDOperand.cpp
@@ -152,10 +152,23 @@ int EDOperand::evaluate(uint64_t &result,
uint64_t scaleAmount = Inst.Inst->getOperand(MCOpIndex+1).getImm();
unsigned indexReg = Inst.Inst->getOperand(MCOpIndex+2).getReg();
int64_t displacement = Inst.Inst->getOperand(MCOpIndex+3).getImm();
- //unsigned segmentReg = Inst.Inst->getOperand(MCOpIndex+4).getReg();
-
+
uint64_t addr = 0;
+ unsigned segmentReg = Inst.Inst->getOperand(MCOpIndex+4).getReg();
+
+ if (segmentReg != 0 && Disassembler.Key.Arch == Triple::x86_64) {
+ unsigned fsID = Disassembler.registerIDWithName("FS");
+ unsigned gsID = Disassembler.registerIDWithName("GS");
+
+ if (segmentReg == fsID ||
+ segmentReg == gsID) {
+ uint64_t segmentBase;
+ if (!callback(&segmentBase, segmentReg, arg))
+ addr += segmentBase;
+ }
+ }
+
if (baseReg) {
uint64_t baseVal;
if (callback(&baseVal, baseReg, arg))
@@ -175,7 +188,7 @@ int EDOperand::evaluate(uint64_t &result,
result = addr;
return 0;
}
- }
+ } // switch (operandType)
break;
case Triple::arm:
case Triple::thumb:
@@ -203,6 +216,7 @@ int EDOperand::evaluate(uint64_t &result,
return 0;
}
}
+ break;
}
return -1;
diff --git a/contrib/llvm/lib/MC/MCDisassembler/EDToken.cpp b/contrib/llvm/lib/MC/MCDisassembler/EDToken.cpp
index 400e164..de770b4 100644
--- a/contrib/llvm/lib/MC/MCDisassembler/EDToken.cpp
+++ b/contrib/llvm/lib/MC/MCDisassembler/EDToken.cpp
@@ -194,6 +194,10 @@ int EDToken::tokenize(std::vector<EDToken*> &tokens,
tokens.push_back(token);
}
+ // Free any parsed operands.
+ for (unsigned i = 0, e = parsedOperands.size(); i != e; ++i)
+ delete parsedOperands[i];
+
return 0;
}
diff --git a/contrib/llvm/lib/MC/MCObjectStreamer.cpp b/contrib/llvm/lib/MC/MCObjectStreamer.cpp
index 0358266..e67d9b0 100644
--- a/contrib/llvm/lib/MC/MCObjectStreamer.cpp
+++ b/contrib/llvm/lib/MC/MCObjectStreamer.cpp
@@ -242,7 +242,23 @@ void MCObjectStreamer::EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel,
void MCObjectStreamer::EmitValueToOffset(const MCExpr *Offset,
unsigned char Value) {
- new MCOrgFragment(*Offset, Value, getCurrentSectionData());
+ int64_t Res;
+ if (Offset->EvaluateAsAbsolute(Res, getAssembler())) {
+ new MCOrgFragment(*Offset, Value, getCurrentSectionData());
+ return;
+ }
+
+ MCSymbol *CurrentPos = getContext().CreateTempSymbol();
+ EmitLabel(CurrentPos);
+ MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
+ const MCExpr *Ref =
+ MCSymbolRefExpr::Create(CurrentPos, Variant, getContext());
+ const MCExpr *Delta =
+ MCBinaryExpr::Create(MCBinaryExpr::Sub, Offset, Ref, getContext());
+
+ if (!Delta->EvaluateAsAbsolute(Res, getAssembler()))
+ report_fatal_error("expected assembly-time absolute expression");
+ EmitFill(Res, Value, 0);
}
void MCObjectStreamer::Finish() {
diff --git a/contrib/llvm/lib/MC/MCParser/AsmParser.cpp b/contrib/llvm/lib/MC/MCParser/AsmParser.cpp
index c6d0da6..a84917f 100644
--- a/contrib/llvm/lib/MC/MCParser/AsmParser.cpp
+++ b/contrib/llvm/lib/MC/MCParser/AsmParser.cpp
@@ -603,6 +603,8 @@ bool AsmParser::ParsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
Lex(); // Eat the '('.
return ParseParenExpr(Res, EndLoc);
case AsmToken::LBrac:
+ if (!PlatformParser->HasBracketExpressions())
+ return TokError("brackets expression not supported on this target");
Lex(); // Eat the '['.
return ParseBracketExpr(Res, EndLoc);
case AsmToken::Minus:
diff --git a/contrib/llvm/lib/MC/MCParser/ELFAsmParser.cpp b/contrib/llvm/lib/MC/MCParser/ELFAsmParser.cpp
index bfaf36a..dcf689a 100644
--- a/contrib/llvm/lib/MC/MCParser/ELFAsmParser.cpp
+++ b/contrib/llvm/lib/MC/MCParser/ELFAsmParser.cpp
@@ -30,9 +30,12 @@ class ELFAsmParser : public MCAsmParserExtension {
bool ParseSectionSwitch(StringRef Section, unsigned Type,
unsigned Flags, SectionKind Kind);
+ bool SeenIdent;
public:
- ELFAsmParser() {}
+ ELFAsmParser() : SeenIdent(false) {
+ BracketExpressionsSupported = true;
+ }
virtual void Initialize(MCAsmParser &Parser) {
// Call the base implementation.
@@ -456,13 +459,12 @@ bool ELFAsmParser::ParseDirectiveIdent(StringRef, SMLoc) {
SectionKind::getReadOnly(),
1, "");
- static bool First = true;
-
getStreamer().PushSection();
getStreamer().SwitchSection(Comment);
- if (First)
+ if (!SeenIdent) {
getStreamer().EmitIntValue(0, 1);
- First = false;
+ SeenIdent = true;
+ }
getStreamer().EmitBytes(Data, 0);
getStreamer().EmitIntValue(0, 1);
getStreamer().PopSection();
diff --git a/contrib/llvm/lib/MC/MCParser/MCAsmParserExtension.cpp b/contrib/llvm/lib/MC/MCParser/MCAsmParserExtension.cpp
index c30d306..3f25a14 100644
--- a/contrib/llvm/lib/MC/MCParser/MCAsmParserExtension.cpp
+++ b/contrib/llvm/lib/MC/MCParser/MCAsmParserExtension.cpp
@@ -10,7 +10,8 @@
#include "llvm/MC/MCParser/MCAsmParserExtension.h"
using namespace llvm;
-MCAsmParserExtension::MCAsmParserExtension() {
+MCAsmParserExtension::MCAsmParserExtension() :
+ BracketExpressionsSupported(false) {
}
MCAsmParserExtension::~MCAsmParserExtension() {
diff --git a/contrib/llvm/lib/MC/MCSectionMachO.cpp b/contrib/llvm/lib/MC/MCSectionMachO.cpp
index b897c0b..577e93a 100644
--- a/contrib/llvm/lib/MC/MCSectionMachO.cpp
+++ b/contrib/llvm/lib/MC/MCSectionMachO.cpp
@@ -101,16 +101,18 @@ void MCSectionMachO::PrintSwitchToSection(const MCAsmInfo &MAI,
return;
}
- OS << ',';
-
unsigned SectionType = TAA & MCSectionMachO::SECTION_TYPE;
assert(SectionType <= MCSectionMachO::LAST_KNOWN_SECTION_TYPE &&
"Invalid SectionType specified!");
- if (SectionTypeDescriptors[SectionType].AssemblerName)
+ if (SectionTypeDescriptors[SectionType].AssemblerName) {
+ OS << ',';
OS << SectionTypeDescriptors[SectionType].AssemblerName;
- else
- OS << "<<" << SectionTypeDescriptors[SectionType].EnumName << ">>";
+ } else {
+ // If we have no name for the attribute, stop here.
+ OS << '\n';
+ return;
+ }
// If we don't have any attributes, we're done.
unsigned SectionAttrs = TAA & MCSectionMachO::SECTION_ATTRIBUTES;
@@ -125,7 +127,9 @@ void MCSectionMachO::PrintSwitchToSection(const MCAsmInfo &MAI,
// Check each attribute to see if we have it.
char Separator = ',';
- for (unsigned i = 0; SectionAttrDescriptors[i].AttrFlag; ++i) {
+ for (unsigned i = 0;
+ SectionAttrs != 0 && SectionAttrDescriptors[i].AttrFlag;
+ ++i) {
// Check to see if we have this attribute.
if ((SectionAttrDescriptors[i].AttrFlag & SectionAttrs) == 0)
continue;
@@ -207,7 +211,6 @@ std::string MCSectionMachO::ParseSectionSpecifier(StringRef Spec, // In.
"between 1 and 16 characters";
// If there is no comma after the section, we're done.
- TAA = 0;
StubSize = 0;
if (Comma.second.empty())
return "";
diff --git a/contrib/llvm/lib/MC/MCStreamer.cpp b/contrib/llvm/lib/MC/MCStreamer.cpp
index 3dcdba1..4b302c8 100644
--- a/contrib/llvm/lib/MC/MCStreamer.cpp
+++ b/contrib/llvm/lib/MC/MCStreamer.cpp
@@ -20,8 +20,8 @@
using namespace llvm;
MCStreamer::MCStreamer(MCContext &Ctx) : Context(Ctx) {
- PrevSectionStack.push_back(NULL);
- CurSectionStack.push_back(NULL);
+ const MCSection *section = NULL;
+ SectionStack.push_back(std::make_pair(section, section));
}
MCStreamer::~MCStreamer() {
diff --git a/contrib/llvm/lib/Support/APInt.cpp b/contrib/llvm/lib/Support/APInt.cpp
index 7703342..08f36d2 100644
--- a/contrib/llvm/lib/Support/APInt.cpp
+++ b/contrib/llvm/lib/Support/APInt.cpp
@@ -1505,7 +1505,7 @@ APInt::ms APInt::magic() const {
r2 = r2 - ad;
}
delta = ad - r2;
- } while (q1.ule(delta) || (q1 == delta && r1 == 0));
+ } while (q1.ult(delta) || (q1 == delta && r1 == 0));
mag.m = q2 + 1;
if (d.isNegative()) mag.m = -mag.m; // resulting magic number
diff --git a/contrib/llvm/lib/Target/ARM/ARMBaseInstrInfo.h b/contrib/llvm/lib/Target/ARM/ARMBaseInstrInfo.h
index 1fb8872..7e2183d 100644
--- a/contrib/llvm/lib/Target/ARM/ARMBaseInstrInfo.h
+++ b/contrib/llvm/lib/Target/ARM/ARMBaseInstrInfo.h
@@ -155,10 +155,11 @@ namespace ARMII {
//===------------------------------------------------------------------===//
// Code domain.
DomainShift = 18,
- DomainMask = 3 << DomainShift,
+ DomainMask = 7 << DomainShift,
DomainGeneral = 0 << DomainShift,
DomainVFP = 1 << DomainShift,
DomainNEON = 2 << DomainShift,
+ DomainNEONA8 = 4 << DomainShift,
//===------------------------------------------------------------------===//
// Field shifts - such shifts are used to set field while generating
diff --git a/contrib/llvm/lib/Target/ARM/ARMFastISel.cpp b/contrib/llvm/lib/Target/ARM/ARMFastISel.cpp
index 9f29530..26f48b3 100644
--- a/contrib/llvm/lib/Target/ARM/ARMFastISel.cpp
+++ b/contrib/llvm/lib/Target/ARM/ARMFastISel.cpp
@@ -172,6 +172,7 @@ class ARMFastISel : public FastISel {
unsigned ARMMaterializeGV(const GlobalValue *GV, EVT VT);
unsigned ARMMoveToFPReg(EVT VT, unsigned SrcReg);
unsigned ARMMoveToIntReg(EVT VT, unsigned SrcReg);
+ unsigned ARMSelectCallOp(const GlobalValue *GV);
// Call handling routines.
private:
@@ -1633,6 +1634,25 @@ bool ARMFastISel::SelectRet(const Instruction *I) {
return true;
}
+unsigned ARMFastISel::ARMSelectCallOp(const GlobalValue *GV) {
+
+ // Depend our opcode for thumb on whether or not we're targeting an
+ // externally callable function. For libcalls we'll just pass a NULL GV
+ // in here.
+ bool isExternal = false;
+ if (!GV || GV->hasExternalLinkage()) isExternal = true;
+
+ // Darwin needs the r9 versions of the opcodes.
+ bool isDarwin = Subtarget->isTargetDarwin();
+ if (isThumb && isExternal) {
+ return isDarwin ? ARM::tBLXi_r9 : ARM::tBLXi;
+ } else if (isThumb) {
+ return isDarwin ? ARM::tBLr9 : ARM::tBL;
+ } else {
+ return isDarwin ? ARM::BLr9 : ARM::BL;
+ }
+}
+
// A quick function that will emit a call for a named libcall in F with the
// vector of passed arguments for the Instruction in I. We can assume that we
// can emit a call for any libcall we can produce. This is an abridged version
@@ -1694,20 +1714,17 @@ bool ARMFastISel::ARMEmitLibcall(const Instruction *I, RTLIB::Libcall Call) {
// Issue the call, BLXr9 for darwin, BLX otherwise. This uses V5 ops.
// TODO: Turn this into the table of arm call ops.
MachineInstrBuilder MIB;
- unsigned CallOpc;
- if(isThumb) {
- CallOpc = Subtarget->isTargetDarwin() ? ARM::tBLXi_r9 : ARM::tBLXi;
+ unsigned CallOpc = ARMSelectCallOp(NULL);
+ if(isThumb)
// Explicitly adding the predicate here.
MIB = AddDefaultPred(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL,
TII.get(CallOpc)))
.addExternalSymbol(TLI.getLibcallName(Call));
- } else {
- CallOpc = Subtarget->isTargetDarwin() ? ARM::BLr9 : ARM::BL;
+ else
// Explicitly adding the predicate here.
MIB = AddDefaultPred(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL,
TII.get(CallOpc))
.addExternalSymbol(TLI.getLibcallName(Call)));
- }
// Add implicit physical register uses to the call.
for (unsigned i = 0, e = RegArgs.size(); i != e; ++i)
@@ -1813,21 +1830,18 @@ bool ARMFastISel::SelectCall(const Instruction *I) {
// Issue the call, BLXr9 for darwin, BLX otherwise. This uses V5 ops.
// TODO: Turn this into the table of arm call ops.
MachineInstrBuilder MIB;
- unsigned CallOpc;
+ unsigned CallOpc = ARMSelectCallOp(GV);
// Explicitly adding the predicate here.
- if(isThumb) {
- CallOpc = Subtarget->isTargetDarwin() ? ARM::tBLXi_r9 : ARM::tBLXi;
+ if(isThumb)
// Explicitly adding the predicate here.
MIB = AddDefaultPred(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL,
TII.get(CallOpc)))
.addGlobalAddress(GV, 0, 0);
- } else {
- CallOpc = Subtarget->isTargetDarwin() ? ARM::BLr9 : ARM::BL;
+ else
// Explicitly adding the predicate here.
MIB = AddDefaultPred(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL,
TII.get(CallOpc))
.addGlobalAddress(GV, 0, 0));
- }
// Add implicit physical register uses to the call.
for (unsigned i = 0, e = RegArgs.size(); i != e; ++i)
diff --git a/contrib/llvm/lib/Target/ARM/ARMFrameLowering.cpp b/contrib/llvm/lib/Target/ARM/ARMFrameLowering.cpp
index f42c6db..68c33f0 100644
--- a/contrib/llvm/lib/Target/ARM/ARMFrameLowering.cpp
+++ b/contrib/llvm/lib/Target/ARM/ARMFrameLowering.cpp
@@ -215,7 +215,13 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF) const {
AFI->setDPRCalleeSavedAreaOffset(DPRCSOffset);
// Move past area 3.
- if (DPRCSSize > 0) MBBI++;
+ if (DPRCSSize > 0) {
+ MBBI++;
+ // Since vpush register list cannot have gaps, there may be multiple vpush
+ // instructions in the prologue.
+ while (MBBI->getOpcode() == ARM::VSTMDDB_UPD)
+ MBBI++;
+ }
NumBytes = DPRCSOffset;
if (NumBytes) {
@@ -370,7 +376,13 @@ void ARMFrameLowering::emitEpilogue(MachineFunction &MF,
emitSPUpdate(isARM, MBB, MBBI, dl, TII, NumBytes);
// Increment past our save areas.
- if (AFI->getDPRCalleeSavedAreaSize()) MBBI++;
+ if (AFI->getDPRCalleeSavedAreaSize()) {
+ MBBI++;
+ // Since vpop register list cannot have gaps, there may be multiple vpop
+ // instructions in the epilogue.
+ while (MBBI->getOpcode() == ARM::VLDMDIA_UPD)
+ MBBI++;
+ }
if (AFI->getGPRCalleeSavedArea2Size()) MBBI++;
if (AFI->getGPRCalleeSavedArea1Size()) MBBI++;
}
diff --git a/contrib/llvm/lib/Target/ARM/ARMHazardRecognizer.cpp b/contrib/llvm/lib/Target/ARM/ARMHazardRecognizer.cpp
index 676b01e..e97ce50 100644
--- a/contrib/llvm/lib/Target/ARM/ARMHazardRecognizer.cpp
+++ b/contrib/llvm/lib/Target/ARM/ARMHazardRecognizer.cpp
@@ -21,17 +21,14 @@ static bool hasRAWHazard(MachineInstr *DefMI, MachineInstr *MI,
// FIXME: Detect integer instructions properly.
const TargetInstrDesc &TID = MI->getDesc();
unsigned Domain = TID.TSFlags & ARMII::DomainMask;
- if (Domain == ARMII::DomainVFP) {
- unsigned Opcode = MI->getOpcode();
- if (Opcode == ARM::VSTRS || Opcode == ARM::VSTRD ||
- Opcode == ARM::VMOVRS || Opcode == ARM::VMOVRRD)
- return false;
- } else if (Domain == ARMII::DomainNEON) {
- if (MI->getDesc().mayStore() || MI->getDesc().mayLoad())
- return false;
- } else
+ if (TID.mayStore())
return false;
- return MI->readsRegister(DefMI->getOperand(0).getReg(), &TRI);
+ unsigned Opcode = TID.getOpcode();
+ if (Opcode == ARM::VMOVRS || Opcode == ARM::VMOVRRD)
+ return false;
+ if ((Domain & ARMII::DomainVFP) || (Domain & ARMII::DomainNEON))
+ return MI->readsRegister(DefMI->getOperand(0).getReg(), &TRI);
+ return false;
}
ScheduleHazardRecognizer::HazardType
diff --git a/contrib/llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp b/contrib/llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp
index a506cff..f0d5a7d 100644
--- a/contrib/llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp
+++ b/contrib/llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp
@@ -126,6 +126,7 @@ public:
bool SelectAddrMode5(SDValue N, SDValue &Base,
SDValue &Offset);
bool SelectAddrMode6(SDNode *Parent, SDValue N, SDValue &Addr,SDValue &Align);
+ bool SelectAddrMode6Offset(SDNode *Op, SDValue N, SDValue &Offset);
bool SelectAddrModePC(SDValue N, SDValue &Offset, SDValue &Label);
@@ -886,6 +887,20 @@ bool ARMDAGToDAGISel::SelectAddrMode6(SDNode *Parent, SDValue N, SDValue &Addr,
return true;
}
+bool ARMDAGToDAGISel::SelectAddrMode6Offset(SDNode *Op, SDValue N,
+ SDValue &Offset) {
+ LSBaseSDNode *LdSt = cast<LSBaseSDNode>(Op);
+ ISD::MemIndexedMode AM = LdSt->getAddressingMode();
+ if (AM != ISD::POST_INC)
+ return false;
+ Offset = N;
+ if (ConstantSDNode *NC = dyn_cast<ConstantSDNode>(N)) {
+ if (NC->getZExtValue() * 8 == LdSt->getMemoryVT().getSizeInBits())
+ Offset = CurDAG->getRegister(0, MVT::i32);
+ }
+ return true;
+}
+
bool ARMDAGToDAGISel::SelectAddrModePC(SDValue N,
SDValue &Offset, SDValue &Label) {
if (N.getOpcode() == ARMISD::PIC_ADD && N.hasOneUse()) {
diff --git a/contrib/llvm/lib/Target/ARM/ARMISelLowering.cpp b/contrib/llvm/lib/Target/ARM/ARMISelLowering.cpp
index 1835ec0..ab9f9e1 100644
--- a/contrib/llvm/lib/Target/ARM/ARMISelLowering.cpp
+++ b/contrib/llvm/lib/Target/ARM/ARMISelLowering.cpp
@@ -2236,7 +2236,7 @@ ARMTargetLowering::GetF64FormalArgument(CCValAssign &VA, CCValAssign &NextVA,
RC = ARM::GPRRegisterClass;
// Transform the arguments stored in physical registers into virtual ones.
- unsigned Reg = MF.addLiveIn(VA.getLocReg(), RC, dl);
+ unsigned Reg = MF.addLiveIn(VA.getLocReg(), RC);
SDValue ArgValue = DAG.getCopyFromReg(Root, dl, Reg, MVT::i32);
SDValue ArgValue2;
@@ -2250,7 +2250,7 @@ ARMTargetLowering::GetF64FormalArgument(CCValAssign &VA, CCValAssign &NextVA,
MachinePointerInfo::getFixedStack(FI),
false, false, 0);
} else {
- Reg = MF.addLiveIn(NextVA.getLocReg(), RC, dl);
+ Reg = MF.addLiveIn(NextVA.getLocReg(), RC);
ArgValue2 = DAG.getCopyFromReg(Root, dl, Reg, MVT::i32);
}
@@ -2331,7 +2331,7 @@ ARMTargetLowering::LowerFormalArguments(SDValue Chain,
llvm_unreachable("RegVT not supported by FORMAL_ARGUMENTS Lowering");
// Transform the arguments in physical registers into virtual ones.
- unsigned Reg = MF.addLiveIn(VA.getLocReg(), RC, dl);
+ unsigned Reg = MF.addLiveIn(VA.getLocReg(), RC);
ArgValue = DAG.getCopyFromReg(Chain, dl, Reg, RegVT);
}
@@ -2408,7 +2408,7 @@ ARMTargetLowering::LowerFormalArguments(SDValue Chain,
else
RC = ARM::GPRRegisterClass;
- unsigned VReg = MF.addLiveIn(GPRArgRegs[NumGPRs], RC, dl);
+ unsigned VReg = MF.addLiveIn(GPRArgRegs[NumGPRs], RC);
SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32);
SDValue Store =
DAG.getStore(Val.getValue(1), dl, Val, FIN,
@@ -2838,8 +2838,51 @@ SDValue ARMTargetLowering::LowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) const {
DebugLoc dl = Op.getDebugLoc();
EVT VT = Op.getValueType();
EVT SrcVT = Tmp1.getValueType();
- bool F2IisFast = Subtarget->isCortexA9() ||
- Tmp0.getOpcode() == ISD::BITCAST || Tmp0.getOpcode() == ARMISD::VMOVDRR;
+ bool InGPR = Tmp0.getOpcode() == ISD::BITCAST ||
+ Tmp0.getOpcode() == ARMISD::VMOVDRR;
+ bool UseNEON = !InGPR && Subtarget->hasNEON();
+
+ if (UseNEON) {
+ // Use VBSL to copy the sign bit.
+ unsigned EncodedVal = ARM_AM::createNEONModImm(0x6, 0x80);
+ SDValue Mask = DAG.getNode(ARMISD::VMOVIMM, dl, MVT::v2i32,
+ DAG.getTargetConstant(EncodedVal, MVT::i32));
+ EVT OpVT = (VT == MVT::f32) ? MVT::v2i32 : MVT::v1i64;
+ if (VT == MVT::f64)
+ Mask = DAG.getNode(ARMISD::VSHL, dl, OpVT,
+ DAG.getNode(ISD::BITCAST, dl, OpVT, Mask),
+ DAG.getConstant(32, MVT::i32));
+ else /*if (VT == MVT::f32)*/
+ Tmp0 = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, MVT::v2f32, Tmp0);
+ if (SrcVT == MVT::f32) {
+ Tmp1 = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, MVT::v2f32, Tmp1);
+ if (VT == MVT::f64)
+ Tmp1 = DAG.getNode(ARMISD::VSHL, dl, OpVT,
+ DAG.getNode(ISD::BITCAST, dl, OpVT, Tmp1),
+ DAG.getConstant(32, MVT::i32));
+ }
+ Tmp0 = DAG.getNode(ISD::BITCAST, dl, OpVT, Tmp0);
+ Tmp1 = DAG.getNode(ISD::BITCAST, dl, OpVT, Tmp1);
+
+ SDValue AllOnes = DAG.getTargetConstant(ARM_AM::createNEONModImm(0xe, 0xff),
+ MVT::i32);
+ AllOnes = DAG.getNode(ARMISD::VMOVIMM, dl, MVT::v8i8, AllOnes);
+ SDValue MaskNot = DAG.getNode(ISD::XOR, dl, OpVT, Mask,
+ DAG.getNode(ISD::BITCAST, dl, OpVT, AllOnes));
+
+ SDValue Res = DAG.getNode(ISD::OR, dl, OpVT,
+ DAG.getNode(ISD::AND, dl, OpVT, Tmp1, Mask),
+ DAG.getNode(ISD::AND, dl, OpVT, Tmp0, MaskNot));
+ if (SrcVT == MVT::f32) {
+ Res = DAG.getNode(ISD::BITCAST, dl, MVT::v2f32, Res);
+ Res = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, MVT::f32, Res,
+ DAG.getConstant(0, MVT::i32));
+ } else {
+ Res = DAG.getNode(ISD::BITCAST, dl, MVT::f64, Res);
+ }
+
+ return Res;
+ }
// Bitcast operand 1 to i32.
if (SrcVT == MVT::f64)
@@ -2847,37 +2890,24 @@ SDValue ARMTargetLowering::LowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) const {
&Tmp1, 1).getValue(1);
Tmp1 = DAG.getNode(ISD::BITCAST, dl, MVT::i32, Tmp1);
- // If float to int conversion isn't going to be super expensive, then simply
- // or in the signbit.
- if (F2IisFast) {
- SDValue Mask1 = DAG.getConstant(0x80000000, MVT::i32);
- SDValue Mask2 = DAG.getConstant(0x7fffffff, MVT::i32);
- Tmp1 = DAG.getNode(ISD::AND, dl, MVT::i32, Tmp1, Mask1);
- if (VT == MVT::f32) {
- Tmp0 = DAG.getNode(ISD::AND, dl, MVT::i32,
- DAG.getNode(ISD::BITCAST, dl, MVT::i32, Tmp0), Mask2);
- return DAG.getNode(ISD::BITCAST, dl, MVT::f32,
- DAG.getNode(ISD::OR, dl, MVT::i32, Tmp0, Tmp1));
- }
-
- // f64: Or the high part with signbit and then combine two parts.
- Tmp0 = DAG.getNode(ARMISD::VMOVRRD, dl, DAG.getVTList(MVT::i32, MVT::i32),
- &Tmp0, 1);
- SDValue Lo = Tmp0.getValue(0);
- SDValue Hi = DAG.getNode(ISD::AND, dl, MVT::i32, Tmp0.getValue(1), Mask2);
- Hi = DAG.getNode(ISD::OR, dl, MVT::i32, Hi, Tmp1);
- return DAG.getNode(ARMISD::VMOVDRR, dl, MVT::f64, Lo, Hi);
+ // Or in the signbit with integer operations.
+ SDValue Mask1 = DAG.getConstant(0x80000000, MVT::i32);
+ SDValue Mask2 = DAG.getConstant(0x7fffffff, MVT::i32);
+ Tmp1 = DAG.getNode(ISD::AND, dl, MVT::i32, Tmp1, Mask1);
+ if (VT == MVT::f32) {
+ Tmp0 = DAG.getNode(ISD::AND, dl, MVT::i32,
+ DAG.getNode(ISD::BITCAST, dl, MVT::i32, Tmp0), Mask2);
+ return DAG.getNode(ISD::BITCAST, dl, MVT::f32,
+ DAG.getNode(ISD::OR, dl, MVT::i32, Tmp0, Tmp1));
}
- // Remove the signbit of operand 0.
- Tmp0 = DAG.getNode(ISD::FABS, dl, VT, Tmp0);
-
- // If operand 1 signbit is one, then negate operand 0.
- SDValue ARMcc;
- SDValue Cmp = getARMCmp(Tmp1, DAG.getConstant(0, MVT::i32),
- ISD::SETLT, ARMcc, DAG, dl);
- SDValue CCR = DAG.getRegister(ARM::CPSR, MVT::i32);
- return DAG.getNode(ARMISD::CNEG, dl, VT, Tmp0, Tmp0, ARMcc, CCR, Cmp);
+ // f64: Or the high part with signbit and then combine two parts.
+ Tmp0 = DAG.getNode(ARMISD::VMOVRRD, dl, DAG.getVTList(MVT::i32, MVT::i32),
+ &Tmp0, 1);
+ SDValue Lo = Tmp0.getValue(0);
+ SDValue Hi = DAG.getNode(ISD::AND, dl, MVT::i32, Tmp0.getValue(1), Mask2);
+ Hi = DAG.getNode(ISD::OR, dl, MVT::i32, Hi, Tmp1);
+ return DAG.getNode(ARMISD::VMOVDRR, dl, MVT::f64, Lo, Hi);
}
SDValue ARMTargetLowering::LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const{
@@ -2897,7 +2927,7 @@ SDValue ARMTargetLowering::LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const{
}
// Return LR, which contains the return address. Mark it an implicit live-in.
- unsigned Reg = MF.addLiveIn(ARM::LR, getRegClassFor(MVT::i32), dl);
+ unsigned Reg = MF.addLiveIn(ARM::LR, getRegClassFor(MVT::i32));
return DAG.getCopyFromReg(DAG.getEntryNode(), dl, Reg, VT);
}
diff --git a/contrib/llvm/lib/Target/ARM/ARMInstrFormats.td b/contrib/llvm/lib/Target/ARM/ARMInstrFormats.td
index 765cba4..359ac45 100644
--- a/contrib/llvm/lib/Target/ARM/ARMInstrFormats.td
+++ b/contrib/llvm/lib/Target/ARM/ARMInstrFormats.td
@@ -127,13 +127,14 @@ def IndexModePost : IndexMode<2>;
def IndexModeUpd : IndexMode<3>;
// Instruction execution domain.
-class Domain<bits<2> val> {
- bits<2> Value = val;
+class Domain<bits<3> val> {
+ bits<3> Value = val;
}
def GenericDomain : Domain<0>;
def VFPDomain : Domain<1>; // Instructions in VFP domain only
def NeonDomain : Domain<2>; // Instructions in Neon domain only
def VFPNeonDomain : Domain<3>; // Instructions in both VFP & Neon domains
+def VFPNeonA8Domain : Domain<5>; // Instructions in VFP & Neon under A8
//===----------------------------------------------------------------------===//
// ARM special operands.
@@ -249,7 +250,7 @@ class InstTemplate<AddrMode am, SizeFlagVal sz, IndexMode im,
let TSFlags{15-10} = Form;
let TSFlags{16} = isUnaryDataProc;
let TSFlags{17} = canXformTo16Bit;
- let TSFlags{19-18} = D.Value;
+ let TSFlags{20-18} = D.Value;
let Constraints = cstr;
let Itinerary = itin;
diff --git a/contrib/llvm/lib/Target/ARM/ARMInstrInfo.td b/contrib/llvm/lib/Target/ARM/ARMInstrInfo.td
index c827ce3d..6e3fe2e 100644
--- a/contrib/llvm/lib/Target/ARM/ARMInstrInfo.td
+++ b/contrib/llvm/lib/Target/ARM/ARMInstrInfo.td
@@ -561,7 +561,9 @@ def addrmode6 : Operand<i32>,
let EncoderMethod = "getAddrMode6AddressOpValue";
}
-def am6offset : Operand<i32> {
+def am6offset : Operand<i32>,
+ ComplexPattern<i32, 1, "SelectAddrMode6Offset",
+ [], [SDNPWantRoot]> {
let PrintMethod = "printAddrMode6OffsetOperand";
let MIOperandInfo = (ops GPR);
let EncoderMethod = "getAddrMode6OffsetOpValue";
diff --git a/contrib/llvm/lib/Target/ARM/ARMInstrNEON.td b/contrib/llvm/lib/Target/ARM/ARMInstrNEON.td
index 1e2e550..dc3d63e 100644
--- a/contrib/llvm/lib/Target/ARM/ARMInstrNEON.td
+++ b/contrib/llvm/lib/Target/ARM/ARMInstrNEON.td
@@ -1402,31 +1402,42 @@ def : Pat<(store (extractelt (v2f32 DPR:$src), imm:$lane), addrmode6:$addr),
def : Pat<(store (extractelt (v4f32 QPR:$src), imm:$lane), addrmode6:$addr),
(VST1LNq32Pseudo addrmode6:$addr, QPR:$src, imm:$lane)>;
-let mayStore = 1, neverHasSideEffects = 1, hasExtraSrcRegAllocReq = 1 in {
-
// ...with address register writeback:
-class VST1LNWB<bits<4> op11_8, bits<4> op7_4, string Dt>
+class VST1LNWB<bits<4> op11_8, bits<4> op7_4, string Dt, ValueType Ty,
+ PatFrag StoreOp, SDNode ExtractOp>
: NLdStLn<1, 0b00, op11_8, op7_4, (outs GPR:$wb),
(ins addrmode6:$Rn, am6offset:$Rm,
DPR:$Vd, nohash_imm:$lane), IIC_VST1lnu, "vst1", Dt,
"\\{$Vd[$lane]\\}, $Rn$Rm",
- "$Rn.addr = $wb", []>;
+ "$Rn.addr = $wb",
+ [(set GPR:$wb, (StoreOp (ExtractOp (Ty DPR:$Vd), imm:$lane),
+ addrmode6:$Rn, am6offset:$Rm))]>;
+class VST1QLNWBPseudo<ValueType Ty, PatFrag StoreOp, SDNode ExtractOp>
+ : VSTQLNWBPseudo<IIC_VST1lnu> {
+ let Pattern = [(set GPR:$wb, (StoreOp (ExtractOp (Ty QPR:$src), imm:$lane),
+ addrmode6:$addr, am6offset:$offset))];
+}
-def VST1LNd8_UPD : VST1LNWB<0b0000, {?,?,?,0}, "8"> {
+def VST1LNd8_UPD : VST1LNWB<0b0000, {?,?,?,0}, "8", v8i8, post_truncsti8,
+ NEONvgetlaneu> {
let Inst{7-5} = lane{2-0};
}
-def VST1LNd16_UPD : VST1LNWB<0b0100, {?,?,0,?}, "16"> {
+def VST1LNd16_UPD : VST1LNWB<0b0100, {?,?,0,?}, "16", v4i16, post_truncsti16,
+ NEONvgetlaneu> {
let Inst{7-6} = lane{1-0};
let Inst{4} = Rn{5};
}
-def VST1LNd32_UPD : VST1LNWB<0b1000, {?,0,?,?}, "32"> {
+def VST1LNd32_UPD : VST1LNWB<0b1000, {?,0,?,?}, "32", v2i32, post_store,
+ extractelt> {
let Inst{7} = lane{0};
let Inst{5-4} = Rn{5-4};
}
-def VST1LNq8Pseudo_UPD : VSTQLNWBPseudo<IIC_VST1lnu>;
-def VST1LNq16Pseudo_UPD : VSTQLNWBPseudo<IIC_VST1lnu>;
-def VST1LNq32Pseudo_UPD : VSTQLNWBPseudo<IIC_VST1lnu>;
+def VST1LNq8Pseudo_UPD : VST1QLNWBPseudo<v16i8, post_truncsti8, NEONvgetlaneu>;
+def VST1LNq16Pseudo_UPD : VST1QLNWBPseudo<v8i16, post_truncsti16,NEONvgetlaneu>;
+def VST1LNq32Pseudo_UPD : VST1QLNWBPseudo<v4i32, post_store, extractelt>;
+
+let mayStore = 1, neverHasSideEffects = 1, hasExtraSrcRegAllocReq = 1 in {
// VST2LN : Vector Store (single 2-element structure from one lane)
class VST2LN<bits<4> op11_8, bits<4> op7_4, string Dt>
diff --git a/contrib/llvm/lib/Target/ARM/ARMInstrVFP.td b/contrib/llvm/lib/Target/ARM/ARMInstrVFP.td
index 920c5c9..2990283 100644
--- a/contrib/llvm/lib/Target/ARM/ARMInstrVFP.td
+++ b/contrib/llvm/lib/Target/ARM/ARMInstrVFP.td
@@ -197,9 +197,9 @@ def VADDS : ASbIn<0b11100, 0b11, 0, 0,
(outs SPR:$Sd), (ins SPR:$Sn, SPR:$Sm),
IIC_fpALU32, "vadd", ".f32\t$Sd, $Sn, $Sm",
[(set SPR:$Sd, (fadd SPR:$Sn, SPR:$Sm))]> {
- // Some single precision VFP instructions may be executed on both NEON and VFP
- // pipelines.
- let D = VFPNeonDomain;
+ // Some single precision VFP instructions may be executed on both NEON and
+ // VFP pipelines on A8.
+ let D = VFPNeonA8Domain;
}
def VSUBD : ADbI<0b11100, 0b11, 1, 0,
@@ -211,9 +211,9 @@ def VSUBS : ASbIn<0b11100, 0b11, 1, 0,
(outs SPR:$Sd), (ins SPR:$Sn, SPR:$Sm),
IIC_fpALU32, "vsub", ".f32\t$Sd, $Sn, $Sm",
[(set SPR:$Sd, (fsub SPR:$Sn, SPR:$Sm))]> {
- // Some single precision VFP instructions may be executed on both NEON and VFP
- // pipelines.
- let D = VFPNeonDomain;
+ // Some single precision VFP instructions may be executed on both NEON and
+ // VFP pipelines on A8.
+ let D = VFPNeonA8Domain;
}
def VDIVD : ADbI<0b11101, 0b00, 0, 0,
@@ -235,9 +235,9 @@ def VMULS : ASbIn<0b11100, 0b10, 0, 0,
(outs SPR:$Sd), (ins SPR:$Sn, SPR:$Sm),
IIC_fpMUL32, "vmul", ".f32\t$Sd, $Sn, $Sm",
[(set SPR:$Sd, (fmul SPR:$Sn, SPR:$Sm))]> {
- // Some single precision VFP instructions may be executed on both NEON and VFP
- // pipelines.
- let D = VFPNeonDomain;
+ // Some single precision VFP instructions may be executed on both NEON and
+ // VFP pipelines on A8.
+ let D = VFPNeonA8Domain;
}
def VNMULD : ADbI<0b11100, 0b10, 1, 0,
@@ -249,9 +249,9 @@ def VNMULS : ASbI<0b11100, 0b10, 1, 0,
(outs SPR:$Sd), (ins SPR:$Sn, SPR:$Sm),
IIC_fpMUL32, "vnmul", ".f32\t$Sd, $Sn, $Sm",
[(set SPR:$Sd, (fneg (fmul SPR:$Sn, SPR:$Sm)))]> {
- // Some single precision VFP instructions may be executed on both NEON and VFP
- // pipelines.
- let D = VFPNeonDomain;
+ // Some single precision VFP instructions may be executed on both NEON and
+ // VFP pipelines on A8.
+ let D = VFPNeonA8Domain;
}
// Match reassociated forms only if not sign dependent rounding.
@@ -271,9 +271,9 @@ def VCMPES : ASuI<0b11101, 0b11, 0b0100, 0b11, 0,
(outs), (ins SPR:$Sd, SPR:$Sm),
IIC_fpCMP32, "vcmpe", ".f32\t$Sd, $Sm",
[(arm_cmpfp SPR:$Sd, SPR:$Sm)]> {
- // Some single precision VFP instructions may be executed on both NEON and VFP
- // pipelines.
- let D = VFPNeonDomain;
+ // Some single precision VFP instructions may be executed on both NEON and
+ // VFP pipelines on A8.
+ let D = VFPNeonA8Domain;
}
// FIXME: Verify encoding after integrated assembler is working.
@@ -286,9 +286,9 @@ def VCMPS : ASuI<0b11101, 0b11, 0b0100, 0b01, 0,
(outs), (ins SPR:$Sd, SPR:$Sm),
IIC_fpCMP32, "vcmp", ".f32\t$Sd, $Sm",
[/* For disassembly only; pattern left blank */]> {
- // Some single precision VFP instructions may be executed on both NEON and VFP
- // pipelines.
- let D = VFPNeonDomain;
+ // Some single precision VFP instructions may be executed on both NEON and
+ // VFP pipelines on A8.
+ let D = VFPNeonA8Domain;
}
} // Defs = [FPSCR]
@@ -305,9 +305,9 @@ def VABSS : ASuIn<0b11101, 0b11, 0b0000, 0b11, 0,
(outs SPR:$Sd), (ins SPR:$Sm),
IIC_fpUNA32, "vabs", ".f32\t$Sd, $Sm",
[(set SPR:$Sd, (fabs SPR:$Sm))]> {
- // Some single precision VFP instructions may be executed on both NEON and VFP
- // pipelines.
- let D = VFPNeonDomain;
+ // Some single precision VFP instructions may be executed on both NEON and
+ // VFP pipelines on A8.
+ let D = VFPNeonA8Domain;
}
let Defs = [FPSCR] in {
@@ -326,9 +326,9 @@ def VCMPEZS : ASuI<0b11101, 0b11, 0b0101, 0b11, 0,
let Inst{3-0} = 0b0000;
let Inst{5} = 0;
- // Some single precision VFP instructions may be executed on both NEON and VFP
- // pipelines.
- let D = VFPNeonDomain;
+ // Some single precision VFP instructions may be executed on both NEON and
+ // VFP pipelines on A8.
+ let D = VFPNeonA8Domain;
}
// FIXME: Verify encoding after integrated assembler is working.
@@ -347,9 +347,9 @@ def VCMPZS : ASuI<0b11101, 0b11, 0b0101, 0b01, 0,
let Inst{3-0} = 0b0000;
let Inst{5} = 0;
- // Some single precision VFP instructions may be executed on both NEON and VFP
- // pipelines.
- let D = VFPNeonDomain;
+ // Some single precision VFP instructions may be executed on both NEON and
+ // VFP pipelines on A8.
+ let D = VFPNeonA8Domain;
}
} // Defs = [FPSCR]
@@ -423,9 +423,9 @@ def VNEGS : ASuIn<0b11101, 0b11, 0b0001, 0b01, 0,
(outs SPR:$Sd), (ins SPR:$Sm),
IIC_fpUNA32, "vneg", ".f32\t$Sd, $Sm",
[(set SPR:$Sd, (fneg SPR:$Sm))]> {
- // Some single precision VFP instructions may be executed on both NEON and VFP
- // pipelines.
- let D = VFPNeonDomain;
+ // Some single precision VFP instructions may be executed on both NEON and
+ // VFP pipelines on A8.
+ let D = VFPNeonA8Domain;
}
def VSQRTD : ADuI<0b11101, 0b11, 0b0001, 0b11, 0,
@@ -598,9 +598,9 @@ def VSITOS : AVConv1InSs_Encode<0b11101, 0b11, 0b1000, 0b1010,
[(set SPR:$Sd, (arm_sitof SPR:$Sm))]> {
let Inst{7} = 1; // s32
- // Some single precision VFP instructions may be executed on both NEON and VFP
- // pipelines.
- let D = VFPNeonDomain;
+ // Some single precision VFP instructions may be executed on both NEON and
+ // VFP pipelines on A8.
+ let D = VFPNeonA8Domain;
}
def VUITOD : AVConv1IDs_Encode<0b11101, 0b11, 0b1000, 0b1011,
@@ -616,9 +616,9 @@ def VUITOS : AVConv1InSs_Encode<0b11101, 0b11, 0b1000, 0b1010,
[(set SPR:$Sd, (arm_uitof SPR:$Sm))]> {
let Inst{7} = 0; // u32
- // Some single precision VFP instructions may be executed on both NEON and VFP
- // pipelines.
- let D = VFPNeonDomain;
+ // Some single precision VFP instructions may be executed on both NEON and
+ // VFP pipelines on A8.
+ let D = VFPNeonA8Domain;
}
// FP -> Int:
@@ -671,9 +671,9 @@ def VTOSIZS : AVConv1InsS_Encode<0b11101, 0b11, 0b1101, 0b1010,
[(set SPR:$Sd, (arm_ftosi SPR:$Sm))]> {
let Inst{7} = 1; // Z bit
- // Some single precision VFP instructions may be executed on both NEON and VFP
- // pipelines.
- let D = VFPNeonDomain;
+ // Some single precision VFP instructions may be executed on both NEON and
+ // VFP pipelines on A8.
+ let D = VFPNeonA8Domain;
}
def VTOUIZD : AVConv1IsD_Encode<0b11101, 0b11, 0b1100, 0b1011,
@@ -689,9 +689,9 @@ def VTOUIZS : AVConv1InsS_Encode<0b11101, 0b11, 0b1100, 0b1010,
[(set SPR:$Sd, (arm_ftoui SPR:$Sm))]> {
let Inst{7} = 1; // Z bit
- // Some single precision VFP instructions may be executed on both NEON and VFP
- // pipelines.
- let D = VFPNeonDomain;
+ // Some single precision VFP instructions may be executed on both NEON and
+ // VFP pipelines on A8.
+ let D = VFPNeonA8Domain;
}
// And the Z bit '0' variants, i.e. use the rounding mode specified by FPSCR.
@@ -743,36 +743,36 @@ def VTOSHS : AVConv1XI<0b11101, 0b11, 0b1110, 0b1010, 0,
(outs SPR:$dst), (ins SPR:$a, i32imm:$fbits),
IIC_fpCVTSI, "vcvt", ".s16.f32\t$dst, $a, $fbits",
[/* For disassembly only; pattern left blank */]> {
- // Some single precision VFP instructions may be executed on both NEON and VFP
- // pipelines.
- let D = VFPNeonDomain;
+ // Some single precision VFP instructions may be executed on both NEON and
+ // VFP pipelines on A8.
+ let D = VFPNeonA8Domain;
}
def VTOUHS : AVConv1XI<0b11101, 0b11, 0b1111, 0b1010, 0,
(outs SPR:$dst), (ins SPR:$a, i32imm:$fbits),
IIC_fpCVTSI, "vcvt", ".u16.f32\t$dst, $a, $fbits",
[/* For disassembly only; pattern left blank */]> {
- // Some single precision VFP instructions may be executed on both NEON and VFP
- // pipelines.
- let D = VFPNeonDomain;
+ // Some single precision VFP instructions may be executed on both NEON and
+ // VFP pipelines on A8.
+ let D = VFPNeonA8Domain;
}
def VTOSLS : AVConv1XI<0b11101, 0b11, 0b1110, 0b1010, 1,
(outs SPR:$dst), (ins SPR:$a, i32imm:$fbits),
IIC_fpCVTSI, "vcvt", ".s32.f32\t$dst, $a, $fbits",
[/* For disassembly only; pattern left blank */]> {
- // Some single precision VFP instructions may be executed on both NEON and VFP
- // pipelines.
- let D = VFPNeonDomain;
+ // Some single precision VFP instructions may be executed on both NEON and
+ // VFP pipelines on A8.
+ let D = VFPNeonA8Domain;
}
def VTOULS : AVConv1XI<0b11101, 0b11, 0b1111, 0b1010, 1,
(outs SPR:$dst), (ins SPR:$a, i32imm:$fbits),
IIC_fpCVTSI, "vcvt", ".u32.f32\t$dst, $a, $fbits",
[/* For disassembly only; pattern left blank */]> {
- // Some single precision VFP instructions may be executed on both NEON and VFP
- // pipelines.
- let D = VFPNeonDomain;
+ // Some single precision VFP instructions may be executed on both NEON and
+ // VFP pipelines on A8.
+ let D = VFPNeonA8Domain;
}
def VTOSHD : AVConv1XI<0b11101, 0b11, 0b1110, 0b1011, 0,
@@ -801,36 +801,36 @@ def VSHTOS : AVConv1XI<0b11101, 0b11, 0b1010, 0b1010, 0,
(outs SPR:$dst), (ins SPR:$a, i32imm:$fbits),
IIC_fpCVTIS, "vcvt", ".f32.s16\t$dst, $a, $fbits",
[/* For disassembly only; pattern left blank */]> {
- // Some single precision VFP instructions may be executed on both NEON and VFP
- // pipelines.
- let D = VFPNeonDomain;
+ // Some single precision VFP instructions may be executed on both NEON and
+ // VFP pipelines on A8.
+ let D = VFPNeonA8Domain;
}
def VUHTOS : AVConv1XI<0b11101, 0b11, 0b1011, 0b1010, 0,
(outs SPR:$dst), (ins SPR:$a, i32imm:$fbits),
IIC_fpCVTIS, "vcvt", ".f32.u16\t$dst, $a, $fbits",
[/* For disassembly only; pattern left blank */]> {
- // Some single precision VFP instructions may be executed on both NEON and VFP
- // pipelines.
- let D = VFPNeonDomain;
+ // Some single precision VFP instructions may be executed on both NEON and
+ // VFP pipelines on A8.
+ let D = VFPNeonA8Domain;
}
def VSLTOS : AVConv1XI<0b11101, 0b11, 0b1010, 0b1010, 1,
(outs SPR:$dst), (ins SPR:$a, i32imm:$fbits),
IIC_fpCVTIS, "vcvt", ".f32.s32\t$dst, $a, $fbits",
[/* For disassembly only; pattern left blank */]> {
- // Some single precision VFP instructions may be executed on both NEON and VFP
- // pipelines.
- let D = VFPNeonDomain;
+ // Some single precision VFP instructions may be executed on both NEON and
+ // VFP pipelines on A8.
+ let D = VFPNeonA8Domain;
}
def VULTOS : AVConv1XI<0b11101, 0b11, 0b1011, 0b1010, 1,
(outs SPR:$dst), (ins SPR:$a, i32imm:$fbits),
IIC_fpCVTIS, "vcvt", ".f32.u32\t$dst, $a, $fbits",
[/* For disassembly only; pattern left blank */]> {
- // Some single precision VFP instructions may be executed on both NEON and VFP
- // pipelines.
- let D = VFPNeonDomain;
+ // Some single precision VFP instructions may be executed on both NEON and
+ // VFP pipelines on A8.
+ let D = VFPNeonA8Domain;
}
def VSHTOD : AVConv1XI<0b11101, 0b11, 0b1010, 0b1011, 0,
@@ -874,9 +874,9 @@ def VMLAS : ASbIn<0b11100, 0b00, 0, 0,
SPR:$Sdin))]>,
RegConstraint<"$Sdin = $Sd">,
Requires<[HasVFP2,DontUseNEONForFP,UseFPVMLx]> {
- // Some single precision VFP instructions may be executed on both NEON and VFP
- // pipelines.
- let D = VFPNeonDomain;
+ // Some single precision VFP instructions may be executed on both NEON and
+ // VFP pipelines on A8.
+ let D = VFPNeonA8Domain;
}
def : Pat<(fadd_mlx DPR:$dstin, (fmul_su DPR:$a, (f64 DPR:$b))),
@@ -901,9 +901,9 @@ def VMLSS : ASbIn<0b11100, 0b00, 1, 0,
SPR:$Sdin))]>,
RegConstraint<"$Sdin = $Sd">,
Requires<[HasVFP2,DontUseNEONForFP,UseFPVMLx]> {
- // Some single precision VFP instructions may be executed on both NEON and VFP
- // pipelines.
- let D = VFPNeonDomain;
+ // Some single precision VFP instructions may be executed on both NEON and
+ // VFP pipelines on A8.
+ let D = VFPNeonA8Domain;
}
def : Pat<(fsub_mlx DPR:$dstin, (fmul_su DPR:$a, (f64 DPR:$b))),
@@ -928,9 +928,9 @@ def VNMLAS : ASbI<0b11100, 0b01, 1, 0,
SPR:$Sdin))]>,
RegConstraint<"$Sdin = $Sd">,
Requires<[HasVFP2,DontUseNEONForFP,UseFPVMLx]> {
- // Some single precision VFP instructions may be executed on both NEON and VFP
- // pipelines.
- let D = VFPNeonDomain;
+ // Some single precision VFP instructions may be executed on both NEON and
+ // VFP pipelines on A8.
+ let D = VFPNeonA8Domain;
}
def : Pat<(fsub_mlx (fneg (fmul_su DPR:$a, (f64 DPR:$b))), DPR:$dstin),
@@ -954,9 +954,9 @@ def VNMLSS : ASbI<0b11100, 0b01, 0, 0,
[(set SPR:$Sd, (fsub_mlx (fmul_su SPR:$Sn, SPR:$Sm), SPR:$Sdin))]>,
RegConstraint<"$Sdin = $Sd">,
Requires<[HasVFP2,DontUseNEONForFP,UseFPVMLx]> {
- // Some single precision VFP instructions may be executed on both NEON and VFP
- // pipelines.
- let D = VFPNeonDomain;
+ // Some single precision VFP instructions may be executed on both NEON and
+ // VFP pipelines on A8.
+ let D = VFPNeonA8Domain;
}
def : Pat<(fsub_mlx (fmul_su DPR:$a, (f64 DPR:$b)), DPR:$dstin),
@@ -995,9 +995,9 @@ def VNEGScc : ASuI<0b11101, 0b11, 0b0001, 0b01, 0,
IIC_fpUNA32, "vneg", ".f32\t$Sd, $Sm",
[/*(set SPR:$Sd, (ARMcneg SPR:$Sn, SPR:$Sm, imm:$cc))*/]>,
RegConstraint<"$Sn = $Sd"> {
- // Some single precision VFP instructions may be executed on both NEON and VFP
- // pipelines.
- let D = VFPNeonDomain;
+ // Some single precision VFP instructions may be executed on both NEON and
+ // VFP pipelines on A8.
+ let D = VFPNeonA8Domain;
}
} // neverHasSideEffects
diff --git a/contrib/llvm/lib/Target/ARM/ARMSubtarget.cpp b/contrib/llvm/lib/Target/ARM/ARMSubtarget.cpp
index 0bd740c..1465984 100644
--- a/contrib/llvm/lib/Target/ARM/ARMSubtarget.cpp
+++ b/contrib/llvm/lib/Target/ARM/ARMSubtarget.cpp
@@ -171,7 +171,9 @@ ARMSubtarget::GVIsIndirectSymbol(const GlobalValue *GV,
// Materializable GVs (in JIT lazy compilation mode) do not require an extra
// load from stub.
- bool isDecl = GV->isDeclaration() && !GV->isMaterializable();
+ bool isDecl = GV->hasAvailableExternallyLinkage();
+ if (GV->isDeclaration() && !GV->isMaterializable())
+ isDecl = true;
if (!isTargetDarwin()) {
// Extra load is needed for all externally visible.
diff --git a/contrib/llvm/lib/Target/ARM/MLxExpansionPass.cpp b/contrib/llvm/lib/Target/ARM/MLxExpansionPass.cpp
index f9e86eb..9a27e2f 100644
--- a/contrib/llvm/lib/Target/ARM/MLxExpansionPass.cpp
+++ b/contrib/llvm/lib/Target/ARM/MLxExpansionPass.cpp
@@ -132,22 +132,16 @@ unsigned MLxExpansion::getDefReg(MachineInstr *MI) const {
}
bool MLxExpansion::hasRAWHazard(unsigned Reg, MachineInstr *MI) const {
- const TargetInstrDesc &TID = MI->getDesc();
// FIXME: Detect integer instructions properly.
+ const TargetInstrDesc &TID = MI->getDesc();
unsigned Domain = TID.TSFlags & ARMII::DomainMask;
- if (Domain == ARMII::DomainVFP) {
- unsigned Opcode = TID.getOpcode();
- if (Opcode == ARM::VSTRS || Opcode == ARM::VSTRD ||
- Opcode == ARM::VMOVRS || Opcode == ARM::VMOVRRD)
- return false;
- } else if (Domain == ARMII::DomainNEON) {
- if (TID.mayStore() || TID.mayLoad())
- return false;
- } else {
+ if (TID.mayStore())
return false;
- }
-
- return MI->readsRegister(Reg, TRI);
+ unsigned Opcode = TID.getOpcode();
+ if (Opcode == ARM::VMOVRS || Opcode == ARM::VMOVRRD)
+ return false;
+ if ((Domain & ARMII::DomainVFP) || (Domain & ARMII::DomainNEON))
+ return MI->readsRegister(Reg, TRI);
return false;
}
diff --git a/contrib/llvm/lib/Target/ARM/NEONMoveFix.cpp b/contrib/llvm/lib/Target/ARM/NEONMoveFix.cpp
index 97e54bf..965665c 100644
--- a/contrib/llvm/lib/Target/ARM/NEONMoveFix.cpp
+++ b/contrib/llvm/lib/Target/ARM/NEONMoveFix.cpp
@@ -35,6 +35,7 @@ namespace {
private:
const TargetRegisterInfo *TRI;
const ARMBaseInstrInfo *TII;
+ bool isA8;
typedef DenseMap<unsigned, const MachineInstr*> RegMap;
@@ -43,6 +44,11 @@ namespace {
char NEONMoveFixPass::ID = 0;
}
+static bool inNEONDomain(unsigned Domain, bool isA8) {
+ return (Domain & ARMII::DomainNEON) ||
+ (isA8 && (Domain & ARMII::DomainNEONA8));
+}
+
bool NEONMoveFixPass::InsertMoves(MachineBasicBlock &MBB) {
RegMap Defs;
bool Modified = false;
@@ -70,7 +76,7 @@ bool NEONMoveFixPass::InsertMoves(MachineBasicBlock &MBB) {
Domain = ARMII::DomainNEON;
}
- if (Domain & ARMII::DomainNEON) {
+ if (inNEONDomain(Domain, isA8)) {
// Convert VMOVD to VMOVDneon
unsigned DestReg = MI->getOperand(0).getReg();
@@ -123,6 +129,7 @@ bool NEONMoveFixPass::runOnMachineFunction(MachineFunction &Fn) {
TRI = TM.getRegisterInfo();
TII = static_cast<const ARMBaseInstrInfo*>(TM.getInstrInfo());
+ isA8 = TM.getSubtarget<ARMSubtarget>().isCortexA8();
bool Modified = false;
for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E;
diff --git a/contrib/llvm/lib/Target/ARM/Thumb2InstrInfo.cpp b/contrib/llvm/lib/Target/ARM/Thumb2InstrInfo.cpp
index 2f67257..9b1073b 100644
--- a/contrib/llvm/lib/Target/ARM/Thumb2InstrInfo.cpp
+++ b/contrib/llvm/lib/Target/ARM/Thumb2InstrInfo.cpp
@@ -95,6 +95,12 @@ Thumb2InstrInfo::ReplaceTailWithBranchTo(MachineBasicBlock::iterator Tail,
bool
Thumb2InstrInfo::isLegalToSplitMBBAt(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI) const {
+ while (MBBI->isDebugValue()) {
+ ++MBBI;
+ if (MBBI == MBB.end())
+ return false;
+ }
+
unsigned PredReg = 0;
return llvm::getITInstrPredicate(MBBI, PredReg) == ARMCC::AL;
}
diff --git a/contrib/llvm/lib/Target/Alpha/AlphaISelLowering.cpp b/contrib/llvm/lib/Target/Alpha/AlphaISelLowering.cpp
index 9137d65..c4f43ab 100644
--- a/contrib/llvm/lib/Target/Alpha/AlphaISelLowering.cpp
+++ b/contrib/llvm/lib/Target/Alpha/AlphaISelLowering.cpp
@@ -48,7 +48,6 @@ AlphaTargetLowering::AlphaTargetLowering(TargetMachine &TM)
: TargetLowering(TM, new TargetLoweringObjectFileELF()) {
// Set up the TargetLowering object.
//I am having problems with shr n i8 1
- setShiftAmountType(MVT::i64);
setBooleanContents(ZeroOrOneBooleanContent);
addRegisterClass(MVT::i64, Alpha::GPRCRegisterClass);
diff --git a/contrib/llvm/lib/Target/Alpha/AlphaISelLowering.h b/contrib/llvm/lib/Target/Alpha/AlphaISelLowering.h
index b429e9f..cb98f92 100644
--- a/contrib/llvm/lib/Target/Alpha/AlphaISelLowering.h
+++ b/contrib/llvm/lib/Target/Alpha/AlphaISelLowering.h
@@ -31,25 +31,25 @@ namespace llvm {
/// GPRelHi/GPRelLo - These represent the high and low 16-bit
/// parts of a global address respectively.
- GPRelHi, GPRelLo,
+ GPRelHi, GPRelLo,
/// RetLit - Literal Relocation of a Global
RelLit,
/// GlobalRetAddr - used to restore the return address
GlobalRetAddr,
-
+
/// CALL - Normal call.
CALL,
/// DIVCALL - used for special library calls for div and rem
DivCall,
-
+
/// return flag operand
RET_FLAG,
/// CHAIN = COND_BRANCH CHAIN, OPC, (G|F)PRC, DESTBB [, INFLAG] - This
- /// corresponds to the COND_BRANCH pseudo instruction.
+ /// corresponds to the COND_BRANCH pseudo instruction.
/// *PRC is the input register to compare to zero,
/// OPC is the branch opcode to use (e.g. Alpha::BEQ),
/// DESTBB is the destination block to branch to, and INFLAG is
@@ -62,7 +62,9 @@ namespace llvm {
class AlphaTargetLowering : public TargetLowering {
public:
explicit AlphaTargetLowering(TargetMachine &TM);
-
+
+ virtual MVT getShiftAmountTy(EVT LHSTy) const { return MVT::i64; }
+
/// getSetCCResultType - Get the SETCC result ValueType
virtual MVT::SimpleValueType getSetCCResultType(EVT VT) const;
@@ -92,7 +94,7 @@ namespace llvm {
ConstraintWeight getSingleConstraintMatchWeight(
AsmOperandInfo &info, const char *constraint) const;
- std::vector<unsigned>
+ std::vector<unsigned>
getRegClassForInlineAsmConstraint(const std::string &Constraint,
EVT VT) const;
diff --git a/contrib/llvm/lib/Target/Blackfin/BlackfinISelLowering.cpp b/contrib/llvm/lib/Target/Blackfin/BlackfinISelLowering.cpp
index dd27d0a..7c80eec 100644
--- a/contrib/llvm/lib/Target/Blackfin/BlackfinISelLowering.cpp
+++ b/contrib/llvm/lib/Target/Blackfin/BlackfinISelLowering.cpp
@@ -41,7 +41,6 @@ using namespace llvm;
BlackfinTargetLowering::BlackfinTargetLowering(TargetMachine &TM)
: TargetLowering(TM, new TargetLoweringObjectFileELF()) {
- setShiftAmountType(MVT::i16);
setBooleanContents(ZeroOrOneBooleanContent);
setStackPointerRegisterToSaveRestore(BF::SP);
setIntDivIsCheap(false);
diff --git a/contrib/llvm/lib/Target/Blackfin/BlackfinISelLowering.h b/contrib/llvm/lib/Target/Blackfin/BlackfinISelLowering.h
index 15a745f..102c830 100644
--- a/contrib/llvm/lib/Target/Blackfin/BlackfinISelLowering.h
+++ b/contrib/llvm/lib/Target/Blackfin/BlackfinISelLowering.h
@@ -32,6 +32,7 @@ namespace llvm {
class BlackfinTargetLowering : public TargetLowering {
public:
BlackfinTargetLowering(TargetMachine &TM);
+ virtual MVT getShiftAmountTy(EVT LHSTy) const { return MVT::i16; }
virtual MVT::SimpleValueType getSetCCResultType(EVT VT) const;
virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const;
virtual void ReplaceNodeResults(SDNode *N,
diff --git a/contrib/llvm/lib/Target/CellSPU/SPUISelLowering.cpp b/contrib/llvm/lib/Target/CellSPU/SPUISelLowering.cpp
index e6511d0..743a4d7 100644
--- a/contrib/llvm/lib/Target/CellSPU/SPUISelLowering.cpp
+++ b/contrib/llvm/lib/Target/CellSPU/SPUISelLowering.cpp
@@ -435,7 +435,6 @@ SPUTargetLowering::SPUTargetLowering(SPUTargetMachine &TM)
setOperationAction(ISD::FDIV, MVT::v4f32, Legal);
- setShiftAmountType(MVT::i32);
setBooleanContents(ZeroOrNegativeOneBooleanContent);
setStackPointerRegisterToSaveRestore(SPU::R1);
@@ -1219,7 +1218,7 @@ SPUTargetLowering::LowerFormalArguments(SDValue Chain,
FuncInfo->setVarArgsFrameIndex(
MFI->CreateFixedObject(StackSlotSize, ArgOffset, true));
SDValue FIN = DAG.getFrameIndex(FuncInfo->getVarArgsFrameIndex(), PtrVT);
- unsigned VReg = MF.addLiveIn(ArgRegs[ArgRegIdx], &SPU::R32CRegClass, dl);
+ unsigned VReg = MF.addLiveIn(ArgRegs[ArgRegIdx], &SPU::R32CRegClass);
SDValue ArgVal = DAG.getRegister(VReg, MVT::v16i8);
SDValue Store = DAG.getStore(Chain, dl, ArgVal, FIN, MachinePointerInfo(),
false, false, 0);
@@ -2190,7 +2189,7 @@ static SDValue LowerI8Math(SDValue Op, SelectionDAG &DAG, unsigned Opc,
{
SDValue N0 = Op.getOperand(0); // Everything has at least one operand
DebugLoc dl = Op.getDebugLoc();
- EVT ShiftVT = TLI.getShiftAmountTy();
+ EVT ShiftVT = TLI.getShiftAmountTy(N0.getValueType());
assert(Op.getValueType() == MVT::i8);
switch (Opc) {
@@ -3112,7 +3111,7 @@ SPUTargetLowering::getSingleConstraintMatchWeight(
switch (*constraint) {
default:
weight = TargetLowering::getSingleConstraintMatchWeight(info, constraint);
- break;
+ break;
//FIXME: Seems like the supported constraint letters were just copied
// from PPC, as the following doesn't correspond to the GCC docs.
// I'm leaving it so until someone adds the corresponding lowering support.
diff --git a/contrib/llvm/lib/Target/CellSPU/SPUISelLowering.h b/contrib/llvm/lib/Target/CellSPU/SPUISelLowering.h
index 95d44af..dd48d7b 100644
--- a/contrib/llvm/lib/Target/CellSPU/SPUISelLowering.h
+++ b/contrib/llvm/lib/Target/CellSPU/SPUISelLowering.h
@@ -109,6 +109,8 @@ namespace llvm {
/// getSetCCResultType - Return the ValueType for ISD::SETCC
virtual MVT::SimpleValueType getSetCCResultType(EVT VT) const;
+ virtual MVT getShiftAmountTy(EVT LHSTy) const { return MVT::i32; }
+
//! Custom lowering hooks
virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const;
@@ -179,9 +181,9 @@ namespace llvm {
virtual bool isLegalICmpImmediate(int64_t Imm) const;
- virtual bool isLegalAddressingMode(const AddrMode &AM,
+ virtual bool isLegalAddressingMode(const AddrMode &AM,
const Type *Ty) const;
-
+
/// After allocating this many registers, the allocator should feel
/// register pressure. The value is a somewhat random guess, based on the
/// number of non callee saved registers in the C calling convention.
diff --git a/contrib/llvm/lib/Target/MBlaze/MBlazeISelLowering.cpp b/contrib/llvm/lib/Target/MBlaze/MBlazeISelLowering.cpp
index 2f40bfc..f39826b 100644
--- a/contrib/llvm/lib/Target/MBlaze/MBlazeISelLowering.cpp
+++ b/contrib/llvm/lib/Target/MBlaze/MBlazeISelLowering.cpp
@@ -907,7 +907,7 @@ LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
// Transform the arguments stored on
// physical registers into virtual ones
- unsigned Reg = MF.addLiveIn(ArgRegEnd, RC, dl);
+ unsigned Reg = MF.addLiveIn(ArgRegEnd, RC);
SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, Reg, RegVT);
// If this is an 8 or 16-bit value, it has been passed promoted
@@ -973,7 +973,7 @@ LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
for (; Start <= End; ++Start, ++StackLoc) {
unsigned Reg = MBlazeRegisterInfo::getRegisterFromNumbering(Start);
- unsigned LiveReg = MF.addLiveIn(Reg, RC, dl);
+ unsigned LiveReg = MF.addLiveIn(Reg, RC);
SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, LiveReg, MVT::i32);
int FI = MFI->CreateFixedObject(4, 0, true);
diff --git a/contrib/llvm/lib/Target/MSP430/MSP430ISelLowering.cpp b/contrib/llvm/lib/Target/MSP430/MSP430ISelLowering.cpp
index 30ef4f5..a95d59c 100644
--- a/contrib/llvm/lib/Target/MSP430/MSP430ISelLowering.cpp
+++ b/contrib/llvm/lib/Target/MSP430/MSP430ISelLowering.cpp
@@ -77,10 +77,6 @@ MSP430TargetLowering::MSP430TargetLowering(MSP430TargetMachine &tm) :
// Division is expensive
setIntDivIsCheap(false);
- // Even if we have only 1 bit shift here, we can perform
- // shifts of the whole bitwidth 1 bit per step.
- setShiftAmountType(MVT::i8);
-
setStackPointerRegisterToSaveRestore(MSP430::SPW);
setBooleanContents(ZeroOrOneBooleanContent);
setSchedulingPreference(Sched::Latency);
@@ -330,7 +326,7 @@ MSP430TargetLowering::LowerCCCArguments(SDValue Chain,
// Arguments passed in registers
EVT RegVT = VA.getLocVT();
switch (RegVT.getSimpleVT().SimpleTy) {
- default:
+ default:
{
#ifndef NDEBUG
errs() << "LowerFormalArguments Unhandled argument type: "
diff --git a/contrib/llvm/lib/Target/MSP430/MSP430ISelLowering.h b/contrib/llvm/lib/Target/MSP430/MSP430ISelLowering.h
index 673c543..19c9eac 100644
--- a/contrib/llvm/lib/Target/MSP430/MSP430ISelLowering.h
+++ b/contrib/llvm/lib/Target/MSP430/MSP430ISelLowering.h
@@ -73,6 +73,8 @@ namespace llvm {
public:
explicit MSP430TargetLowering(MSP430TargetMachine &TM);
+ virtual MVT getShiftAmountTy(EVT LHSTy) const { return MVT::i8; }
+
/// LowerOperation - Provide custom lowering hooks for some operations.
virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const;
diff --git a/contrib/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/contrib/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index 8f623b8..70d00e4 100644
--- a/contrib/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/contrib/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -362,7 +362,6 @@ PPCTargetLowering::PPCTargetLowering(PPCTargetMachine &TM)
setOperationAction(ISD::BUILD_VECTOR, MVT::v4f32, Custom);
}
- setShiftAmountType(MVT::i32);
setBooleanContents(ZeroOrOneBooleanContent);
if (TM.getSubtarget<PPCSubtarget>().isPPC64()) {
@@ -1597,7 +1596,7 @@ PPCTargetLowering::LowerFormalArguments_SVR4(
}
// Transform the arguments stored in physical registers into virtual ones.
- unsigned Reg = MF.addLiveIn(VA.getLocReg(), RC, dl);
+ unsigned Reg = MF.addLiveIn(VA.getLocReg(), RC);
SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, Reg, ValVT);
InVals.push_back(ArgValue);
@@ -1689,7 +1688,7 @@ PPCTargetLowering::LowerFormalArguments_SVR4(
// Get an existing live-in vreg, or add a new one.
unsigned VReg = MF.getRegInfo().getLiveInVirtReg(GPArgRegs[GPRIndex]);
if (!VReg)
- VReg = MF.addLiveIn(GPArgRegs[GPRIndex], &PPC::GPRCRegClass, dl);
+ VReg = MF.addLiveIn(GPArgRegs[GPRIndex], &PPC::GPRCRegClass);
SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, PtrVT);
SDValue Store = DAG.getStore(Val.getValue(1), dl, Val, FIN,
@@ -1708,7 +1707,7 @@ PPCTargetLowering::LowerFormalArguments_SVR4(
// Get an existing live-in vreg, or add a new one.
unsigned VReg = MF.getRegInfo().getLiveInVirtReg(FPArgRegs[FPRIndex]);
if (!VReg)
- VReg = MF.addLiveIn(FPArgRegs[FPRIndex], &PPC::F8RCRegClass, dl);
+ VReg = MF.addLiveIn(FPArgRegs[FPRIndex], &PPC::F8RCRegClass);
SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, MVT::f64);
SDValue Store = DAG.getStore(Val.getValue(1), dl, Val, FIN,
@@ -1872,7 +1871,7 @@ PPCTargetLowering::LowerFormalArguments_Darwin(
InVals.push_back(FIN);
if (ObjSize==1 || ObjSize==2) {
if (GPR_idx != Num_GPR_Regs) {
- unsigned VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::GPRCRegClass, dl);
+ unsigned VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::GPRCRegClass);
SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, PtrVT);
SDValue Store = DAG.getTruncStore(Val.getValue(1), dl, Val, FIN,
MachinePointerInfo(),
@@ -1891,7 +1890,7 @@ PPCTargetLowering::LowerFormalArguments_Darwin(
// to memory. ArgVal will be address of the beginning of
// the object.
if (GPR_idx != Num_GPR_Regs) {
- unsigned VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::GPRCRegClass, dl);
+ unsigned VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::GPRCRegClass);
int FI = MFI->CreateFixedObject(PtrByteSize, ArgOffset, true);
SDValue FIN = DAG.getFrameIndex(FI, PtrVT);
SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, PtrVT);
@@ -1914,7 +1913,7 @@ PPCTargetLowering::LowerFormalArguments_Darwin(
case MVT::i32:
if (!isPPC64) {
if (GPR_idx != Num_GPR_Regs) {
- unsigned VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::GPRCRegClass, dl);
+ unsigned VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::GPRCRegClass);
ArgVal = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32);
++GPR_idx;
} else {
@@ -1928,7 +1927,7 @@ PPCTargetLowering::LowerFormalArguments_Darwin(
// FALLTHROUGH
case MVT::i64: // PPC64
if (GPR_idx != Num_GPR_Regs) {
- unsigned VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::G8RCRegClass, dl);
+ unsigned VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::G8RCRegClass);
ArgVal = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i64);
if (ObjectVT == MVT::i32) {
@@ -1966,9 +1965,9 @@ PPCTargetLowering::LowerFormalArguments_Darwin(
unsigned VReg;
if (ObjectVT == MVT::f32)
- VReg = MF.addLiveIn(FPR[FPR_idx], &PPC::F4RCRegClass, dl);
+ VReg = MF.addLiveIn(FPR[FPR_idx], &PPC::F4RCRegClass);
else
- VReg = MF.addLiveIn(FPR[FPR_idx], &PPC::F8RCRegClass, dl);
+ VReg = MF.addLiveIn(FPR[FPR_idx], &PPC::F8RCRegClass);
ArgVal = DAG.getCopyFromReg(Chain, dl, VReg, ObjectVT);
++FPR_idx;
@@ -1986,7 +1985,7 @@ PPCTargetLowering::LowerFormalArguments_Darwin(
// Note that vector arguments in registers don't reserve stack space,
// except in varargs functions.
if (VR_idx != Num_VR_Regs) {
- unsigned VReg = MF.addLiveIn(VR[VR_idx], &PPC::VRRCRegClass, dl);
+ unsigned VReg = MF.addLiveIn(VR[VR_idx], &PPC::VRRCRegClass);
ArgVal = DAG.getCopyFromReg(Chain, dl, VReg, ObjectVT);
if (isVarArg) {
while ((ArgOffset % 16) != 0) {
@@ -2064,9 +2063,9 @@ PPCTargetLowering::LowerFormalArguments_Darwin(
unsigned VReg;
if (isPPC64)
- VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::G8RCRegClass, dl);
+ VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::G8RCRegClass);
else
- VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::GPRCRegClass, dl);
+ VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::GPRCRegClass);
SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, PtrVT);
SDValue Store = DAG.getStore(Val.getValue(1), dl, Val, FIN,
diff --git a/contrib/llvm/lib/Target/PowerPC/PPCISelLowering.h b/contrib/llvm/lib/Target/PowerPC/PPCISelLowering.h
index 80cab75..33daae9 100644
--- a/contrib/llvm/lib/Target/PowerPC/PPCISelLowering.h
+++ b/contrib/llvm/lib/Target/PowerPC/PPCISelLowering.h
@@ -29,36 +29,36 @@ namespace llvm {
/// FSEL - Traditional three-operand fsel node.
///
FSEL,
-
+
/// FCFID - The FCFID instruction, taking an f64 operand and producing
/// and f64 value containing the FP representation of the integer that
/// was temporarily in the f64 operand.
FCFID,
-
- /// FCTI[D,W]Z - The FCTIDZ and FCTIWZ instructions, taking an f32 or f64
+
+ /// FCTI[D,W]Z - The FCTIDZ and FCTIWZ instructions, taking an f32 or f64
/// operand, producing an f64 value containing the integer representation
/// of that FP value.
FCTIDZ, FCTIWZ,
-
+
/// STFIWX - The STFIWX instruction. The first operand is an input token
/// chain, then an f64 value to store, then an address to store it to.
STFIWX,
-
+
// VMADDFP, VNMSUBFP - The VMADDFP and VNMSUBFP instructions, taking
// three v4f32 operands and producing a v4f32 result.
VMADDFP, VNMSUBFP,
-
+
/// VPERM - The PPC VPERM Instruction.
///
VPERM,
-
+
/// Hi/Lo - These represent the high and low 16-bit parts of a global
/// address respectively. These nodes have two operands, the first of
/// which must be a TargetGlobalAddress, and the second of which must be a
/// Constant. Selected naively, these turn into 'lis G+C' and 'li G+C',
/// though these are usually folded into other nodes.
Hi, Lo,
-
+
TOC_ENTRY,
/// The following three target-specific nodes are used for calls through
@@ -80,37 +80,37 @@ namespace llvm {
/// This instruction is lowered in PPCRegisterInfo::eliminateFrameIndex to
/// compute an allocation on the stack.
DYNALLOC,
-
+
/// GlobalBaseReg - On Darwin, this node represents the result of the mflr
/// at function entry, used for PIC code.
GlobalBaseReg,
-
+
/// These nodes represent the 32-bit PPC shifts that operate on 6-bit
/// shift amounts. These nodes are generated by the multi-precision shift
/// code.
SRL, SRA, SHL,
-
+
/// EXTSW_32 - This is the EXTSW instruction for use with "32-bit"
/// registers.
EXTSW_32,
/// CALL - A direct function call.
CALL_Darwin, CALL_SVR4,
-
+
/// NOP - Special NOP which follows 64-bit SVR4 calls.
NOP,
/// CHAIN,FLAG = MTCTR(VAL, CHAIN[, INFLAG]) - Directly corresponds to a
/// MTCTR instruction.
MTCTR,
-
+
/// CHAIN,FLAG = BCTRL(CHAIN, INFLAG) - Directly corresponds to a
/// BCTRL instruction.
BCTRL_Darwin, BCTRL_SVR4,
-
+
/// Return with a flag operand, matched by 'blr'
RET_FLAG,
-
+
/// R32 = MFCR(CRREG, INFLAG) - Represents the MFCRpseud/MFOCRF
/// instructions. This copies the bits corresponding to the specified
/// CRREG into the resultant GPR. Bits corresponding to other CR regs
@@ -122,20 +122,20 @@ namespace llvm {
/// encoding for the OPC field to identify the compare. For example, 838
/// is VCMPGTSH.
VCMP,
-
+
/// RESVEC, OUTFLAG = VCMPo(LHS, RHS, OPC) - Represents one of the
- /// altivec VCMP*o instructions. For lack of better number, we use the
+ /// altivec VCMP*o instructions. For lack of better number, we use the
/// opcode number encoding for the OPC field to identify the compare. For
/// example, 838 is VCMPGTSH.
VCMPo,
-
+
/// CHAIN = COND_BRANCH CHAIN, CRRC, OPC, DESTBB [, INFLAG] - This
/// corresponds to the COND_BRANCH pseudo instruction. CRRC is the
/// condition register to branch on, OPC is the branch opcode to use (e.g.
/// PPC::BLE), DESTBB is the destination block to branch to, and INFLAG is
/// an optional input flag argument.
COND_BRANCH,
-
+
// The following 5 instructions are used only as part of the
// long double-to-int conversion sequence.
@@ -150,7 +150,7 @@ namespace llvm {
MTFSB1,
/// F8RC, OUTFLAG = FADDRTZ F8RC, F8RC, INFLAG - This is an FADD done with
- /// rounding towards zero. It has flags added so it won't move past the
+ /// rounding towards zero. It has flags added so it won't move past the
/// FPSCR-setting instructions.
FADDRTZ,
@@ -174,14 +174,14 @@ namespace llvm {
/// STD_32 - This is the STD instruction for use with "32-bit" registers.
STD_32 = ISD::FIRST_TARGET_MEMORY_OPCODE,
-
- /// CHAIN = STBRX CHAIN, GPRC, Ptr, Type - This is a
+
+ /// CHAIN = STBRX CHAIN, GPRC, Ptr, Type - This is a
/// byte-swapping store instruction. It byte-swaps the low "Type" bits of
/// the GPRC input, then stores it through Ptr. Type can be either i16 or
/// i32.
- STBRX,
-
- /// GPRC, CHAIN = LBRX CHAIN, Ptr, Type - This is a
+ STBRX,
+
+ /// GPRC, CHAIN = LBRX CHAIN, Ptr, Type - This is a
/// byte-swapping load instruction. It loads "Type" bits, byte swaps it,
/// then puts it in the bottom bits of the GPRC. TYPE can be either i16
/// or i32.
@@ -194,7 +194,7 @@ namespace llvm {
/// isVPKUHUMShuffleMask - Return true if this is the shuffle mask for a
/// VPKUHUM instruction.
bool isVPKUHUMShuffleMask(ShuffleVectorSDNode *N, bool isUnary);
-
+
/// isVPKUWUMShuffleMask - Return true if this is the shuffle mask for a
/// VPKUWUM instruction.
bool isVPKUWUMShuffleMask(ShuffleVectorSDNode *N, bool isUnary);
@@ -208,16 +208,16 @@ namespace llvm {
/// a VRGH* instruction with the specified unit size (1,2 or 4 bytes).
bool isVMRGHShuffleMask(ShuffleVectorSDNode *N, unsigned UnitSize,
bool isUnary);
-
+
/// isVSLDOIShuffleMask - If this is a vsldoi shuffle mask, return the shift
/// amount, otherwise return -1.
int isVSLDOIShuffleMask(SDNode *N, bool isUnary);
-
+
/// isSplatShuffleMask - Return true if the specified VECTOR_SHUFFLE operand
/// specifies a splat of a single element that is suitable for input to
/// VSPLTB/VSPLTH/VSPLTW.
bool isSplatShuffleMask(ShuffleVectorSDNode *N, unsigned EltSize);
-
+
/// isAllNegativeZeroVector - Returns true if all elements of build_vector
/// are -0.0.
bool isAllNegativeZeroVector(SDNode *N);
@@ -225,24 +225,26 @@ namespace llvm {
/// getVSPLTImmediate - Return the appropriate VSPLT* immediate to splat the
/// specified isSplatShuffleMask VECTOR_SHUFFLE mask.
unsigned getVSPLTImmediate(SDNode *N, unsigned EltSize);
-
+
/// get_VSPLTI_elt - If this is a build_vector of constants which can be
/// formed by using a vspltis[bhw] instruction of the specified element
/// size, return the constant being splatted. The ByteSize field indicates
/// the number of bytes of each element [124] -> [bhw].
SDValue get_VSPLTI_elt(SDNode *N, unsigned ByteSize, SelectionDAG &DAG);
}
-
+
class PPCTargetLowering : public TargetLowering {
const PPCSubtarget &PPCSubTarget;
public:
explicit PPCTargetLowering(PPCTargetMachine &TM);
-
+
/// getTargetNodeName() - This method returns the name of a target specific
/// DAG node.
virtual const char *getTargetNodeName(unsigned Opcode) const;
+ virtual MVT getShiftAmountTy(EVT LHSTy) const { return MVT::i32; }
+
/// getSetCCResultType - Return the ISD::SETCC ValueType
virtual MVT::SimpleValueType getSetCCResultType(EVT VT) const;
@@ -253,19 +255,19 @@ namespace llvm {
SDValue &Offset,
ISD::MemIndexedMode &AM,
SelectionDAG &DAG) const;
-
+
/// SelectAddressRegReg - Given the specified addressed, check to see if it
/// can be represented as an indexed [r+r] operation. Returns false if it
/// can be more efficiently represented with [r+imm].
bool SelectAddressRegReg(SDValue N, SDValue &Base, SDValue &Index,
SelectionDAG &DAG) const;
-
+
/// SelectAddressRegImm - Returns true if the address N can be represented
/// by a base register plus a signed 16-bit displacement [r+imm], and if it
/// is not better represented as reg+reg.
bool SelectAddressRegImm(SDValue N, SDValue &Disp, SDValue &Base,
SelectionDAG &DAG) const;
-
+
/// SelectAddressRegRegOnly - Given the specified addressed, force it to be
/// represented as an indexed [r+r] operation.
bool SelectAddressRegRegOnly(SDValue N, SDValue &Base, SDValue &Index,
@@ -277,7 +279,7 @@ namespace llvm {
bool SelectAddressRegImmShift(SDValue N, SDValue &Disp, SDValue &Base,
SelectionDAG &DAG) const;
-
+
/// LowerOperation - Provide custom lowering hooks for some operations.
///
virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const;
@@ -289,10 +291,10 @@ namespace llvm {
SelectionDAG &DAG) const;
virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const;
-
+
virtual void computeMaskedBitsForTargetNode(const SDValue Op,
const APInt &Mask,
- APInt &KnownZero,
+ APInt &KnownZero,
APInt &KnownOne,
const SelectionDAG &DAG,
unsigned Depth = 0) const;
@@ -300,13 +302,13 @@ namespace llvm {
virtual MachineBasicBlock *
EmitInstrWithCustomInserter(MachineInstr *MI,
MachineBasicBlock *MBB) const;
- MachineBasicBlock *EmitAtomicBinary(MachineInstr *MI,
+ MachineBasicBlock *EmitAtomicBinary(MachineInstr *MI,
MachineBasicBlock *MBB, bool is64Bit,
unsigned BinOpcode) const;
- MachineBasicBlock *EmitPartwordAtomicBinary(MachineInstr *MI,
- MachineBasicBlock *MBB,
+ MachineBasicBlock *EmitPartwordAtomicBinary(MachineInstr *MI,
+ MachineBasicBlock *MBB,
bool is8bit, unsigned Opcode) const;
-
+
ConstraintType getConstraintType(const std::string &Constraint) const;
/// Examine constraint string and operand type and determine a weight value.
@@ -314,7 +316,7 @@ namespace llvm {
ConstraintWeight getSingleConstraintMatchWeight(
AsmOperandInfo &info, const char *constraint) const;
- std::pair<unsigned, const TargetRegisterClass*>
+ std::pair<unsigned, const TargetRegisterClass*>
getRegForInlineAsmConstraint(const std::string &Constraint,
EVT VT) const;
@@ -329,11 +331,11 @@ namespace llvm {
char ConstraintLetter,
std::vector<SDValue> &Ops,
SelectionDAG &DAG) const;
-
+
/// isLegalAddressingMode - Return true if the addressing mode represented
/// by AM is legal for this target, for a load/store of the specified type.
virtual bool isLegalAddressingMode(const AddrMode &AM, const Type *Ty)const;
-
+
/// isLegalAddressImmediate - Return true if the integer value can be used
/// as the offset of the target addressing mode for load / store of the
/// given type.
@@ -344,7 +346,7 @@ namespace llvm {
virtual bool isLegalAddressImmediate(GlobalValue *GV) const;
virtual bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const;
-
+
/// getOptimalMemOpType - Returns the target specific optimal type for load
/// and store operations as a result of memset, memcpy, and memmove
/// lowering. If DstAlign is zero that means it's safe to destination
diff --git a/contrib/llvm/lib/Target/Sparc/DelaySlotFiller.cpp b/contrib/llvm/lib/Target/Sparc/DelaySlotFiller.cpp
index ee29275..4b12852 100644
--- a/contrib/llvm/lib/Target/Sparc/DelaySlotFiller.cpp
+++ b/contrib/llvm/lib/Target/Sparc/DelaySlotFiller.cpp
@@ -79,6 +79,7 @@ namespace {
MachineBasicBlock::iterator
findDelayInstr(MachineBasicBlock &MBB, MachineBasicBlock::iterator slot);
+ bool needsUnimp(MachineBasicBlock::iterator I, unsigned &StructSize);
};
char Filler::ID = 0;
@@ -91,6 +92,7 @@ FunctionPass *llvm::createSparcDelaySlotFillerPass(TargetMachine &tm) {
return new Filler(tm);
}
+
/// runOnMachineBasicBlock - Fill in delay slots for the given basic block.
/// We assume there is only one delay slot per delayed instruction.
///
@@ -112,6 +114,13 @@ bool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) {
BuildMI(MBB, ++J, I->getDebugLoc(), TII->get(SP::NOP));
else
MBB.splice(++J, &MBB, D);
+ unsigned structSize = 0;
+ if (needsUnimp(I, structSize)) {
+ MachineBasicBlock::iterator J = I;
+ ++J; //skip the delay filler.
+ BuildMI(MBB, ++J, I->getDebugLoc(),
+ TII->get(SP::UNIMP)).addImm(structSize);
+ }
}
return Changed;
}
@@ -287,6 +296,28 @@ bool Filler::isDelayFiller(MachineBasicBlock &MBB,
{
if (candidate == MBB.begin())
return false;
+ if (candidate->getOpcode() == SP::UNIMP)
+ return true;
const TargetInstrDesc &prevdesc = (--candidate)->getDesc();
return prevdesc.hasDelaySlot();
}
+
+bool Filler::needsUnimp(MachineBasicBlock::iterator I, unsigned &StructSize)
+{
+ if (!I->getDesc().isCall())
+ return false;
+
+ unsigned structSizeOpNum = 0;
+ switch (I->getOpcode()) {
+ default: llvm_unreachable("Unknown call opcode.");
+ case SP::CALL: structSizeOpNum = 1; break;
+ case SP::JMPLrr:
+ case SP::JMPLri: structSizeOpNum = 2; break;
+ }
+
+ const MachineOperand &MO = I->getOperand(structSizeOpNum);
+ if (!MO.isImm())
+ return false;
+ StructSize = MO.getImm();
+ return true;
+}
diff --git a/contrib/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/contrib/llvm/lib/Target/Sparc/SparcISelLowering.cpp
index 196b87d..70574c3 100644
--- a/contrib/llvm/lib/Target/Sparc/SparcISelLowering.cpp
+++ b/contrib/llvm/lib/Target/Sparc/SparcISelLowering.cpp
@@ -16,7 +16,9 @@
#include "SparcISelLowering.h"
#include "SparcTargetMachine.h"
#include "SparcMachineFunctionInfo.h"
+#include "llvm/DerivedTypes.h"
#include "llvm/Function.h"
+#include "llvm/Module.h"
#include "llvm/CodeGen/CallingConvLower.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
@@ -116,6 +118,8 @@ SparcTargetLowering::LowerReturn(SDValue Chain,
// Guarantee that all emitted copies are stuck together with flags.
Flag = Chain.getValue(1);
}
+
+ unsigned RetAddrOffset = 8; //Call Inst + Delay Slot
// If the function returns a struct, copy the SRetReturnReg to I0
if (MF.getFunction()->hasStructRetAttr()) {
SparcMachineFunctionInfo *SFI = MF.getInfo<SparcMachineFunctionInfo>();
@@ -127,11 +131,16 @@ SparcTargetLowering::LowerReturn(SDValue Chain,
Flag = Chain.getValue(1);
if (MF.getRegInfo().liveout_empty())
MF.getRegInfo().addLiveOut(SP::I0);
+ RetAddrOffset = 12; // CallInst + Delay Slot + Unimp
}
+ SDValue RetAddrOffsetNode = DAG.getConstant(RetAddrOffset, MVT::i32);
+
if (Flag.getNode())
- return DAG.getNode(SPISD::RET_FLAG, dl, MVT::Other, Chain, Flag);
- return DAG.getNode(SPISD::RET_FLAG, dl, MVT::Other, Chain);
+ return DAG.getNode(SPISD::RET_FLAG, dl, MVT::Other, Chain,
+ RetAddrOffsetNode, Flag);
+ return DAG.getNode(SPISD::RET_FLAG, dl, MVT::Other, Chain,
+ RetAddrOffsetNode);
}
/// LowerFormalArguments - V8 uses a very simple ABI, where all values are
@@ -194,7 +203,7 @@ SparcTargetLowering::LowerFormalArguments(SDValue Chain,
false, false, 0);
} else {
unsigned loReg = MF.addLiveIn(NextVA.getLocReg(),
- &SP::IntRegsRegClass, dl);
+ &SP::IntRegsRegClass);
LoVal = DAG.getCopyFromReg(Chain, dl, loReg, MVT::i32);
}
SDValue WholeValue =
@@ -393,6 +402,7 @@ SparcTargetLowering::LowerCall(SDValue Chain, SDValue Callee,
SmallVector<SDValue, 8> MemOpChains;
const unsigned StackOffset = 92;
+ bool hasStructRetAttr = false;
// Walk the register/memloc assignments, inserting copies/loads.
for (unsigned i = 0, realArgIdx = 0, byvalArgIdx = 0, e = ArgLocs.size();
i != e;
@@ -433,6 +443,7 @@ SparcTargetLowering::LowerCall(SDValue Chain, SDValue Callee,
MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff,
MachinePointerInfo(),
false, false, 0));
+ hasStructRetAttr = true;
continue;
}
@@ -546,6 +557,8 @@ SparcTargetLowering::LowerCall(SDValue Chain, SDValue Callee,
InFlag = Chain.getValue(1);
}
+ unsigned SRetArgSize = (hasStructRetAttr)? getSRetArgSize(DAG, Callee):0;
+
// If the callee is a GlobalAddress node (quite common, every direct call is)
// turn it into a TargetGlobalAddress node so that legalize doesn't hack it.
// Likewise ExternalSymbol -> TargetExternalSymbol.
@@ -559,6 +572,8 @@ SparcTargetLowering::LowerCall(SDValue Chain, SDValue Callee,
SmallVector<SDValue, 8> Ops;
Ops.push_back(Chain);
Ops.push_back(Callee);
+ if (hasStructRetAttr)
+ Ops.push_back(DAG.getTargetConstant(SRetArgSize, MVT::i32));
for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
unsigned Reg = RegsToPass[i].first;
if (Reg >= SP::I0 && Reg <= SP::I7)
@@ -600,7 +615,29 @@ SparcTargetLowering::LowerCall(SDValue Chain, SDValue Callee,
return Chain;
}
+unsigned
+SparcTargetLowering::getSRetArgSize(SelectionDAG &DAG, SDValue Callee) const
+{
+ const Function *CalleeFn = 0;
+ if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
+ CalleeFn = dyn_cast<Function>(G->getGlobal());
+ } else if (ExternalSymbolSDNode *E =
+ dyn_cast<ExternalSymbolSDNode>(Callee)) {
+ const Function *Fn = DAG.getMachineFunction().getFunction();
+ const Module *M = Fn->getParent();
+ CalleeFn = M->getFunction(E->getSymbol());
+ }
+
+ if (!CalleeFn)
+ return 0;
+ assert(CalleeFn->hasStructRetAttr() &&
+ "Callee does not have the StructRet attribute.");
+
+ const PointerType *Ty = cast<PointerType>(CalleeFn->arg_begin()->getType());
+ const Type *ElementTy = Ty->getElementType();
+ return getTargetData()->getTypeAllocSize(ElementTy);
+}
//===----------------------------------------------------------------------===//
// TargetLowering Implementation
diff --git a/contrib/llvm/lib/Target/Sparc/SparcISelLowering.h b/contrib/llvm/lib/Target/Sparc/SparcISelLowering.h
index 849e401..7d02df8 100644
--- a/contrib/llvm/lib/Target/Sparc/SparcISelLowering.h
+++ b/contrib/llvm/lib/Target/Sparc/SparcISelLowering.h
@@ -101,6 +101,8 @@ namespace llvm {
SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG) const;
+
+ unsigned getSRetArgSize(SelectionDAG &DAG, SDValue Callee) const;
};
} // end namespace llvm
diff --git a/contrib/llvm/lib/Target/Sparc/SparcInstrInfo.td b/contrib/llvm/lib/Target/Sparc/SparcInstrInfo.td
index 1072323..cf5c48f 100644
--- a/contrib/llvm/lib/Target/Sparc/SparcInstrInfo.td
+++ b/contrib/llvm/lib/Target/Sparc/SparcInstrInfo.td
@@ -124,7 +124,8 @@ def call : SDNode<"SPISD::CALL", SDT_SPCall,
[SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,
SDNPVariadic]>;
-def retflag : SDNode<"SPISD::RET_FLAG", SDTNone,
+def SDT_SPRet : SDTypeProfile<0, 1, [SDTCisVT<0, i32>]>;
+def retflag : SDNode<"SPISD::RET_FLAG", SDT_SPRet,
[SDNPHasChain, SDNPOptInGlue]>;
def flushw : SDNode<"SPISD::FLUSHW", SDTNone,
@@ -132,7 +133,7 @@ def flushw : SDNode<"SPISD::FLUSHW", SDTNone,
def getPCX : Operand<i32> {
let PrintMethod = "printGetPCX";
-}
+}
//===----------------------------------------------------------------------===//
// SPARC Flag Conditions
@@ -232,6 +233,9 @@ let hasSideEffects = 1, mayStore = 1 in {
[(flushw)]>;
}
+def UNIMP : F2_1<0b000, (outs), (ins i32imm:$val),
+ "unimp $val", []>;
+
// FpMOVD/FpNEGD/FpABSD - These are lowered to single-precision ops by the
// fpmover pass.
let Predicates = [HasNoV9] in { // Only emit these in V8 mode.
@@ -292,11 +296,13 @@ let usesCustomInserter = 1, Uses = [FCC] in {
// Section A.3 - Synthetic Instructions, p. 85
// special cases of JMPL:
let isReturn = 1, isTerminator = 1, hasDelaySlot = 1, isBarrier = 1 in {
- let rd = O7.Num, rs1 = G0.Num, simm13 = 8 in
- def RETL: F3_2<2, 0b111000, (outs), (ins), "retl", [(retflag)]>;
+ let rd = O7.Num, rs1 = G0.Num in
+ def RETL: F3_2<2, 0b111000, (outs), (ins i32imm:$val),
+ "jmp %o7+$val", [(retflag simm13:$val)]>;
- let rd = I7.Num, rs1 = G0.Num, simm13 = 8 in
- def RET: F3_2<2, 0b111000, (outs), (ins), "ret", []>;
+ let rd = I7.Num, rs1 = G0.Num in
+ def RET: F3_2<2, 0b111000, (outs), (ins i32imm:$val),
+ "jmp %i7+$val", []>;
}
// Section B.1 - Load Integer Instructions, p. 90
diff --git a/contrib/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/contrib/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
index d694f2e..90939c3 100644
--- a/contrib/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
+++ b/contrib/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
@@ -59,9 +59,6 @@ SystemZTargetLowering::SystemZTargetLowering(SystemZTargetMachine &tm) :
// Compute derived properties from the register classes
computeRegisterProperties();
- // Set shifts properties
- setShiftAmountType(MVT::i64);
-
// Provide all sorts of operation actions
setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote);
setLoadExtAction(ISD::ZEXTLOAD, MVT::i1, Promote);
diff --git a/contrib/llvm/lib/Target/SystemZ/SystemZISelLowering.h b/contrib/llvm/lib/Target/SystemZ/SystemZISelLowering.h
index 51d2df3..3019242 100644
--- a/contrib/llvm/lib/Target/SystemZ/SystemZISelLowering.h
+++ b/contrib/llvm/lib/Target/SystemZ/SystemZISelLowering.h
@@ -57,6 +57,8 @@ namespace llvm {
public:
explicit SystemZTargetLowering(SystemZTargetMachine &TM);
+ virtual MVT getShiftAmountTy(EVT LHSTy) const { return MVT::i64; }
+
/// LowerOperation - Provide custom lowering hooks for some operations.
virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const;
diff --git a/contrib/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp b/contrib/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
index 1cac07a..8fe549b 100644
--- a/contrib/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
+++ b/contrib/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
@@ -775,6 +775,19 @@ ParseInstruction(StringRef Name, SMLoc NameLoc,
delete &Op;
}
}
+ // Same hack for "in[bwl]? (%dx), %al" -> "inb %dx, %al".
+ if ((Name == "inb" || Name == "inw" || Name == "inl" || Name == "in") &&
+ Operands.size() == 3) {
+ X86Operand &Op = *(X86Operand*)Operands.begin()[1];
+ if (Op.isMem() && Op.Mem.SegReg == 0 &&
+ isa<MCConstantExpr>(Op.Mem.Disp) &&
+ cast<MCConstantExpr>(Op.Mem.Disp)->getValue() == 0 &&
+ Op.Mem.BaseReg == MatchRegisterName("dx") && Op.Mem.IndexReg == 0) {
+ SMLoc Loc = Op.getEndLoc();
+ Operands.begin()[1] = X86Operand::CreateReg(Op.Mem.BaseReg, Loc, Loc);
+ delete &Op;
+ }
+ }
// FIXME: Hack to handle recognize s{hr,ar,hl} $1, <op>. Canonicalize to
// "shift <op>".
diff --git a/contrib/llvm/lib/Target/X86/Disassembler/X86Disassembler.cpp b/contrib/llvm/lib/Target/X86/Disassembler/X86Disassembler.cpp
index 691e2d7..f777756 100644
--- a/contrib/llvm/lib/Target/X86/Disassembler/X86Disassembler.cpp
+++ b/contrib/llvm/lib/Target/X86/Disassembler/X86Disassembler.cpp
@@ -168,16 +168,16 @@ static void translateImmediate(MCInst &mcInst, uint64_t immediate,
switch (insn.displacementSize) {
default:
break;
- case 8:
+ case 1:
type = TYPE_MOFFS8;
break;
- case 16:
+ case 2:
type = TYPE_MOFFS16;
break;
- case 32:
+ case 4:
type = TYPE_MOFFS32;
break;
- case 64:
+ case 8:
type = TYPE_MOFFS64;
break;
}
diff --git a/contrib/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h b/contrib/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h
index 4f4fbcd..d0dc8b5 100644
--- a/contrib/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h
+++ b/contrib/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h
@@ -399,7 +399,7 @@ struct InternalInstruction {
/* The segment override type */
SegmentOverride segmentOverride;
- /* Sizes of various critical pieces of data */
+ /* Sizes of various critical pieces of data, in bytes */
uint8_t registerSize;
uint8_t addressSize;
uint8_t displacementSize;
diff --git a/contrib/llvm/lib/Target/X86/X86FastISel.cpp b/contrib/llvm/lib/Target/X86/X86FastISel.cpp
index 9d42ac2..6fa9284 100644
--- a/contrib/llvm/lib/Target/X86/X86FastISel.cpp
+++ b/contrib/llvm/lib/Target/X86/X86FastISel.cpp
@@ -597,9 +597,13 @@ bool X86FastISel::X86SelectCallAddress(const Value *V, X86AddressMode &AM) {
(AM.Base.Reg != 0 || AM.IndexReg != 0))
return false;
- // Can't handle TLS or DLLImport.
+ // Can't handle DLLImport.
+ if (GV->hasDLLImportLinkage())
+ return false;
+
+ // Can't handle TLS.
if (const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV))
- if (GVar->isThreadLocal() || GVar->hasDLLImportLinkage())
+ if (GVar->isThreadLocal())
return false;
// Okay, we've committed to selecting this global. Set up the basic address.
diff --git a/contrib/llvm/lib/Target/X86/X86ISelLowering.cpp b/contrib/llvm/lib/Target/X86/X86ISelLowering.cpp
index 27024b4..2f49dbc 100644
--- a/contrib/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/contrib/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -45,7 +45,6 @@
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/VectorExtras.h"
-#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/ErrorHandling.h"
@@ -56,10 +55,6 @@ using namespace dwarf;
STATISTIC(NumTailCalls, "Number of tail calls");
-static cl::opt<bool>
-Disable256Bit("disable-256bit", cl::Hidden,
- cl::desc("Disable use of 256-bit vectors"));
-
// Forward declarations.
static SDValue getMOVL(SelectionDAG &DAG, DebugLoc dl, EVT VT, SDValue V1,
SDValue V2);
@@ -225,7 +220,6 @@ X86TargetLowering::X86TargetLowering(X86TargetMachine &TM)
static MVT IntVTs[] = { MVT::i8, MVT::i16, MVT::i32, MVT::i64 };
// X86 is weird, it always uses i8 for shift amounts and setcc results.
- setShiftAmountType(MVT::i8);
setBooleanContents(ZeroOrOneBooleanContent);
setSchedulingPreference(Sched::RegPressure);
setStackPointerRegisterToSaveRestore(X86StackPtr);
@@ -1713,7 +1707,7 @@ X86TargetLowering::LowerFormalArguments(SDValue Chain,
else
llvm_unreachable("Unknown argument type!");
- unsigned Reg = MF.addLiveIn(VA.getLocReg(), RC, dl);
+ unsigned Reg = MF.addLiveIn(VA.getLocReg(), RC);
ArgValue = DAG.getCopyFromReg(Chain, dl, Reg, RegVT);
// If this is an 8 or 16-bit value, it is really passed promoted to 32
@@ -1845,7 +1839,7 @@ X86TargetLowering::LowerFormalArguments(SDValue Chain,
SDValue FIN = DAG.getNode(ISD::ADD, dl, getPointerTy(), RSFIN,
DAG.getIntPtrConstant(Offset));
unsigned VReg = MF.addLiveIn(GPR64ArgRegs[NumIntRegs],
- X86::GR64RegisterClass, dl);
+ X86::GR64RegisterClass);
SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i64);
SDValue Store =
DAG.getStore(Val.getValue(1), dl, Val, FIN,
@@ -1861,7 +1855,7 @@ X86TargetLowering::LowerFormalArguments(SDValue Chain,
SmallVector<SDValue, 11> SaveXMMOps;
SaveXMMOps.push_back(Chain);
- unsigned AL = MF.addLiveIn(X86::AL, X86::GR8RegisterClass, dl);
+ unsigned AL = MF.addLiveIn(X86::AL, X86::GR8RegisterClass);
SDValue ALVal = DAG.getCopyFromReg(DAG.getEntryNode(), dl, AL, MVT::i8);
SaveXMMOps.push_back(ALVal);
@@ -1872,7 +1866,7 @@ X86TargetLowering::LowerFormalArguments(SDValue Chain,
for (; NumXMMRegs != TotalNumXMMRegs; ++NumXMMRegs) {
unsigned VReg = MF.addLiveIn(XMMArgRegs64Bit[NumXMMRegs],
- X86::VR128RegisterClass, dl);
+ X86::VR128RegisterClass);
SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, MVT::v4f32);
SaveXMMOps.push_back(Val);
}
@@ -2693,6 +2687,10 @@ static bool isTargetShuffle(unsigned Opcode) {
case X86ISD::MOVSD:
case X86ISD::UNPCKLPS:
case X86ISD::UNPCKLPD:
+ case X86ISD::VUNPCKLPS:
+ case X86ISD::VUNPCKLPD:
+ case X86ISD::VUNPCKLPSY:
+ case X86ISD::VUNPCKLPDY:
case X86ISD::PUNPCKLWD:
case X86ISD::PUNPCKLBW:
case X86ISD::PUNPCKLDQ:
@@ -2760,6 +2758,10 @@ static SDValue getTargetShuffleNode(unsigned Opc, DebugLoc dl, EVT VT,
case X86ISD::MOVSD:
case X86ISD::UNPCKLPS:
case X86ISD::UNPCKLPD:
+ case X86ISD::VUNPCKLPS:
+ case X86ISD::VUNPCKLPD:
+ case X86ISD::VUNPCKLPSY:
+ case X86ISD::VUNPCKLPDY:
case X86ISD::PUNPCKLWD:
case X86ISD::PUNPCKLBW:
case X86ISD::PUNPCKLDQ:
@@ -4178,7 +4180,8 @@ static SDValue getVShift(bool isLeft, EVT VT, SDValue SrcOp,
SrcOp = DAG.getNode(ISD::BITCAST, dl, ShVT, SrcOp);
return DAG.getNode(ISD::BITCAST, dl, VT,
DAG.getNode(Opc, dl, ShVT, SrcOp,
- DAG.getConstant(NumBits, TLI.getShiftAmountTy())));
+ DAG.getConstant(NumBits,
+ TLI.getShiftAmountTy(SrcOp.getValueType()))));
}
SDValue
@@ -4327,16 +4330,15 @@ X86TargetLowering::LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) const {
// For AVX-length vectors, build the individual 128-bit pieces and
// use shuffles to put them in place.
- if (VT.getSizeInBits() > 256 &&
- Subtarget->hasAVX() &&
- !Disable256Bit &&
+ if (VT.getSizeInBits() > 256 &&
+ Subtarget->hasAVX() &&
!ISD::isBuildVectorAllZeros(Op.getNode())) {
SmallVector<SDValue, 8> V;
V.resize(NumElems);
for (unsigned i = 0; i < NumElems; ++i) {
V[i] = Op.getOperand(i);
}
-
+
EVT HVT = EVT::getVectorVT(*DAG.getContext(), ExtVT, NumElems/2);
// Build the lower subvector.
@@ -5044,7 +5046,8 @@ SDValue LowerVECTOR_SHUFFLEv16i8(ShuffleVectorSDNode *SVOp,
DAG.getIntPtrConstant(Elt1 / 2));
if ((Elt1 & 1) == 0)
InsElt = DAG.getNode(ISD::SHL, dl, MVT::i16, InsElt,
- DAG.getConstant(8, TLI.getShiftAmountTy()));
+ DAG.getConstant(8,
+ TLI.getShiftAmountTy(InsElt.getValueType())));
else if (Elt0 >= 0)
InsElt = DAG.getNode(ISD::AND, dl, MVT::i16, InsElt,
DAG.getConstant(0xFF00, MVT::i16));
@@ -5058,7 +5061,8 @@ SDValue LowerVECTOR_SHUFFLEv16i8(ShuffleVectorSDNode *SVOp,
Elt0Src, DAG.getIntPtrConstant(Elt0 / 2));
if ((Elt0 & 1) != 0)
InsElt0 = DAG.getNode(ISD::SRL, dl, MVT::i16, InsElt0,
- DAG.getConstant(8, TLI.getShiftAmountTy()));
+ DAG.getConstant(8,
+ TLI.getShiftAmountTy(InsElt0.getValueType())));
else if (Elt1 >= 0)
InsElt0 = DAG.getNode(ISD::AND, dl, MVT::i16, InsElt0,
DAG.getConstant(0x00FF, MVT::i16));
@@ -5475,7 +5479,7 @@ SDValue getMOVLP(SDValue &Op, DebugLoc &dl, SelectionDAG &DAG, bool HasSSE2) {
// Both of them can't be memory operations though.
if (MayFoldVectorLoad(V1) && MayFoldVectorLoad(V2))
CanFoldLoad = false;
-
+
if (CanFoldLoad) {
if (HasSSE2 && NumElems == 2)
return getTargetShuffleNode(X86ISD::MOVLPD, dl, VT, V1, V2, DAG);
@@ -6088,7 +6092,7 @@ X86TargetLowering::LowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const {
SDValue ScaledN2 = N2;
if (Upper)
ScaledN2 = DAG.getNode(ISD::SUB, dl, N2.getValueType(), N2,
- DAG.getConstant(NumElems /
+ DAG.getConstant(NumElems /
(VT.getSizeInBits() / 128),
N2.getValueType()));
Op = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, SubN0.getValueType(), SubN0,
@@ -9327,6 +9331,10 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const {
case X86ISD::MOVSS: return "X86ISD::MOVSS";
case X86ISD::UNPCKLPS: return "X86ISD::UNPCKLPS";
case X86ISD::UNPCKLPD: return "X86ISD::UNPCKLPD";
+ case X86ISD::VUNPCKLPS: return "X86ISD::VUNPCKLPS";
+ case X86ISD::VUNPCKLPD: return "X86ISD::VUNPCKLPD";
+ case X86ISD::VUNPCKLPSY: return "X86ISD::VUNPCKLPSY";
+ case X86ISD::VUNPCKLPDY: return "X86ISD::VUNPCKLPDY";
case X86ISD::UNPCKHPS: return "X86ISD::UNPCKHPS";
case X86ISD::UNPCKHPD: return "X86ISD::UNPCKHPD";
case X86ISD::PUNPCKLBW: return "X86ISD::PUNPCKLBW";
@@ -11984,6 +11992,10 @@ SDValue X86TargetLowering::PerformDAGCombine(SDNode *N,
case X86ISD::PUNPCKLQDQ:
case X86ISD::UNPCKLPS:
case X86ISD::UNPCKLPD:
+ case X86ISD::VUNPCKLPS:
+ case X86ISD::VUNPCKLPD:
+ case X86ISD::VUNPCKLPSY:
+ case X86ISD::VUNPCKLPDY:
case X86ISD::MOVHLPS:
case X86ISD::MOVLHPS:
case X86ISD::PSHUFD:
diff --git a/contrib/llvm/lib/Target/X86/X86ISelLowering.h b/contrib/llvm/lib/Target/X86/X86ISelLowering.h
index 419da37..6ec4a7d 100644
--- a/contrib/llvm/lib/Target/X86/X86ISelLowering.h
+++ b/contrib/llvm/lib/Target/X86/X86ISelLowering.h
@@ -159,16 +159,16 @@ namespace llvm {
/// PSHUFB - Shuffle 16 8-bit values within a vector.
PSHUFB,
-
+
/// PANDN - and with not'd value.
PANDN,
-
+
/// PSIGNB/W/D - Copy integer sign.
- PSIGNB, PSIGNW, PSIGND,
-
+ PSIGNB, PSIGNW, PSIGND,
+
/// PBLENDVB - Variable blend
PBLENDVB,
-
+
/// FMAX, FMIN - Floating point max and min.
///
FMAX, FMIN,
@@ -212,7 +212,7 @@ namespace llvm {
// ADD, SUB, SMUL, etc. - Arithmetic operations with FLAGS results.
ADD, SUB, ADC, SBB, SMUL,
INC, DEC, OR, XOR, AND,
-
+
UMUL, // LOW, HI, FLAGS = umul LHS, RHS
// MUL_IMM - X86 specific multiply by immediate.
@@ -248,6 +248,10 @@ namespace llvm {
MOVSS,
UNPCKLPS,
UNPCKLPD,
+ VUNPCKLPS,
+ VUNPCKLPD,
+ VUNPCKLPSY,
+ VUNPCKLPDY,
UNPCKHPS,
UNPCKHPD,
PUNPCKLBW,
@@ -463,6 +467,8 @@ namespace llvm {
virtual unsigned getJumpTableEncoding() const;
+ virtual MVT getShiftAmountTy(EVT LHSTy) const { return MVT::i8; }
+
virtual const MCExpr *
LowerCustomJumpTableEntry(const MachineJumpTableInfo *MJTI,
const MachineBasicBlock *MBB, unsigned uid,
diff --git a/contrib/llvm/lib/Target/X86/X86InstrFormats.td b/contrib/llvm/lib/Target/X86/X86InstrFormats.td
index 344c14c..0660072 100644
--- a/contrib/llvm/lib/Target/X86/X86InstrFormats.td
+++ b/contrib/llvm/lib/Target/X86/X86InstrFormats.td
@@ -41,6 +41,8 @@ def MRM_F8 : Format<41>;
def MRM_F9 : Format<42>;
def RawFrmImm8 : Format<43>;
def RawFrmImm16 : Format<44>;
+def MRM_D0 : Format<45>;
+def MRM_D1 : Format<46>;
// ImmType - This specifies the immediate type used by an instruction. This is
// part of the ad-hoc solution used to emit machine instruction encodings by our
diff --git a/contrib/llvm/lib/Target/X86/X86InstrInfo.cpp b/contrib/llvm/lib/Target/X86/X86InstrInfo.cpp
index ceb1b65..76a9b12 100644
--- a/contrib/llvm/lib/Target/X86/X86InstrInfo.cpp
+++ b/contrib/llvm/lib/Target/X86/X86InstrInfo.cpp
@@ -369,8 +369,6 @@ X86InstrInfo::X86InstrInfo(X86TargetMachine &tm)
{ X86::IMUL32rri8, X86::IMUL32rmi8, 0 },
{ X86::IMUL64rri32, X86::IMUL64rmi32, 0 },
{ X86::IMUL64rri8, X86::IMUL64rmi8, 0 },
- { X86::Int_CMPSDrr, X86::Int_CMPSDrm, 0 },
- { X86::Int_CMPSSrr, X86::Int_CMPSSrm, 0 },
{ X86::Int_COMISDrr, X86::Int_COMISDrm, 0 },
{ X86::Int_COMISSrr, X86::Int_COMISSrm, 0 },
{ X86::Int_CVTDQ2PDrr, X86::Int_CVTDQ2PDrm, 16 },
@@ -568,6 +566,8 @@ X86InstrInfo::X86InstrInfo(X86TargetMachine &tm)
{ X86::IMUL16rr, X86::IMUL16rm, 0 },
{ X86::IMUL32rr, X86::IMUL32rm, 0 },
{ X86::IMUL64rr, X86::IMUL64rm, 0 },
+ { X86::Int_CMPSDrr, X86::Int_CMPSDrm, 0 },
+ { X86::Int_CMPSSrr, X86::Int_CMPSSrm, 0 },
{ X86::MAXPDrr, X86::MAXPDrm, 16 },
{ X86::MAXPDrr_Int, X86::MAXPDrm_Int, 16 },
{ X86::MAXPSrr, X86::MAXPSrm, 16 },
diff --git a/contrib/llvm/lib/Target/X86/X86InstrInfo.h b/contrib/llvm/lib/Target/X86/X86InstrInfo.h
index 1d44207..fcb5a25 100644
--- a/contrib/llvm/lib/Target/X86/X86InstrInfo.h
+++ b/contrib/llvm/lib/Target/X86/X86InstrInfo.h
@@ -311,6 +311,8 @@ namespace X86II {
MRM_F0 = 40,
MRM_F8 = 41,
MRM_F9 = 42,
+ MRM_D0 = 45,
+ MRM_D1 = 46,
/// RawFrmImm8 - This is used for the ENTER instruction, which has two
/// immediates, the first of which is a 16-bit immediate (specified by
@@ -577,6 +579,8 @@ namespace X86II {
case X86II::MRM_F0:
case X86II::MRM_F8:
case X86II::MRM_F9:
+ case X86II::MRM_D0:
+ case X86II::MRM_D1:
return -1;
}
}
diff --git a/contrib/llvm/lib/Target/X86/X86InstrInfo.td b/contrib/llvm/lib/Target/X86/X86InstrInfo.td
index 87dc4be..f832a7c 100644
--- a/contrib/llvm/lib/Target/X86/X86InstrInfo.td
+++ b/contrib/llvm/lib/Target/X86/X86InstrInfo.td
@@ -1296,6 +1296,9 @@ def : MnemonicAlias<"lret", "lretl">;
def : MnemonicAlias<"leavel", "leave">, Requires<[In32BitMode]>;
def : MnemonicAlias<"leaveq", "leave">, Requires<[In64BitMode]>;
+def : MnemonicAlias<"loopz", "loope">;
+def : MnemonicAlias<"loopnz", "loopne">;
+
def : MnemonicAlias<"pop", "popl">, Requires<[In32BitMode]>;
def : MnemonicAlias<"pop", "popq">, Requires<[In64BitMode]>;
def : MnemonicAlias<"popf", "popfl">, Requires<[In32BitMode]>;
diff --git a/contrib/llvm/lib/Target/X86/X86InstrSystem.td b/contrib/llvm/lib/Target/X86/X86InstrSystem.td
index 1a58ba0..6a24d14 100644
--- a/contrib/llvm/lib/Target/X86/X86InstrSystem.td
+++ b/contrib/llvm/lib/Target/X86/X86InstrSystem.td
@@ -388,3 +388,8 @@ def CPUID : I<0xA2, RawFrm, (outs), (ins), "cpuid", []>, TB;
def INVD : I<0x08, RawFrm, (outs), (ins), "invd", []>, TB;
def WBINVD : I<0x09, RawFrm, (outs), (ins), "wbinvd", []>, TB;
+let Defs = [RDX, RAX], Uses = [RCX] in
+ def XGETBV : I<0x01, MRM_D0, (outs), (ins), "xgetbv", []>, TB;
+
+let Uses = [RDX, RAX, RCX] in
+ def XSETBV : I<0x01, MRM_D1, (outs), (ins), "xsetbv", []>, TB;
diff --git a/contrib/llvm/lib/Target/X86/X86MCCodeEmitter.cpp b/contrib/llvm/lib/Target/X86/X86MCCodeEmitter.cpp
index e6dc74e..0e3b571 100644
--- a/contrib/llvm/lib/Target/X86/X86MCCodeEmitter.cpp
+++ b/contrib/llvm/lib/Target/X86/X86MCCodeEmitter.cpp
@@ -979,6 +979,14 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS,
EmitByte(BaseOpcode, CurByte, OS);
EmitByte(0xF9, CurByte, OS);
break;
+ case X86II::MRM_D0:
+ EmitByte(BaseOpcode, CurByte, OS);
+ EmitByte(0xD0, CurByte, OS);
+ break;
+ case X86II::MRM_D1:
+ EmitByte(BaseOpcode, CurByte, OS);
+ EmitByte(0xD1, CurByte, OS);
+ break;
}
// If there is a remaining operand, it must be a trailing immediate. Emit it
diff --git a/contrib/llvm/lib/Target/X86/X86Subtarget.cpp b/contrib/llvm/lib/Target/X86/X86Subtarget.cpp
index de76856..1ee7312 100644
--- a/contrib/llvm/lib/Target/X86/X86Subtarget.cpp
+++ b/contrib/llvm/lib/Target/X86/X86Subtarget.cpp
@@ -342,9 +342,10 @@ X86Subtarget::X86Subtarget(const std::string &TT, const std::string &FS,
assert((!Is64Bit || HasX86_64) &&
"64-bit code requested on a subtarget that doesn't support it!");
- // Stack alignment is 16 bytes on Darwin and Linux (both 32 and 64 bit) and
- // for all 64-bit targets.
- if (isTargetDarwin() || isTargetLinux() || Is64Bit)
+ // Stack alignment is 16 bytes on Darwin, FreeBSD, Linux and Solaris (both
+ // 32 and 64 bit) and for all 64-bit targets.
+ if (isTargetDarwin() || isTargetFreeBSD() || isTargetLinux() ||
+ isTargetSolaris() || Is64Bit)
stackAlignment = 16;
if (StackAlignment)
diff --git a/contrib/llvm/lib/Target/X86/X86Subtarget.h b/contrib/llvm/lib/Target/X86/X86Subtarget.h
index 8a119b4..0a62a02 100644
--- a/contrib/llvm/lib/Target/X86/X86Subtarget.h
+++ b/contrib/llvm/lib/Target/X86/X86Subtarget.h
@@ -166,6 +166,8 @@ public:
bool hasVectorUAMem() const { return HasVectorUAMem; }
bool isTargetDarwin() const { return TargetTriple.getOS() == Triple::Darwin; }
+ bool isTargetFreeBSD() const { return TargetTriple.getOS() == Triple::FreeBSD; }
+ bool isTargetSolaris() const { return TargetTriple.getOS() == Triple::Solaris; }
// ELF is a reasonably sane default and the only other X86 targets we
// support are Darwin and Windows. Just use "not those".
diff --git a/contrib/llvm/lib/Target/XCore/XCoreISelLowering.cpp b/contrib/llvm/lib/Target/XCore/XCoreISelLowering.cpp
index 828d6f9..4817787 100644
--- a/contrib/llvm/lib/Target/XCore/XCoreISelLowering.cpp
+++ b/contrib/llvm/lib/Target/XCore/XCoreISelLowering.cpp
@@ -42,9 +42,9 @@
using namespace llvm;
const char *XCoreTargetLowering::
-getTargetNodeName(unsigned Opcode) const
+getTargetNodeName(unsigned Opcode) const
{
- switch (Opcode)
+ switch (Opcode)
{
case XCoreISD::BL : return "XCoreISD::BL";
case XCoreISD::PCRelativeWrapper : return "XCoreISD::PCRelativeWrapper";
@@ -77,7 +77,6 @@ XCoreTargetLowering::XCoreTargetLowering(XCoreTargetMachine &XTM)
// Division is expensive
setIntDivIsCheap(false);
- setShiftAmountType(MVT::i32);
setStackPointerRegisterToSaveRestore(XCore::SP);
setSchedulingPreference(Sched::RegPressure);
@@ -95,7 +94,7 @@ XCoreTargetLowering::XCoreTargetLowering(XCoreTargetMachine &XTM)
// Stop the combiner recombining select and set_cc
setOperationAction(ISD::SELECT_CC, MVT::Other, Expand);
-
+
// 64bit
setOperationAction(ISD::ADD, MVT::i64, Custom);
setOperationAction(ISD::SUB, MVT::i64, Custom);
@@ -106,14 +105,14 @@ XCoreTargetLowering::XCoreTargetLowering(XCoreTargetMachine &XTM)
setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand);
setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand);
setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand);
-
+
// Bit Manipulation
setOperationAction(ISD::CTPOP, MVT::i32, Expand);
setOperationAction(ISD::ROTL , MVT::i32, Expand);
setOperationAction(ISD::ROTR , MVT::i32, Expand);
-
+
setOperationAction(ISD::TRAP, MVT::Other, Legal);
-
+
// Jump tables.
setOperationAction(ISD::BR_JT, MVT::Other, Custom);
@@ -122,7 +121,7 @@ XCoreTargetLowering::XCoreTargetLowering(XCoreTargetMachine &XTM)
// Thread Local Storage
setOperationAction(ISD::GlobalTLSAddress, MVT::i32, Custom);
-
+
// Conversion of i64 -> double produces constantpool nodes
setOperationAction(ISD::ConstantPool, MVT::i32, Custom);
@@ -143,7 +142,7 @@ XCoreTargetLowering::XCoreTargetLowering(XCoreTargetMachine &XTM)
setOperationAction(ISD::VACOPY, MVT::Other, Expand);
setOperationAction(ISD::VAARG, MVT::Other, Custom);
setOperationAction(ISD::VASTART, MVT::Other, Custom);
-
+
// Dynamic stack
setOperationAction(ISD::STACKSAVE, MVT::Other, Expand);
setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand);
@@ -163,7 +162,7 @@ XCoreTargetLowering::XCoreTargetLowering(XCoreTargetMachine &XTM)
SDValue XCoreTargetLowering::
LowerOperation(SDValue Op, SelectionDAG &DAG) const {
- switch (Op.getOpcode())
+ switch (Op.getOpcode())
{
case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG);
case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG);
@@ -414,7 +413,7 @@ LowerLOAD(SDValue Op, SelectionDAG &DAG) const {
SDValue Chain = LD->getChain();
SDValue BasePtr = LD->getBasePtr();
DebugLoc DL = Op.getDebugLoc();
-
+
SDValue Base;
int64_t Offset;
if (!LD->isVolatile() &&
@@ -437,10 +436,10 @@ LowerLOAD(SDValue Op, SelectionDAG &DAG) const {
SDValue HighOffset = DAG.getConstant((Offset & ~0x3) + 4, MVT::i32);
SDValue LowShift = DAG.getConstant((Offset & 0x3) * 8, MVT::i32);
SDValue HighShift = DAG.getConstant(32 - (Offset & 0x3) * 8, MVT::i32);
-
+
SDValue LowAddr = DAG.getNode(ISD::ADD, DL, MVT::i32, Base, LowOffset);
SDValue HighAddr = DAG.getNode(ISD::ADD, DL, MVT::i32, Base, HighOffset);
-
+
SDValue Low = DAG.getLoad(getPointerTy(), DL, Chain,
LowAddr, MachinePointerInfo(), false, false, 0);
SDValue High = DAG.getLoad(getPointerTy(), DL, Chain,
@@ -453,7 +452,7 @@ LowerLOAD(SDValue Op, SelectionDAG &DAG) const {
SDValue Ops[] = { Result, Chain };
return DAG.getMergeValues(Ops, 2, DL);
}
-
+
if (LD->getAlignment() == 2) {
SDValue Low = DAG.getExtLoad(ISD::ZEXTLOAD, DL, MVT::i32, Chain,
BasePtr, LD->getPointerInfo(), MVT::i16,
@@ -473,16 +472,16 @@ LowerLOAD(SDValue Op, SelectionDAG &DAG) const {
SDValue Ops[] = { Result, Chain };
return DAG.getMergeValues(Ops, 2, DL);
}
-
+
// Lower to a call to __misaligned_load(BasePtr).
const Type *IntPtrTy = getTargetData()->getIntPtrType(*DAG.getContext());
TargetLowering::ArgListTy Args;
TargetLowering::ArgListEntry Entry;
-
+
Entry.Ty = IntPtrTy;
Entry.Node = BasePtr;
Args.push_back(Entry);
-
+
std::pair<SDValue, SDValue> CallResult =
LowerCallTo(Chain, IntPtrTy, false, false,
false, false, 0, CallingConv::C, false,
@@ -515,7 +514,7 @@ LowerSTORE(SDValue Op, SelectionDAG &DAG) const
SDValue BasePtr = ST->getBasePtr();
SDValue Value = ST->getValue();
DebugLoc dl = Op.getDebugLoc();
-
+
if (ST->getAlignment() == 2) {
SDValue Low = Value;
SDValue High = DAG.getNode(ISD::SRL, dl, MVT::i32, Value,
@@ -532,19 +531,19 @@ LowerSTORE(SDValue Op, SelectionDAG &DAG) const
ST->isNonTemporal(), 2);
return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, StoreLow, StoreHigh);
}
-
+
// Lower to a call to __misaligned_store(BasePtr, Value).
const Type *IntPtrTy = getTargetData()->getIntPtrType(*DAG.getContext());
TargetLowering::ArgListTy Args;
TargetLowering::ArgListEntry Entry;
-
+
Entry.Ty = IntPtrTy;
Entry.Node = BasePtr;
Args.push_back(Entry);
-
+
Entry.Node = Value;
Args.push_back(Entry);
-
+
std::pair<SDValue, SDValue> CallResult =
LowerCallTo(Chain, Type::getVoidTy(*DAG.getContext()), false, false,
false, false, 0, CallingConv::C, false,
@@ -722,7 +721,7 @@ ExpandADDSUB(SDNode *N, SelectionDAG &DAG) const
}
DebugLoc dl = N->getDebugLoc();
-
+
// Extract components
SDValue LHSL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
N->getOperand(0), DAG.getConstant(0, MVT::i32));
@@ -732,7 +731,7 @@ ExpandADDSUB(SDNode *N, SelectionDAG &DAG) const
N->getOperand(1), DAG.getConstant(0, MVT::i32));
SDValue RHSH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
N->getOperand(1), DAG.getConstant(1, MVT::i32));
-
+
// Expand
unsigned Opcode = (N->getOpcode() == ISD::ADD) ? XCoreISD::LADD :
XCoreISD::LSUB;
@@ -740,7 +739,7 @@ ExpandADDSUB(SDNode *N, SelectionDAG &DAG) const
SDValue Carry = DAG.getNode(Opcode, dl, DAG.getVTList(MVT::i32, MVT::i32),
LHSL, RHSL, Zero);
SDValue Lo(Carry.getNode(), 1);
-
+
SDValue Ignored = DAG.getNode(Opcode, dl, DAG.getVTList(MVT::i32, MVT::i32),
LHSH, RHSH, Carry);
SDValue Hi(Ignored.getNode(), 1);
@@ -761,8 +760,8 @@ LowerVAARG(SDValue Op, SelectionDAG &DAG) const
Node->getOperand(1), MachinePointerInfo(V),
false, false, 0);
// Increment the pointer, VAList, to the next vararg
- SDValue Tmp3 = DAG.getNode(ISD::ADD, dl, getPointerTy(), VAList,
- DAG.getConstant(VT.getSizeInBits(),
+ SDValue Tmp3 = DAG.getNode(ISD::ADD, dl, getPointerTy(), VAList,
+ DAG.getConstant(VT.getSizeInBits(),
getPointerTy()));
// Store the incremented VAList to the legalized pointer
Tmp3 = DAG.getStore(VAList.getValue(1), dl, Tmp3, Node->getOperand(1),
@@ -781,20 +780,20 @@ LowerVASTART(SDValue Op, SelectionDAG &DAG) const
MachineFunction &MF = DAG.getMachineFunction();
XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>();
SDValue Addr = DAG.getFrameIndex(XFI->getVarArgsFrameIndex(), MVT::i32);
- return DAG.getStore(Op.getOperand(0), dl, Addr, Op.getOperand(1),
+ return DAG.getStore(Op.getOperand(0), dl, Addr, Op.getOperand(1),
MachinePointerInfo(), false, false, 0);
}
SDValue XCoreTargetLowering::LowerFRAMEADDR(SDValue Op,
SelectionDAG &DAG) const {
DebugLoc dl = Op.getDebugLoc();
- // Depths > 0 not supported yet!
+ // Depths > 0 not supported yet!
if (cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue() > 0)
return SDValue();
-
+
MachineFunction &MF = DAG.getMachineFunction();
const TargetRegisterInfo *RegInfo = getTargetMachine().getRegisterInfo();
- return DAG.getCopyFromReg(DAG.getEntryNode(), dl,
+ return DAG.getCopyFromReg(DAG.getEntryNode(), dl,
RegInfo->getFrameRegister(MF), MVT::i32);
}
@@ -919,7 +918,7 @@ XCoreTargetLowering::LowerCCCCallTo(SDValue Chain, SDValue Callee,
// Get a count of how many bytes are to be pushed on the stack.
unsigned NumBytes = CCInfo.getNextStackOffset();
- Chain = DAG.getCALLSEQ_START(Chain,DAG.getConstant(NumBytes,
+ Chain = DAG.getCALLSEQ_START(Chain,DAG.getConstant(NumBytes,
getPointerTy(), true));
SmallVector<std::pair<unsigned, SDValue>, 4> RegsToPass;
@@ -944,8 +943,8 @@ XCoreTargetLowering::LowerCCCCallTo(SDValue Chain, SDValue Callee,
Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Arg);
break;
}
-
- // Arguments that can be passed on register must be kept at
+
+ // Arguments that can be passed on register must be kept at
// RegsToPass vector
if (VA.isRegLoc()) {
RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
@@ -954,7 +953,7 @@ XCoreTargetLowering::LowerCCCCallTo(SDValue Chain, SDValue Callee,
int Offset = VA.getLocMemOffset();
- MemOpChains.push_back(DAG.getNode(XCoreISD::STWSP, dl, MVT::Other,
+ MemOpChains.push_back(DAG.getNode(XCoreISD::STWSP, dl, MVT::Other,
Chain, Arg,
DAG.getConstant(Offset/4, MVT::i32)));
}
@@ -963,16 +962,16 @@ XCoreTargetLowering::LowerCCCCallTo(SDValue Chain, SDValue Callee,
// Transform all store nodes into one single node because
// all store nodes are independent of each other.
if (!MemOpChains.empty())
- Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
+ Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
&MemOpChains[0], MemOpChains.size());
- // Build a sequence of copy-to-reg nodes chained together with token
+ // Build a sequence of copy-to-reg nodes chained together with token
// chain and flag operands which copy the outgoing args into registers.
// The InFlag in necessary since all emited instructions must be
// stuck together.
SDValue InFlag;
for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
- Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first,
+ Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first,
RegsToPass[i].second, InFlag);
InFlag = Chain.getValue(1);
}
@@ -986,7 +985,7 @@ XCoreTargetLowering::LowerCCCCallTo(SDValue Chain, SDValue Callee,
Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i32);
// XCoreBranchLink = #chain, #target_address, #opt_in_flags...
- // = Chain, Callee, Reg#1, Reg#2, ...
+ // = Chain, Callee, Reg#1, Reg#2, ...
//
// Returns a chain & a flag for retval copy to use.
SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
@@ -994,7 +993,7 @@ XCoreTargetLowering::LowerCCCCallTo(SDValue Chain, SDValue Callee,
Ops.push_back(Chain);
Ops.push_back(Callee);
- // Add argument registers to the end of the list so that they are
+ // Add argument registers to the end of the list so that they are
// known live into the call.
for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
Ops.push_back(DAG.getRegister(RegsToPass[i].first,
@@ -1098,11 +1097,11 @@ XCoreTargetLowering::LowerCCCArguments(SDValue Chain,
unsigned StackSlotSize = XCoreFrameLowering::stackSlotSize();
unsigned LRSaveSize = StackSlotSize;
-
+
for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
CCValAssign &VA = ArgLocs[i];
-
+
if (VA.isRegLoc()) {
// Arguments passed in registers
EVT RegVT = VA.getLocVT();
@@ -1139,12 +1138,12 @@ XCoreTargetLowering::LowerCCCArguments(SDValue Chain,
// Create the SelectionDAG nodes corresponding to a load
//from this parameter
SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
- InVals.push_back(DAG.getLoad(VA.getLocVT(), dl, Chain, FIN,
+ InVals.push_back(DAG.getLoad(VA.getLocVT(), dl, Chain, FIN,
MachinePointerInfo::getFixedStack(FI),
false, false, 0));
}
}
-
+
if (isVarArg) {
/* Argument registers */
static const unsigned ArgRegs[] = {
@@ -1186,7 +1185,7 @@ XCoreTargetLowering::LowerCCCArguments(SDValue Chain,
true));
}
}
-
+
return Chain;
}
@@ -1222,7 +1221,7 @@ XCoreTargetLowering::LowerReturn(SDValue Chain,
// Analize return values.
CCInfo.AnalyzeReturn(Outs, RetCC_XCore);
- // If this is the first return lowered for this function, add
+ // If this is the first return lowered for this function, add
// the regs to the liveout set for the function.
if (DAG.getMachineFunction().getRegInfo().liveout_empty()) {
for (unsigned i = 0; i != RVLocs.size(); ++i)
@@ -1237,7 +1236,7 @@ XCoreTargetLowering::LowerReturn(SDValue Chain,
CCValAssign &VA = RVLocs[i];
assert(VA.isRegLoc() && "Can only return in registers!");
- Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(),
+ Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(),
OutVals[i], Flag);
// guarantee that all emitted copies are
@@ -1265,7 +1264,7 @@ XCoreTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
DebugLoc dl = MI->getDebugLoc();
assert((MI->getOpcode() == XCore::SELECT_CC) &&
"Unexpected instr type to insert");
-
+
// To "insert" a SELECT_CC instruction, we actually have to insert the diamond
// control-flow pattern. The incoming instruction knows the destination vreg
// to set, the condition code register to branch on, the true/false values to
@@ -1273,7 +1272,7 @@ XCoreTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
const BasicBlock *LLVM_BB = BB->getBasicBlock();
MachineFunction::iterator It = BB;
++It;
-
+
// thisMBB:
// ...
// TrueVal = ...
@@ -1296,7 +1295,7 @@ XCoreTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
// Next, add the true and fallthrough blocks as its successors.
BB->addSuccessor(copy0MBB);
BB->addSuccessor(sinkMBB);
-
+
BuildMI(BB, dl, TII.get(XCore::BRFT_lru6))
.addReg(MI->getOperand(1).getReg()).addMBB(sinkMBB);
@@ -1304,10 +1303,10 @@ XCoreTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
// %FalseValue = ...
// # fallthrough to sinkMBB
BB = copy0MBB;
-
+
// Update machine-CFG edges
BB->addSuccessor(sinkMBB);
-
+
// sinkMBB:
// %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ]
// ...
@@ -1316,7 +1315,7 @@ XCoreTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
TII.get(XCore::PHI), MI->getOperand(0).getReg())
.addReg(MI->getOperand(3).getReg()).addMBB(copy0MBB)
.addReg(MI->getOperand(2).getReg()).addMBB(thisMBB);
-
+
MI->eraseFromParent(); // The pseudo instruction is gone now.
return BB;
}
@@ -1354,7 +1353,7 @@ SDValue XCoreTargetLowering::PerformDAGCombine(SDNode *N,
// fold (ladd x, 0, y) -> 0, add x, y iff carry is unused and y has only the
// low bit set
- if (N1C && N1C->isNullValue() && N->hasNUsesOfValue(0, 0)) {
+ if (N1C && N1C->isNullValue() && N->hasNUsesOfValue(0, 0)) {
APInt KnownZero, KnownOne;
APInt Mask = APInt::getHighBitsSet(VT.getSizeInBits(),
VT.getSizeInBits() - 1);
@@ -1377,7 +1376,7 @@ SDValue XCoreTargetLowering::PerformDAGCombine(SDNode *N,
EVT VT = N0.getValueType();
// fold (lsub 0, 0, x) -> x, -x iff x has only the low bit set
- if (N0C && N0C->isNullValue() && N1C && N1C->isNullValue()) {
+ if (N0C && N0C->isNullValue() && N1C && N1C->isNullValue()) {
APInt KnownZero, KnownOne;
APInt Mask = APInt::getHighBitsSet(VT.getSizeInBits(),
VT.getSizeInBits() - 1);
@@ -1393,7 +1392,7 @@ SDValue XCoreTargetLowering::PerformDAGCombine(SDNode *N,
// fold (lsub x, 0, y) -> 0, sub x, y iff borrow is unused and y has only the
// low bit set
- if (N1C && N1C->isNullValue() && N->hasNUsesOfValue(0, 0)) {
+ if (N1C && N1C->isNullValue() && N->hasNUsesOfValue(0, 0)) {
APInt KnownZero, KnownOne;
APInt Mask = APInt::getHighBitsSet(VT.getSizeInBits(),
VT.getSizeInBits() - 1);
@@ -1557,7 +1556,7 @@ static inline bool isImmUs4(int64_t val)
/// isLegalAddressingMode - Return true if the addressing mode represented
/// by AM is legal for this target, for a load/store of the specified type.
bool
-XCoreTargetLowering::isLegalAddressingMode(const AddrMode &AM,
+XCoreTargetLowering::isLegalAddressingMode(const AddrMode &AM,
const Type *Ty) const {
if (Ty->getTypeID() == Type::VoidTyID)
return AM.Scale == 0 && isImmUs(AM.BaseOffs) && isImmUs4(AM.BaseOffs);
@@ -1568,7 +1567,7 @@ XCoreTargetLowering::isLegalAddressingMode(const AddrMode &AM,
return Size >= 4 && !AM.HasBaseReg && AM.Scale == 0 &&
AM.BaseOffs%4 == 0;
}
-
+
switch (Size) {
case 1:
// reg + imm
@@ -1593,7 +1592,7 @@ XCoreTargetLowering::isLegalAddressingMode(const AddrMode &AM,
// reg + reg<<2
return AM.Scale == 4 && AM.BaseOffs == 0;
}
-
+
return false;
}
@@ -1603,7 +1602,7 @@ XCoreTargetLowering::isLegalAddressingMode(const AddrMode &AM,
std::vector<unsigned> XCoreTargetLowering::
getRegClassForInlineAsmConstraint(const std::string &Constraint,
- EVT VT) const
+ EVT VT) const
{
if (Constraint.size() != 1)
return std::vector<unsigned>();
@@ -1611,9 +1610,9 @@ getRegClassForInlineAsmConstraint(const std::string &Constraint,
switch (Constraint[0]) {
default : break;
case 'r':
- return make_vector<unsigned>(XCore::R0, XCore::R1, XCore::R2,
- XCore::R3, XCore::R4, XCore::R5,
- XCore::R6, XCore::R7, XCore::R8,
+ return make_vector<unsigned>(XCore::R0, XCore::R1, XCore::R2,
+ XCore::R3, XCore::R4, XCore::R5,
+ XCore::R6, XCore::R7, XCore::R8,
XCore::R9, XCore::R10, XCore::R11, 0);
break;
}
diff --git a/contrib/llvm/lib/Target/XCore/XCoreISelLowering.h b/contrib/llvm/lib/Target/XCore/XCoreISelLowering.h
index 7e5dd2e..bb3f2cc 100644
--- a/contrib/llvm/lib/Target/XCore/XCoreISelLowering.h
+++ b/contrib/llvm/lib/Target/XCore/XCoreISelLowering.h
@@ -20,11 +20,11 @@
#include "XCore.h"
namespace llvm {
-
+
// Forward delcarations
class XCoreSubtarget;
class XCoreTargetMachine;
-
+
namespace XCoreISD {
enum NodeType {
// Start the numbering where the builtin ops and target ops leave off.
@@ -38,16 +38,16 @@ namespace llvm {
// dp relative address
DPRelativeWrapper,
-
+
// cp relative address
CPRelativeWrapper,
-
+
// Store word to stack
STWSP,
// Corresponds to retsp instruction
RETSP,
-
+
// Corresponds to LADD instruction
LADD,
@@ -74,13 +74,14 @@ namespace llvm {
//===--------------------------------------------------------------------===//
// TargetLowering Implementation
//===--------------------------------------------------------------------===//
- class XCoreTargetLowering : public TargetLowering
+ class XCoreTargetLowering : public TargetLowering
{
public:
explicit XCoreTargetLowering(XCoreTargetMachine &TM);
virtual unsigned getJumpTableEncoding() const;
+ virtual MVT getShiftAmountTy(EVT LHSTy) const { return MVT::i32; }
/// LowerOperation - Provide custom lowering hooks for some operations.
virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const;
@@ -91,10 +92,10 @@ namespace llvm {
virtual void ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue>&Results,
SelectionDAG &DAG) const;
- /// getTargetNodeName - This method returns the name of a target specific
+ /// getTargetNodeName - This method returns the name of a target specific
// DAG node.
virtual const char *getTargetNodeName(unsigned Opcode) const;
-
+
virtual MachineBasicBlock *
EmitInstrWithCustomInserter(MachineInstr *MI,
MachineBasicBlock *MBB) const;
@@ -108,7 +109,7 @@ namespace llvm {
private:
const XCoreTargetMachine &TM;
const XCoreSubtarget &Subtarget;
-
+
// Lower Operand helpers
SDValue LowerCCCArguments(SDValue Chain,
CallingConv::ID CallConv,
@@ -148,12 +149,12 @@ namespace llvm {
SDValue LowerSMUL_LOHI(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerTRAMPOLINE(SDValue Op, SelectionDAG &DAG) const;
-
+
// Inline asm support
std::vector<unsigned>
getRegClassForInlineAsmConstraint(const std::string &Constraint,
EVT VT) const;
-
+
// Expand specifics
SDValue TryExpandADDWithMul(SDNode *Op, SelectionDAG &DAG) const;
SDValue ExpandADDSUB(SDNode *Op, SelectionDAG &DAG) const;
diff --git a/contrib/llvm/lib/Target/XCore/XCoreInstrInfo.td b/contrib/llvm/lib/Target/XCore/XCoreInstrInfo.td
index 38cc734..ecdd4cb 100644
--- a/contrib/llvm/lib/Target/XCore/XCoreInstrInfo.td
+++ b/contrib/llvm/lib/Target/XCore/XCoreInstrInfo.td
@@ -727,7 +727,7 @@ def NEG : _F2R<(outs GRRegs:$dst), (ins GRRegs:$b),
"neg $dst, $b",
[(set GRRegs:$dst, (ineg GRRegs:$b))]>;
-// TODO setd, eet, eef, getts, setpt, outshr, inshr, testwct, tinitpc, tinitdp,
+// TODO setd, eet, eef, testwct, tinitpc, tinitdp,
// tinitsp, tinitcp, tsetmr, sext (reg), zext (reg)
let Constraints = "$src1 = $dst" in {
let neverHasSideEffects = 1 in
@@ -758,6 +758,14 @@ def GETR_rus : _FRUS<(outs GRRegs:$dst), (ins i32imm:$type),
"getr $dst, $type",
[(set GRRegs:$dst, (int_xcore_getr immUs:$type))]>;
+def GETTS_2r : _F2R<(outs GRRegs:$dst), (ins GRRegs:$r),
+ "getts $dst, res[$r]",
+ [(set GRRegs:$dst, (int_xcore_getts GRRegs:$r))]>;
+
+def SETPT_2r : _F2R<(outs), (ins GRRegs:$r, GRRegs:$val),
+ "setpt res[$r], $val",
+ [(int_xcore_setpt GRRegs:$r, GRRegs:$val)]>;
+
def OUTCT_2r : _F2R<(outs), (ins GRRegs:$r, GRRegs:$val),
"outct res[$r], $val",
[(int_xcore_outct GRRegs:$r, GRRegs:$val)]>;
@@ -774,6 +782,11 @@ def OUT_2r : _F2R<(outs), (ins GRRegs:$r, GRRegs:$val),
"out res[$r], $val",
[(int_xcore_out GRRegs:$r, GRRegs:$val)]>;
+let Constraints = "$src = $dst" in
+def OUTSHR_2r : _F2R<(outs GRRegs:$dst), (ins GRRegs:$r, GRRegs:$src),
+ "outshr res[$r], $src",
+ [(set GRRegs:$dst, (int_xcore_outshr GRRegs:$r, GRRegs:$src))]>;
+
def INCT_2r : _F2R<(outs GRRegs:$dst), (ins GRRegs:$r),
"inct $dst, res[$r]",
[(set GRRegs:$dst, (int_xcore_inct GRRegs:$r))]>;
@@ -786,6 +799,11 @@ def IN_2r : _F2R<(outs GRRegs:$dst), (ins GRRegs:$r),
"in $dst, res[$r]",
[(set GRRegs:$dst, (int_xcore_in GRRegs:$r))]>;
+let Constraints = "$src = $dst" in
+def INSHR_2r : _F2R<(outs GRRegs:$dst), (ins GRRegs:$r, GRRegs:$src),
+ "inshr $dst, res[$r]",
+ [(set GRRegs:$dst, (int_xcore_inshr GRRegs:$r, GRRegs:$src))]>;
+
def CHKCT_2r : _F2R<(outs), (ins GRRegs:$r, GRRegs:$val),
"chkct res[$r], $val",
[(int_xcore_chkct GRRegs:$r, GRRegs:$val)]>;
@@ -799,7 +817,7 @@ def SETD_2r : _F2R<(outs), (ins GRRegs:$r, GRRegs:$val),
[(int_xcore_setd GRRegs:$r, GRRegs:$val)]>;
// Two operand long
-// TODO settw, setclk, setrdy, setpsc, endin, peek,
+// TODO setclk, setrdy, setpsc, endin, peek,
// getd, testlcl, tinitlr, getps, setps
def BITREV_l2r : _FL2R<(outs GRRegs:$dst), (ins GRRegs:$src),
"bitrev $dst, $src",
@@ -813,13 +831,17 @@ def CLZ_l2r : _FL2R<(outs GRRegs:$dst), (ins GRRegs:$src),
"clz $dst, $src",
[(set GRRegs:$dst, (ctlz GRRegs:$src))]>;
-def SETC_l2r : _FRU6<(outs), (ins GRRegs:$r, GRRegs:$val),
+def SETC_l2r : _FL2R<(outs), (ins GRRegs:$r, GRRegs:$val),
"setc res[$r], $val",
[(int_xcore_setc GRRegs:$r, GRRegs:$val)]>;
+def SETTW_l2r : _FL2R<(outs), (ins GRRegs:$r, GRRegs:$val),
+ "settw res[$r], $val",
+ [(int_xcore_settw GRRegs:$r, GRRegs:$val)]>;
+
// One operand short
-// TODO edu, eeu, waitet, waitef, tstart, msync, mjoin, syncr, clrtp
-// setdp, setcp, setv, setev, kcall
+// TODO edu, eeu, waitet, waitef, tstart, msync, mjoin, clrtp
+// setdp, setcp, setev, kcall
// dgetreg
let isBranch=1, isIndirectBranch=1, isTerminator=1, isBarrier = 1 in
def BAU_1r : _F1R<(outs), (ins GRRegs:$addr),
@@ -859,20 +881,41 @@ def BLA_1r : _F1R<(outs), (ins GRRegs:$addr, variable_ops),
[(XCoreBranchLink GRRegs:$addr)]>;
}
+def SYNCR_1r : _F1R<(outs), (ins GRRegs:$r),
+ "syncr res[$r]",
+ [(int_xcore_syncr GRRegs:$r)]>;
+
def FREER_1r : _F1R<(outs), (ins GRRegs:$r),
"freer res[$r]",
[(int_xcore_freer GRRegs:$r)]>;
+let Uses=[R11] in
+def SETV_1r : _F1R<(outs), (ins GRRegs:$r),
+ "setv res[$r], r11",
+ [(int_xcore_setv GRRegs:$r, R11)]>;
+
+def EEU_1r : _F1R<(outs), (ins GRRegs:$r),
+ "eeu res[$r]",
+ [(int_xcore_eeu GRRegs:$r)]>;
+
// Zero operand short
-// TODO waiteu, clre, ssync, freet, ldspc, stspc, ldssr, stssr, ldsed, stsed,
+// TODO ssync, freet, ldspc, stspc, ldssr, stssr, ldsed, stsed,
// stet, geted, getet, getkep, getksp, setkep, getid, kret, dcall, dret,
// dentsp, drestsp
+def CLRE_0R : _F0R<(outs), (ins), "clre", [(int_xcore_clre)]>;
+
let Defs = [R11] in
def GETID_0R : _F0R<(outs), (ins),
"get r11, id",
[(set R11, (int_xcore_getid))]>;
+let isBranch=1, isIndirectBranch=1, isTerminator=1, isBarrier = 1,
+ hasSideEffects = 1 in
+def WAITEU_0R : _F0R<(outs), (ins),
+ "waiteu",
+ [(brind (int_xcore_waitevent))]>;
+
//===----------------------------------------------------------------------===//
// Non-Instruction Patterns
//===----------------------------------------------------------------------===//
diff --git a/contrib/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/contrib/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index b6b6b84..7986d1a 100644
--- a/contrib/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/contrib/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -1897,6 +1897,39 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) {
return BinaryOperator::CreateNot(And);
}
+ // Canonicalize xor to the RHS.
+ if (match(Op0, m_Xor(m_Value(), m_Value())))
+ std::swap(Op0, Op1);
+
+ // A | ( A ^ B) -> A | B
+ // A | (~A ^ B) -> A | ~B
+ if (match(Op1, m_Xor(m_Value(A), m_Value(B)))) {
+ if (Op0 == A || Op0 == B)
+ return BinaryOperator::CreateOr(A, B);
+
+ if (Op1->hasOneUse() && match(A, m_Not(m_Specific(Op0)))) {
+ Value *Not = Builder->CreateNot(B, B->getName()+".not");
+ return BinaryOperator::CreateOr(Not, Op0);
+ }
+ if (Op1->hasOneUse() && match(B, m_Not(m_Specific(Op0)))) {
+ Value *Not = Builder->CreateNot(A, A->getName()+".not");
+ return BinaryOperator::CreateOr(Not, Op0);
+ }
+ }
+
+ // A | ~(A | B) -> A | ~B
+ // A | ~(A ^ B) -> A | ~B
+ if (match(Op1, m_Not(m_Value(A))))
+ if (BinaryOperator *B = dyn_cast<BinaryOperator>(A))
+ if ((Op0 == B->getOperand(0) || Op0 == B->getOperand(1)) &&
+ Op1->hasOneUse() && (B->getOpcode() == Instruction::Or ||
+ B->getOpcode() == Instruction::Xor)) {
+ Value *NotOp = Op0 == B->getOperand(0) ? B->getOperand(1) :
+ B->getOperand(0);
+ Value *Not = Builder->CreateNot(NotOp, NotOp->getName()+".not");
+ return BinaryOperator::CreateOr(Not, Op0);
+ }
+
if (ICmpInst *RHS = dyn_cast<ICmpInst>(I.getOperand(1)))
if (ICmpInst *LHS = dyn_cast<ICmpInst>(I.getOperand(0)))
if (Value *Res = FoldOrOfICmps(LHS, RHS))
diff --git a/contrib/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/contrib/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 8449f7b..0e46450 100644
--- a/contrib/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/contrib/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -953,10 +953,19 @@ bool InstCombiner::transformConstExprCastCall(CallSite CS) {
if (Callee->isDeclaration() && !isConvertible) return false;
}
- if (FT->getNumParams() < NumActualArgs && !FT->isVarArg() &&
- Callee->isDeclaration())
- return false; // Do not delete arguments unless we have a function body.
-
+ if (Callee->isDeclaration()) {
+ // Do not delete arguments unless we have a function body.
+ if (FT->getNumParams() < NumActualArgs && !FT->isVarArg())
+ return false;
+
+ // If the callee is just a declaration, don't change the varargsness of the
+ // call. We don't want to introduce a varargs call where one doesn't
+ // already exist.
+ const PointerType *APTy = cast<PointerType>(CS.getCalledValue()->getType());
+ if (FT->isVarArg()!=cast<FunctionType>(APTy->getElementType())->isVarArg())
+ return false;
+ }
+
if (FT->getNumParams() < NumActualArgs && FT->isVarArg() &&
!CallerPAL.isEmpty())
// In this case we have more arguments than the new function type, but we
@@ -970,8 +979,9 @@ bool InstCombiner::transformConstExprCastCall(CallSite CS) {
return false;
}
+
// Okay, we decided that this is a safe thing to do: go ahead and start
- // inserting cast instructions as necessary...
+ // inserting cast instructions as necessary.
std::vector<Value*> Args;
Args.reserve(NumActualArgs);
SmallVector<AttributeWithIndex, 8> attrVec;
diff --git a/contrib/llvm/lib/Transforms/Scalar/LoopDeletion.cpp b/contrib/llvm/lib/Transforms/Scalar/LoopDeletion.cpp
index 6d1d344..753a558 100644
--- a/contrib/llvm/lib/Transforms/Scalar/LoopDeletion.cpp
+++ b/contrib/llvm/lib/Transforms/Scalar/LoopDeletion.cpp
@@ -78,7 +78,6 @@ bool LoopDeletion::IsLoopDead(Loop* L,
SmallVector<BasicBlock*, 4>& exitingBlocks,
SmallVector<BasicBlock*, 4>& exitBlocks,
bool &Changed, BasicBlock *Preheader) {
- BasicBlock* exitingBlock = exitingBlocks[0];
BasicBlock* exitBlock = exitBlocks[0];
// Make sure that all PHI entries coming from the loop are loop invariant.
@@ -88,11 +87,21 @@ bool LoopDeletion::IsLoopDead(Loop* L,
// of the loop.
BasicBlock::iterator BI = exitBlock->begin();
while (PHINode* P = dyn_cast<PHINode>(BI)) {
- Value* incoming = P->getIncomingValueForBlock(exitingBlock);
+ Value* incoming = P->getIncomingValueForBlock(exitingBlocks[0]);
+
+ // Make sure all exiting blocks produce the same incoming value for the exit
+ // block. If there are different incoming values for different exiting
+ // blocks, then it is impossible to statically determine which value should
+ // be used.
+ for (unsigned i = 1; i < exitingBlocks.size(); ++i) {
+ if (incoming != P->getIncomingValueForBlock(exitingBlocks[i]))
+ return false;
+ }
+
if (Instruction* I = dyn_cast<Instruction>(incoming))
if (!L->makeLoopInvariant(I, Changed, Preheader->getTerminator()))
return false;
-
+
++BI;
}
@@ -147,10 +156,6 @@ bool LoopDeletion::runOnLoop(Loop* L, LPPassManager& LPM) {
if (exitBlocks.size() != 1)
return false;
- // Loops with multiple exits are too complicated to handle correctly.
- if (exitingBlocks.size() != 1)
- return false;
-
// Finally, we have to check that the loop really is dead.
bool Changed = false;
if (!IsLoopDead(L, exitingBlocks, exitBlocks, Changed, preheader))
@@ -166,7 +171,6 @@ bool LoopDeletion::runOnLoop(Loop* L, LPPassManager& LPM) {
// Now that we know the removal is safe, remove the loop by changing the
// branch from the preheader to go to the single exit block.
BasicBlock* exitBlock = exitBlocks[0];
- BasicBlock* exitingBlock = exitingBlocks[0];
// Because we're deleting a large chunk of code at once, the sequence in which
// we remove things is very important to avoid invalidation issues. Don't
@@ -183,9 +187,12 @@ bool LoopDeletion::runOnLoop(Loop* L, LPPassManager& LPM) {
// Rewrite phis in the exit block to get their inputs from
// the preheader instead of the exiting block.
+ BasicBlock* exitingBlock = exitingBlocks[0];
BasicBlock::iterator BI = exitBlock->begin();
while (PHINode* P = dyn_cast<PHINode>(BI)) {
P->replaceUsesOfWith(exitingBlock, preheader);
+ for (unsigned i = 1; i < exitingBlocks.size(); ++i)
+ P->removeIncomingValue(exitingBlocks[i]);
++BI;
}
diff --git a/contrib/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp b/contrib/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
index d7fa149..f8ce214 100644
--- a/contrib/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
+++ b/contrib/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
@@ -31,6 +31,11 @@
// void foo(_Complex float *P)
// for (i) { __real__(*P) = 0; __imag__(*P) = 0; }
//
+// We should enhance this to handle negative strides through memory.
+// Alternatively (and perhaps better) we could rely on an earlier pass to force
+// forward iteration through memory, which is generally better for cache
+// behavior. Negative strides *do* happen for memset/memcpy loops.
+//
// This could recognize common matrix multiplies and dot product idioms and
// replace them with calls to BLAS (if linked in??).
//
@@ -272,10 +277,17 @@ bool LoopIdiomRecognize::processLoopStore(StoreInst *SI, const SCEV *BECount) {
unsigned StoreSize = (unsigned)SizeInBits >> 3;
const SCEVConstant *Stride = dyn_cast<SCEVConstant>(StoreEv->getOperand(1));
- // TODO: Could also handle negative stride here someday, that will require the
- // validity check in mayLoopAccessLocation to be updated though.
- if (Stride == 0 || StoreSize != Stride->getValue()->getValue())
+ if (Stride == 0 || StoreSize != Stride->getValue()->getValue()) {
+ // TODO: Could also handle negative stride here someday, that will require
+ // the validity check in mayLoopAccessLocation to be updated though.
+ // Enable this to print exact negative strides.
+ if (0 && Stride && StoreSize == -Stride->getValue()->getValue()) {
+ dbgs() << "NEGATIVE STRIDE: " << *SI << "\n";
+ dbgs() << "BB: " << *SI->getParent();
+ }
+
return false;
+ }
// See if we can optimize just this store in isolation.
if (processLoopStridedStore(StorePtr, StoreSize, SI->getAlignment(),
diff --git a/contrib/llvm/lib/Transforms/Scalar/SimplifyLibCalls.cpp b/contrib/llvm/lib/Transforms/Scalar/SimplifyLibCalls.cpp
index ec45b71..9f136d4 100644
--- a/contrib/llvm/lib/Transforms/Scalar/SimplifyLibCalls.cpp
+++ b/contrib/llvm/lib/Transforms/Scalar/SimplifyLibCalls.cpp
@@ -25,13 +25,14 @@
#include "llvm/Support/IRBuilder.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/Target/TargetData.h"
+#include "llvm/Target/TargetLibraryInfo.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
-#include "llvm/Config/config.h"
+#include "llvm/Config/config.h" // FIXME: Shouldn't depend on host!
using namespace llvm;
STATISTIC(NumSimplified, "Number of library calls simplified");
@@ -1369,6 +1370,8 @@ namespace {
/// This pass optimizes well known library functions from libc and libm.
///
class SimplifyLibCalls : public FunctionPass {
+ TargetLibraryInfo *TLI;
+
StringMap<LibCallOptimization*> Optimizations;
// String and Memory LibCall Optimizations
StrCatOpt StrCat; StrNCatOpt StrNCat; StrChrOpt StrChr; StrRChrOpt StrRChr;
@@ -1385,7 +1388,7 @@ namespace {
SPrintFOpt SPrintF; PrintFOpt PrintF;
FWriteOpt FWrite; FPutsOpt FPuts; FPrintFOpt FPrintF;
PutsOpt Puts;
-
+
bool Modified; // This is only used by doInitialization.
public:
static char ID; // Pass identification
@@ -1402,14 +1405,20 @@ namespace {
void setDoesNotAlias(Function &F, unsigned n);
bool doInitialization(Module &M);
+ void inferPrototypeAttributes(Function &F);
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.addRequired<TargetLibraryInfo>();
}
};
- char SimplifyLibCalls::ID = 0;
} // end anonymous namespace.
-INITIALIZE_PASS(SimplifyLibCalls, "simplify-libcalls",
- "Simplify well-known library calls", false, false)
+char SimplifyLibCalls::ID = 0;
+
+INITIALIZE_PASS_BEGIN(SimplifyLibCalls, "simplify-libcalls",
+ "Simplify well-known library calls", false, false)
+INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfo)
+INITIALIZE_PASS_END(SimplifyLibCalls, "simplify-libcalls",
+ "Simplify well-known library calls", false, false)
// Public interface to the Simplify LibCalls pass.
FunctionPass *llvm::createSimplifyLibCallsPass() {
@@ -1441,9 +1450,9 @@ void SimplifyLibCalls::InitOptimizations() {
Optimizations["strcspn"] = &StrCSpn;
Optimizations["strstr"] = &StrStr;
Optimizations["memcmp"] = &MemCmp;
- Optimizations["memcpy"] = &MemCpy;
+ if (TLI->has(LibFunc::memcpy)) Optimizations["memcpy"] = &MemCpy;
Optimizations["memmove"] = &MemMove;
- Optimizations["memset"] = &MemSet;
+ if (TLI->has(LibFunc::memset)) Optimizations["memset"] = &MemSet;
// _chk variants of String and Memory LibCall Optimizations.
Optimizations["__strcpy_chk"] = &StrCpyChk;
@@ -1506,6 +1515,8 @@ void SimplifyLibCalls::InitOptimizations() {
/// runOnFunction - Top level algorithm.
///
bool SimplifyLibCalls::runOnFunction(Function &F) {
+ TLI = &getAnalysis<TargetLibraryInfo>();
+
if (Optimizations.empty())
InitOptimizations();
@@ -1597,688 +1608,654 @@ void SimplifyLibCalls::setDoesNotAlias(Function &F, unsigned n) {
}
}
+
+void SimplifyLibCalls::inferPrototypeAttributes(Function &F) {
+ const FunctionType *FTy = F.getFunctionType();
+
+ StringRef Name = F.getName();
+ switch (Name[0]) {
+ case 's':
+ if (Name == "strlen") {
+ if (FTy->getNumParams() != 1 || !FTy->getParamType(0)->isPointerTy())
+ return;
+ setOnlyReadsMemory(F);
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ } else if (Name == "strchr" ||
+ Name == "strrchr") {
+ if (FTy->getNumParams() != 2 ||
+ !FTy->getParamType(0)->isPointerTy() ||
+ !FTy->getParamType(1)->isIntegerTy())
+ return;
+ setOnlyReadsMemory(F);
+ setDoesNotThrow(F);
+ } else if (Name == "strcpy" ||
+ Name == "stpcpy" ||
+ Name == "strcat" ||
+ Name == "strtol" ||
+ Name == "strtod" ||
+ Name == "strtof" ||
+ Name == "strtoul" ||
+ Name == "strtoll" ||
+ Name == "strtold" ||
+ Name == "strncat" ||
+ Name == "strncpy" ||
+ Name == "strtoull") {
+ if (FTy->getNumParams() < 2 ||
+ !FTy->getParamType(1)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 2);
+ } else if (Name == "strxfrm") {
+ if (FTy->getNumParams() != 3 ||
+ !FTy->getParamType(0)->isPointerTy() ||
+ !FTy->getParamType(1)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ setDoesNotCapture(F, 2);
+ } else if (Name == "strcmp" ||
+ Name == "strspn" ||
+ Name == "strncmp" ||
+ Name == "strcspn" ||
+ Name == "strcoll" ||
+ Name == "strcasecmp" ||
+ Name == "strncasecmp") {
+ if (FTy->getNumParams() < 2 ||
+ !FTy->getParamType(0)->isPointerTy() ||
+ !FTy->getParamType(1)->isPointerTy())
+ return;
+ setOnlyReadsMemory(F);
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ setDoesNotCapture(F, 2);
+ } else if (Name == "strstr" ||
+ Name == "strpbrk") {
+ if (FTy->getNumParams() != 2 || !FTy->getParamType(1)->isPointerTy())
+ return;
+ setOnlyReadsMemory(F);
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 2);
+ } else if (Name == "strtok" ||
+ Name == "strtok_r") {
+ if (FTy->getNumParams() < 2 || !FTy->getParamType(1)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 2);
+ } else if (Name == "scanf" ||
+ Name == "setbuf" ||
+ Name == "setvbuf") {
+ if (FTy->getNumParams() < 1 || !FTy->getParamType(0)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ } else if (Name == "strdup" ||
+ Name == "strndup") {
+ if (FTy->getNumParams() < 1 || !FTy->getReturnType()->isPointerTy() ||
+ !FTy->getParamType(0)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotAlias(F, 0);
+ setDoesNotCapture(F, 1);
+ } else if (Name == "stat" ||
+ Name == "sscanf" ||
+ Name == "sprintf" ||
+ Name == "statvfs") {
+ if (FTy->getNumParams() < 2 ||
+ !FTy->getParamType(0)->isPointerTy() ||
+ !FTy->getParamType(1)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ setDoesNotCapture(F, 2);
+ } else if (Name == "snprintf") {
+ if (FTy->getNumParams() != 3 ||
+ !FTy->getParamType(0)->isPointerTy() ||
+ !FTy->getParamType(2)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ setDoesNotCapture(F, 3);
+ } else if (Name == "setitimer") {
+ if (FTy->getNumParams() != 3 ||
+ !FTy->getParamType(1)->isPointerTy() ||
+ !FTy->getParamType(2)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 2);
+ setDoesNotCapture(F, 3);
+ } else if (Name == "system") {
+ if (FTy->getNumParams() != 1 ||
+ !FTy->getParamType(0)->isPointerTy())
+ return;
+ // May throw; "system" is a valid pthread cancellation point.
+ setDoesNotCapture(F, 1);
+ }
+ break;
+ case 'm':
+ if (Name == "malloc") {
+ if (FTy->getNumParams() != 1 ||
+ !FTy->getReturnType()->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotAlias(F, 0);
+ } else if (Name == "memcmp") {
+ if (FTy->getNumParams() != 3 ||
+ !FTy->getParamType(0)->isPointerTy() ||
+ !FTy->getParamType(1)->isPointerTy())
+ return;
+ setOnlyReadsMemory(F);
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ setDoesNotCapture(F, 2);
+ } else if (Name == "memchr" ||
+ Name == "memrchr") {
+ if (FTy->getNumParams() != 3)
+ return;
+ setOnlyReadsMemory(F);
+ setDoesNotThrow(F);
+ } else if (Name == "modf" ||
+ Name == "modff" ||
+ Name == "modfl" ||
+ Name == "memcpy" ||
+ Name == "memccpy" ||
+ Name == "memmove") {
+ if (FTy->getNumParams() < 2 ||
+ !FTy->getParamType(1)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 2);
+ } else if (Name == "memalign") {
+ if (!FTy->getReturnType()->isPointerTy())
+ return;
+ setDoesNotAlias(F, 0);
+ } else if (Name == "mkdir" ||
+ Name == "mktime") {
+ if (FTy->getNumParams() == 0 ||
+ !FTy->getParamType(0)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ }
+ break;
+ case 'r':
+ if (Name == "realloc") {
+ if (FTy->getNumParams() != 2 ||
+ !FTy->getParamType(0)->isPointerTy() ||
+ !FTy->getReturnType()->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotAlias(F, 0);
+ setDoesNotCapture(F, 1);
+ } else if (Name == "read") {
+ if (FTy->getNumParams() != 3 ||
+ !FTy->getParamType(1)->isPointerTy())
+ return;
+ // May throw; "read" is a valid pthread cancellation point.
+ setDoesNotCapture(F, 2);
+ } else if (Name == "rmdir" ||
+ Name == "rewind" ||
+ Name == "remove" ||
+ Name == "realpath") {
+ if (FTy->getNumParams() < 1 ||
+ !FTy->getParamType(0)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ } else if (Name == "rename" ||
+ Name == "readlink") {
+ if (FTy->getNumParams() < 2 ||
+ !FTy->getParamType(0)->isPointerTy() ||
+ !FTy->getParamType(1)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ setDoesNotCapture(F, 2);
+ }
+ break;
+ case 'w':
+ if (Name == "write") {
+ if (FTy->getNumParams() != 3 || !FTy->getParamType(1)->isPointerTy())
+ return;
+ // May throw; "write" is a valid pthread cancellation point.
+ setDoesNotCapture(F, 2);
+ }
+ break;
+ case 'b':
+ if (Name == "bcopy") {
+ if (FTy->getNumParams() != 3 ||
+ !FTy->getParamType(0)->isPointerTy() ||
+ !FTy->getParamType(1)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ setDoesNotCapture(F, 2);
+ } else if (Name == "bcmp") {
+ if (FTy->getNumParams() != 3 ||
+ !FTy->getParamType(0)->isPointerTy() ||
+ !FTy->getParamType(1)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setOnlyReadsMemory(F);
+ setDoesNotCapture(F, 1);
+ setDoesNotCapture(F, 2);
+ } else if (Name == "bzero") {
+ if (FTy->getNumParams() != 2 || !FTy->getParamType(0)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ }
+ break;
+ case 'c':
+ if (Name == "calloc") {
+ if (FTy->getNumParams() != 2 ||
+ !FTy->getReturnType()->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotAlias(F, 0);
+ } else if (Name == "chmod" ||
+ Name == "chown" ||
+ Name == "ctermid" ||
+ Name == "clearerr" ||
+ Name == "closedir") {
+ if (FTy->getNumParams() == 0 || !FTy->getParamType(0)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ }
+ break;
+ case 'a':
+ if (Name == "atoi" ||
+ Name == "atol" ||
+ Name == "atof" ||
+ Name == "atoll") {
+ if (FTy->getNumParams() != 1 || !FTy->getParamType(0)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setOnlyReadsMemory(F);
+ setDoesNotCapture(F, 1);
+ } else if (Name == "access") {
+ if (FTy->getNumParams() != 2 || !FTy->getParamType(0)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ }
+ break;
+ case 'f':
+ if (Name == "fopen") {
+ if (FTy->getNumParams() != 2 ||
+ !FTy->getReturnType()->isPointerTy() ||
+ !FTy->getParamType(0)->isPointerTy() ||
+ !FTy->getParamType(1)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotAlias(F, 0);
+ setDoesNotCapture(F, 1);
+ setDoesNotCapture(F, 2);
+ } else if (Name == "fdopen") {
+ if (FTy->getNumParams() != 2 ||
+ !FTy->getReturnType()->isPointerTy() ||
+ !FTy->getParamType(1)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotAlias(F, 0);
+ setDoesNotCapture(F, 2);
+ } else if (Name == "feof" ||
+ Name == "free" ||
+ Name == "fseek" ||
+ Name == "ftell" ||
+ Name == "fgetc" ||
+ Name == "fseeko" ||
+ Name == "ftello" ||
+ Name == "fileno" ||
+ Name == "fflush" ||
+ Name == "fclose" ||
+ Name == "fsetpos" ||
+ Name == "flockfile" ||
+ Name == "funlockfile" ||
+ Name == "ftrylockfile") {
+ if (FTy->getNumParams() == 0 || !FTy->getParamType(0)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ } else if (Name == "ferror") {
+ if (FTy->getNumParams() != 1 || !FTy->getParamType(0)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ setOnlyReadsMemory(F);
+ } else if (Name == "fputc" ||
+ Name == "fstat" ||
+ Name == "frexp" ||
+ Name == "frexpf" ||
+ Name == "frexpl" ||
+ Name == "fstatvfs") {
+ if (FTy->getNumParams() != 2 || !FTy->getParamType(1)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 2);
+ } else if (Name == "fgets") {
+ if (FTy->getNumParams() != 3 ||
+ !FTy->getParamType(0)->isPointerTy() ||
+ !FTy->getParamType(2)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 3);
+ } else if (Name == "fread" ||
+ Name == "fwrite") {
+ if (FTy->getNumParams() != 4 ||
+ !FTy->getParamType(0)->isPointerTy() ||
+ !FTy->getParamType(3)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ setDoesNotCapture(F, 4);
+ } else if (Name == "fputs" ||
+ Name == "fscanf" ||
+ Name == "fprintf" ||
+ Name == "fgetpos") {
+ if (FTy->getNumParams() < 2 ||
+ !FTy->getParamType(0)->isPointerTy() ||
+ !FTy->getParamType(1)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ setDoesNotCapture(F, 2);
+ }
+ break;
+ case 'g':
+ if (Name == "getc" ||
+ Name == "getlogin_r" ||
+ Name == "getc_unlocked") {
+ if (FTy->getNumParams() == 0 || !FTy->getParamType(0)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ } else if (Name == "getenv") {
+ if (FTy->getNumParams() != 1 || !FTy->getParamType(0)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setOnlyReadsMemory(F);
+ setDoesNotCapture(F, 1);
+ } else if (Name == "gets" ||
+ Name == "getchar") {
+ setDoesNotThrow(F);
+ } else if (Name == "getitimer") {
+ if (FTy->getNumParams() != 2 || !FTy->getParamType(1)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 2);
+ } else if (Name == "getpwnam") {
+ if (FTy->getNumParams() != 1 || !FTy->getParamType(0)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ }
+ break;
+ case 'u':
+ if (Name == "ungetc") {
+ if (FTy->getNumParams() != 2 || !FTy->getParamType(1)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 2);
+ } else if (Name == "uname" ||
+ Name == "unlink" ||
+ Name == "unsetenv") {
+ if (FTy->getNumParams() != 1 || !FTy->getParamType(0)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ } else if (Name == "utime" ||
+ Name == "utimes") {
+ if (FTy->getNumParams() != 2 ||
+ !FTy->getParamType(0)->isPointerTy() ||
+ !FTy->getParamType(1)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ setDoesNotCapture(F, 2);
+ }
+ break;
+ case 'p':
+ if (Name == "putc") {
+ if (FTy->getNumParams() != 2 || !FTy->getParamType(1)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 2);
+ } else if (Name == "puts" ||
+ Name == "printf" ||
+ Name == "perror") {
+ if (FTy->getNumParams() != 1 || !FTy->getParamType(0)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ } else if (Name == "pread" ||
+ Name == "pwrite") {
+ if (FTy->getNumParams() != 4 || !FTy->getParamType(1)->isPointerTy())
+ return;
+ // May throw; these are valid pthread cancellation points.
+ setDoesNotCapture(F, 2);
+ } else if (Name == "putchar") {
+ setDoesNotThrow(F);
+ } else if (Name == "popen") {
+ if (FTy->getNumParams() != 2 ||
+ !FTy->getReturnType()->isPointerTy() ||
+ !FTy->getParamType(0)->isPointerTy() ||
+ !FTy->getParamType(1)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotAlias(F, 0);
+ setDoesNotCapture(F, 1);
+ setDoesNotCapture(F, 2);
+ } else if (Name == "pclose") {
+ if (FTy->getNumParams() != 1 || !FTy->getParamType(0)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ }
+ break;
+ case 'v':
+ if (Name == "vscanf") {
+ if (FTy->getNumParams() != 2 || !FTy->getParamType(1)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ } else if (Name == "vsscanf" ||
+ Name == "vfscanf") {
+ if (FTy->getNumParams() != 3 ||
+ !FTy->getParamType(1)->isPointerTy() ||
+ !FTy->getParamType(2)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ setDoesNotCapture(F, 2);
+ } else if (Name == "valloc") {
+ if (!FTy->getReturnType()->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotAlias(F, 0);
+ } else if (Name == "vprintf") {
+ if (FTy->getNumParams() != 2 || !FTy->getParamType(0)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ } else if (Name == "vfprintf" ||
+ Name == "vsprintf") {
+ if (FTy->getNumParams() != 3 ||
+ !FTy->getParamType(0)->isPointerTy() ||
+ !FTy->getParamType(1)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ setDoesNotCapture(F, 2);
+ } else if (Name == "vsnprintf") {
+ if (FTy->getNumParams() != 4 ||
+ !FTy->getParamType(0)->isPointerTy() ||
+ !FTy->getParamType(2)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ setDoesNotCapture(F, 3);
+ }
+ break;
+ case 'o':
+ if (Name == "open") {
+ if (FTy->getNumParams() < 2 || !FTy->getParamType(0)->isPointerTy())
+ return;
+ // May throw; "open" is a valid pthread cancellation point.
+ setDoesNotCapture(F, 1);
+ } else if (Name == "opendir") {
+ if (FTy->getNumParams() != 1 ||
+ !FTy->getReturnType()->isPointerTy() ||
+ !FTy->getParamType(0)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotAlias(F, 0);
+ setDoesNotCapture(F, 1);
+ }
+ break;
+ case 't':
+ if (Name == "tmpfile") {
+ if (!FTy->getReturnType()->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotAlias(F, 0);
+ } else if (Name == "times") {
+ if (FTy->getNumParams() != 1 || !FTy->getParamType(0)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ }
+ break;
+ case 'h':
+ if (Name == "htonl" ||
+ Name == "htons") {
+ setDoesNotThrow(F);
+ setDoesNotAccessMemory(F);
+ }
+ break;
+ case 'n':
+ if (Name == "ntohl" ||
+ Name == "ntohs") {
+ setDoesNotThrow(F);
+ setDoesNotAccessMemory(F);
+ }
+ break;
+ case 'l':
+ if (Name == "lstat") {
+ if (FTy->getNumParams() != 2 ||
+ !FTy->getParamType(0)->isPointerTy() ||
+ !FTy->getParamType(1)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ setDoesNotCapture(F, 2);
+ } else if (Name == "lchown") {
+ if (FTy->getNumParams() != 3 || !FTy->getParamType(0)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ }
+ break;
+ case 'q':
+ if (Name == "qsort") {
+ if (FTy->getNumParams() != 4 || !FTy->getParamType(3)->isPointerTy())
+ return;
+ // May throw; places call through function pointer.
+ setDoesNotCapture(F, 4);
+ }
+ break;
+ case '_':
+ if (Name == "__strdup" ||
+ Name == "__strndup") {
+ if (FTy->getNumParams() < 1 ||
+ !FTy->getReturnType()->isPointerTy() ||
+ !FTy->getParamType(0)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotAlias(F, 0);
+ setDoesNotCapture(F, 1);
+ } else if (Name == "__strtok_r") {
+ if (FTy->getNumParams() != 3 ||
+ !FTy->getParamType(1)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 2);
+ } else if (Name == "_IO_getc") {
+ if (FTy->getNumParams() != 1 || !FTy->getParamType(0)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ } else if (Name == "_IO_putc") {
+ if (FTy->getNumParams() != 2 || !FTy->getParamType(1)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 2);
+ }
+ break;
+ case 1:
+ if (Name == "\1__isoc99_scanf") {
+ if (FTy->getNumParams() < 1 ||
+ !FTy->getParamType(0)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ } else if (Name == "\1stat64" ||
+ Name == "\1lstat64" ||
+ Name == "\1statvfs64" ||
+ Name == "\1__isoc99_sscanf") {
+ if (FTy->getNumParams() < 1 ||
+ !FTy->getParamType(0)->isPointerTy() ||
+ !FTy->getParamType(1)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ setDoesNotCapture(F, 2);
+ } else if (Name == "\1fopen64") {
+ if (FTy->getNumParams() != 2 ||
+ !FTy->getReturnType()->isPointerTy() ||
+ !FTy->getParamType(0)->isPointerTy() ||
+ !FTy->getParamType(1)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotAlias(F, 0);
+ setDoesNotCapture(F, 1);
+ setDoesNotCapture(F, 2);
+ } else if (Name == "\1fseeko64" ||
+ Name == "\1ftello64") {
+ if (FTy->getNumParams() == 0 || !FTy->getParamType(0)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ } else if (Name == "\1tmpfile64") {
+ if (!FTy->getReturnType()->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotAlias(F, 0);
+ } else if (Name == "\1fstat64" ||
+ Name == "\1fstatvfs64") {
+ if (FTy->getNumParams() != 2 || !FTy->getParamType(1)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 2);
+ } else if (Name == "\1open64") {
+ if (FTy->getNumParams() < 2 || !FTy->getParamType(0)->isPointerTy())
+ return;
+ // May throw; "open" is a valid pthread cancellation point.
+ setDoesNotCapture(F, 1);
+ }
+ break;
+ }
+}
+
/// doInitialization - Add attributes to well-known functions.
///
bool SimplifyLibCalls::doInitialization(Module &M) {
Modified = false;
for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) {
Function &F = *I;
- if (!F.isDeclaration())
- continue;
-
- if (!F.hasName())
- continue;
-
- const FunctionType *FTy = F.getFunctionType();
-
- StringRef Name = F.getName();
- switch (Name[0]) {
- case 's':
- if (Name == "strlen") {
- if (FTy->getNumParams() != 1 ||
- !FTy->getParamType(0)->isPointerTy())
- continue;
- setOnlyReadsMemory(F);
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- } else if (Name == "strchr" ||
- Name == "strrchr") {
- if (FTy->getNumParams() != 2 ||
- !FTy->getParamType(0)->isPointerTy() ||
- !FTy->getParamType(1)->isIntegerTy())
- continue;
- setOnlyReadsMemory(F);
- setDoesNotThrow(F);
- } else if (Name == "strcpy" ||
- Name == "stpcpy" ||
- Name == "strcat" ||
- Name == "strtol" ||
- Name == "strtod" ||
- Name == "strtof" ||
- Name == "strtoul" ||
- Name == "strtoll" ||
- Name == "strtold" ||
- Name == "strncat" ||
- Name == "strncpy" ||
- Name == "strtoull") {
- if (FTy->getNumParams() < 2 ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 2);
- } else if (Name == "strxfrm") {
- if (FTy->getNumParams() != 3 ||
- !FTy->getParamType(0)->isPointerTy() ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- setDoesNotCapture(F, 2);
- } else if (Name == "strcmp" ||
- Name == "strspn" ||
- Name == "strncmp" ||
- Name == "strcspn" ||
- Name == "strcoll" ||
- Name == "strcasecmp" ||
- Name == "strncasecmp") {
- if (FTy->getNumParams() < 2 ||
- !FTy->getParamType(0)->isPointerTy() ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- setOnlyReadsMemory(F);
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- setDoesNotCapture(F, 2);
- } else if (Name == "strstr" ||
- Name == "strpbrk") {
- if (FTy->getNumParams() != 2 ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- setOnlyReadsMemory(F);
- setDoesNotThrow(F);
- setDoesNotCapture(F, 2);
- } else if (Name == "strtok" ||
- Name == "strtok_r") {
- if (FTy->getNumParams() < 2 ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 2);
- } else if (Name == "scanf" ||
- Name == "setbuf" ||
- Name == "setvbuf") {
- if (FTy->getNumParams() < 1 ||
- !FTy->getParamType(0)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- } else if (Name == "strdup" ||
- Name == "strndup") {
- if (FTy->getNumParams() < 1 ||
- !FTy->getReturnType()->isPointerTy() ||
- !FTy->getParamType(0)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotAlias(F, 0);
- setDoesNotCapture(F, 1);
- } else if (Name == "stat" ||
- Name == "sscanf" ||
- Name == "sprintf" ||
- Name == "statvfs") {
- if (FTy->getNumParams() < 2 ||
- !FTy->getParamType(0)->isPointerTy() ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- setDoesNotCapture(F, 2);
- } else if (Name == "snprintf") {
- if (FTy->getNumParams() != 3 ||
- !FTy->getParamType(0)->isPointerTy() ||
- !FTy->getParamType(2)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- setDoesNotCapture(F, 3);
- } else if (Name == "setitimer") {
- if (FTy->getNumParams() != 3 ||
- !FTy->getParamType(1)->isPointerTy() ||
- !FTy->getParamType(2)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 2);
- setDoesNotCapture(F, 3);
- } else if (Name == "system") {
- if (FTy->getNumParams() != 1 ||
- !FTy->getParamType(0)->isPointerTy())
- continue;
- // May throw; "system" is a valid pthread cancellation point.
- setDoesNotCapture(F, 1);
- }
- break;
- case 'm':
- if (Name == "malloc") {
- if (FTy->getNumParams() != 1 ||
- !FTy->getReturnType()->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotAlias(F, 0);
- } else if (Name == "memcmp") {
- if (FTy->getNumParams() != 3 ||
- !FTy->getParamType(0)->isPointerTy() ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- setOnlyReadsMemory(F);
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- setDoesNotCapture(F, 2);
- } else if (Name == "memchr" ||
- Name == "memrchr") {
- if (FTy->getNumParams() != 3)
- continue;
- setOnlyReadsMemory(F);
- setDoesNotThrow(F);
- } else if (Name == "modf" ||
- Name == "modff" ||
- Name == "modfl" ||
- Name == "memcpy" ||
- Name == "memccpy" ||
- Name == "memmove") {
- if (FTy->getNumParams() < 2 ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 2);
- } else if (Name == "memalign") {
- if (!FTy->getReturnType()->isPointerTy())
- continue;
- setDoesNotAlias(F, 0);
- } else if (Name == "mkdir" ||
- Name == "mktime") {
- if (FTy->getNumParams() == 0 ||
- !FTy->getParamType(0)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- }
- break;
- case 'r':
- if (Name == "realloc") {
- if (FTy->getNumParams() != 2 ||
- !FTy->getParamType(0)->isPointerTy() ||
- !FTy->getReturnType()->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotAlias(F, 0);
- setDoesNotCapture(F, 1);
- } else if (Name == "read") {
- if (FTy->getNumParams() != 3 ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- // May throw; "read" is a valid pthread cancellation point.
- setDoesNotCapture(F, 2);
- } else if (Name == "rmdir" ||
- Name == "rewind" ||
- Name == "remove" ||
- Name == "realpath") {
- if (FTy->getNumParams() < 1 ||
- !FTy->getParamType(0)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- } else if (Name == "rename" ||
- Name == "readlink") {
- if (FTy->getNumParams() < 2 ||
- !FTy->getParamType(0)->isPointerTy() ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- setDoesNotCapture(F, 2);
- }
- break;
- case 'w':
- if (Name == "write") {
- if (FTy->getNumParams() != 3 ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- // May throw; "write" is a valid pthread cancellation point.
- setDoesNotCapture(F, 2);
- }
- break;
- case 'b':
- if (Name == "bcopy") {
- if (FTy->getNumParams() != 3 ||
- !FTy->getParamType(0)->isPointerTy() ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- setDoesNotCapture(F, 2);
- } else if (Name == "bcmp") {
- if (FTy->getNumParams() != 3 ||
- !FTy->getParamType(0)->isPointerTy() ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setOnlyReadsMemory(F);
- setDoesNotCapture(F, 1);
- setDoesNotCapture(F, 2);
- } else if (Name == "bzero") {
- if (FTy->getNumParams() != 2 ||
- !FTy->getParamType(0)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- }
- break;
- case 'c':
- if (Name == "calloc") {
- if (FTy->getNumParams() != 2 ||
- !FTy->getReturnType()->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotAlias(F, 0);
- } else if (Name == "chmod" ||
- Name == "chown" ||
- Name == "ctermid" ||
- Name == "clearerr" ||
- Name == "closedir") {
- if (FTy->getNumParams() == 0 ||
- !FTy->getParamType(0)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- }
- break;
- case 'a':
- if (Name == "atoi" ||
- Name == "atol" ||
- Name == "atof" ||
- Name == "atoll") {
- if (FTy->getNumParams() != 1 ||
- !FTy->getParamType(0)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setOnlyReadsMemory(F);
- setDoesNotCapture(F, 1);
- } else if (Name == "access") {
- if (FTy->getNumParams() != 2 ||
- !FTy->getParamType(0)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- }
- break;
- case 'f':
- if (Name == "fopen") {
- if (FTy->getNumParams() != 2 ||
- !FTy->getReturnType()->isPointerTy() ||
- !FTy->getParamType(0)->isPointerTy() ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotAlias(F, 0);
- setDoesNotCapture(F, 1);
- setDoesNotCapture(F, 2);
- } else if (Name == "fdopen") {
- if (FTy->getNumParams() != 2 ||
- !FTy->getReturnType()->isPointerTy() ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotAlias(F, 0);
- setDoesNotCapture(F, 2);
- } else if (Name == "feof" ||
- Name == "free" ||
- Name == "fseek" ||
- Name == "ftell" ||
- Name == "fgetc" ||
- Name == "fseeko" ||
- Name == "ftello" ||
- Name == "fileno" ||
- Name == "fflush" ||
- Name == "fclose" ||
- Name == "fsetpos" ||
- Name == "flockfile" ||
- Name == "funlockfile" ||
- Name == "ftrylockfile") {
- if (FTy->getNumParams() == 0 ||
- !FTy->getParamType(0)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- } else if (Name == "ferror") {
- if (FTy->getNumParams() != 1 ||
- !FTy->getParamType(0)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- setOnlyReadsMemory(F);
- } else if (Name == "fputc" ||
- Name == "fstat" ||
- Name == "frexp" ||
- Name == "frexpf" ||
- Name == "frexpl" ||
- Name == "fstatvfs") {
- if (FTy->getNumParams() != 2 ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 2);
- } else if (Name == "fgets") {
- if (FTy->getNumParams() != 3 ||
- !FTy->getParamType(0)->isPointerTy() ||
- !FTy->getParamType(2)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 3);
- } else if (Name == "fread" ||
- Name == "fwrite") {
- if (FTy->getNumParams() != 4 ||
- !FTy->getParamType(0)->isPointerTy() ||
- !FTy->getParamType(3)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- setDoesNotCapture(F, 4);
- } else if (Name == "fputs" ||
- Name == "fscanf" ||
- Name == "fprintf" ||
- Name == "fgetpos") {
- if (FTy->getNumParams() < 2 ||
- !FTy->getParamType(0)->isPointerTy() ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- setDoesNotCapture(F, 2);
- }
- break;
- case 'g':
- if (Name == "getc" ||
- Name == "getlogin_r" ||
- Name == "getc_unlocked") {
- if (FTy->getNumParams() == 0 ||
- !FTy->getParamType(0)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- } else if (Name == "getenv") {
- if (FTy->getNumParams() != 1 ||
- !FTy->getParamType(0)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setOnlyReadsMemory(F);
- setDoesNotCapture(F, 1);
- } else if (Name == "gets" ||
- Name == "getchar") {
- setDoesNotThrow(F);
- } else if (Name == "getitimer") {
- if (FTy->getNumParams() != 2 ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 2);
- } else if (Name == "getpwnam") {
- if (FTy->getNumParams() != 1 ||
- !FTy->getParamType(0)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- }
- break;
- case 'u':
- if (Name == "ungetc") {
- if (FTy->getNumParams() != 2 ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 2);
- } else if (Name == "uname" ||
- Name == "unlink" ||
- Name == "unsetenv") {
- if (FTy->getNumParams() != 1 ||
- !FTy->getParamType(0)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- } else if (Name == "utime" ||
- Name == "utimes") {
- if (FTy->getNumParams() != 2 ||
- !FTy->getParamType(0)->isPointerTy() ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- setDoesNotCapture(F, 2);
- }
- break;
- case 'p':
- if (Name == "putc") {
- if (FTy->getNumParams() != 2 ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 2);
- } else if (Name == "puts" ||
- Name == "printf" ||
- Name == "perror") {
- if (FTy->getNumParams() != 1 ||
- !FTy->getParamType(0)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- } else if (Name == "pread" ||
- Name == "pwrite") {
- if (FTy->getNumParams() != 4 ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- // May throw; these are valid pthread cancellation points.
- setDoesNotCapture(F, 2);
- } else if (Name == "putchar") {
- setDoesNotThrow(F);
- } else if (Name == "popen") {
- if (FTy->getNumParams() != 2 ||
- !FTy->getReturnType()->isPointerTy() ||
- !FTy->getParamType(0)->isPointerTy() ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotAlias(F, 0);
- setDoesNotCapture(F, 1);
- setDoesNotCapture(F, 2);
- } else if (Name == "pclose") {
- if (FTy->getNumParams() != 1 ||
- !FTy->getParamType(0)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- }
- break;
- case 'v':
- if (Name == "vscanf") {
- if (FTy->getNumParams() != 2 ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- } else if (Name == "vsscanf" ||
- Name == "vfscanf") {
- if (FTy->getNumParams() != 3 ||
- !FTy->getParamType(1)->isPointerTy() ||
- !FTy->getParamType(2)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- setDoesNotCapture(F, 2);
- } else if (Name == "valloc") {
- if (!FTy->getReturnType()->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotAlias(F, 0);
- } else if (Name == "vprintf") {
- if (FTy->getNumParams() != 2 ||
- !FTy->getParamType(0)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- } else if (Name == "vfprintf" ||
- Name == "vsprintf") {
- if (FTy->getNumParams() != 3 ||
- !FTy->getParamType(0)->isPointerTy() ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- setDoesNotCapture(F, 2);
- } else if (Name == "vsnprintf") {
- if (FTy->getNumParams() != 4 ||
- !FTy->getParamType(0)->isPointerTy() ||
- !FTy->getParamType(2)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- setDoesNotCapture(F, 3);
- }
- break;
- case 'o':
- if (Name == "open") {
- if (FTy->getNumParams() < 2 ||
- !FTy->getParamType(0)->isPointerTy())
- continue;
- // May throw; "open" is a valid pthread cancellation point.
- setDoesNotCapture(F, 1);
- } else if (Name == "opendir") {
- if (FTy->getNumParams() != 1 ||
- !FTy->getReturnType()->isPointerTy() ||
- !FTy->getParamType(0)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotAlias(F, 0);
- setDoesNotCapture(F, 1);
- }
- break;
- case 't':
- if (Name == "tmpfile") {
- if (!FTy->getReturnType()->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotAlias(F, 0);
- } else if (Name == "times") {
- if (FTy->getNumParams() != 1 ||
- !FTy->getParamType(0)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- }
- break;
- case 'h':
- if (Name == "htonl" ||
- Name == "htons") {
- setDoesNotThrow(F);
- setDoesNotAccessMemory(F);
- }
- break;
- case 'n':
- if (Name == "ntohl" ||
- Name == "ntohs") {
- setDoesNotThrow(F);
- setDoesNotAccessMemory(F);
- }
- break;
- case 'l':
- if (Name == "lstat") {
- if (FTy->getNumParams() != 2 ||
- !FTy->getParamType(0)->isPointerTy() ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- setDoesNotCapture(F, 2);
- } else if (Name == "lchown") {
- if (FTy->getNumParams() != 3 ||
- !FTy->getParamType(0)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- }
- break;
- case 'q':
- if (Name == "qsort") {
- if (FTy->getNumParams() != 4 ||
- !FTy->getParamType(3)->isPointerTy())
- continue;
- // May throw; places call through function pointer.
- setDoesNotCapture(F, 4);
- }
- break;
- case '_':
- if (Name == "__strdup" ||
- Name == "__strndup") {
- if (FTy->getNumParams() < 1 ||
- !FTy->getReturnType()->isPointerTy() ||
- !FTy->getParamType(0)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotAlias(F, 0);
- setDoesNotCapture(F, 1);
- } else if (Name == "__strtok_r") {
- if (FTy->getNumParams() != 3 ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 2);
- } else if (Name == "_IO_getc") {
- if (FTy->getNumParams() != 1 ||
- !FTy->getParamType(0)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- } else if (Name == "_IO_putc") {
- if (FTy->getNumParams() != 2 ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 2);
- }
- break;
- case 1:
- if (Name == "\1__isoc99_scanf") {
- if (FTy->getNumParams() < 1 ||
- !FTy->getParamType(0)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- } else if (Name == "\1stat64" ||
- Name == "\1lstat64" ||
- Name == "\1statvfs64" ||
- Name == "\1__isoc99_sscanf") {
- if (FTy->getNumParams() < 1 ||
- !FTy->getParamType(0)->isPointerTy() ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- setDoesNotCapture(F, 2);
- } else if (Name == "\1fopen64") {
- if (FTy->getNumParams() != 2 ||
- !FTy->getReturnType()->isPointerTy() ||
- !FTy->getParamType(0)->isPointerTy() ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotAlias(F, 0);
- setDoesNotCapture(F, 1);
- setDoesNotCapture(F, 2);
- } else if (Name == "\1fseeko64" ||
- Name == "\1ftello64") {
- if (FTy->getNumParams() == 0 ||
- !FTy->getParamType(0)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- } else if (Name == "\1tmpfile64") {
- if (!FTy->getReturnType()->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotAlias(F, 0);
- } else if (Name == "\1fstat64" ||
- Name == "\1fstatvfs64") {
- if (FTy->getNumParams() != 2 ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 2);
- } else if (Name == "\1open64") {
- if (FTy->getNumParams() < 2 ||
- !FTy->getParamType(0)->isPointerTy())
- continue;
- // May throw; "open" is a valid pthread cancellation point.
- setDoesNotCapture(F, 1);
- }
- break;
- }
+ if (F.isDeclaration() && F.hasName())
+ inferPrototypeAttributes(F);
}
return Modified;
}
diff --git a/contrib/llvm/lib/Transforms/Utils/Local.cpp b/contrib/llvm/lib/Transforms/Utils/Local.cpp
index 063c76e..3f789fa 100644
--- a/contrib/llvm/lib/Transforms/Utils/Local.cpp
+++ b/contrib/llvm/lib/Transforms/Utils/Local.cpp
@@ -262,12 +262,13 @@ bool llvm::RecursivelyDeleteTriviallyDeadInstructions(Value *V) {
/// areAllUsesEqual - Check whether the uses of a value are all the same.
/// This is similar to Instruction::hasOneUse() except this will also return
-/// true when there are multiple uses that all refer to the same value.
+/// true when there are no uses or multiple uses that all refer to the same
+/// value.
static bool areAllUsesEqual(Instruction *I) {
Value::use_iterator UI = I->use_begin();
Value::use_iterator UE = I->use_end();
if (UI == UE)
- return false;
+ return true;
User *TheUse = *UI;
for (++UI; UI != UE; ++UI) {
@@ -281,31 +282,24 @@ static bool areAllUsesEqual(Instruction *I) {
/// dead PHI node, due to being a def-use chain of single-use nodes that
/// either forms a cycle or is terminated by a trivially dead instruction,
/// delete it. If that makes any of its operands trivially dead, delete them
-/// too, recursively. Return true if the PHI node is actually deleted.
+/// too, recursively. Return true if a change was made.
bool llvm::RecursivelyDeleteDeadPHINode(PHINode *PN) {
- // We can remove a PHI if it is on a cycle in the def-use graph
- // where each node in the cycle has degree one, i.e. only one use,
- // and is an instruction with no side effects.
- if (!areAllUsesEqual(PN))
- return false;
+ SmallPtrSet<Instruction*, 4> Visited;
+ for (Instruction *I = PN; areAllUsesEqual(I) && !I->mayHaveSideEffects();
+ I = cast<Instruction>(*I->use_begin())) {
+ if (I->use_empty())
+ return RecursivelyDeleteTriviallyDeadInstructions(I);
- bool Changed = false;
- SmallPtrSet<PHINode *, 4> PHIs;
- PHIs.insert(PN);
- for (Instruction *J = cast<Instruction>(*PN->use_begin());
- areAllUsesEqual(J) && !J->mayHaveSideEffects();
- J = cast<Instruction>(*J->use_begin()))
- // If we find a PHI more than once, we're on a cycle that
+ // If we find an instruction more than once, we're on a cycle that
// won't prove fruitful.
- if (PHINode *JP = dyn_cast<PHINode>(J))
- if (!PHIs.insert(JP)) {
- // Break the cycle and delete the PHI and its operands.
- JP->replaceAllUsesWith(UndefValue::get(JP->getType()));
- (void)RecursivelyDeleteTriviallyDeadInstructions(JP);
- Changed = true;
- break;
- }
- return Changed;
+ if (!Visited.insert(I)) {
+ // Break the cycle and delete the instruction and its operands.
+ I->replaceAllUsesWith(UndefValue::get(I->getType()));
+ (void)RecursivelyDeleteTriviallyDeadInstructions(I);
+ return true;
+ }
+ }
+ return false;
}
/// SimplifyInstructionsInBlock - Scan the specified basic block and try to
diff --git a/contrib/llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp b/contrib/llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp
index e6a4373..7788857 100644
--- a/contrib/llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp
+++ b/contrib/llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp
@@ -35,6 +35,7 @@
#include "llvm/Metadata.h"
#include "llvm/Analysis/AliasSetTracker.h"
#include "llvm/Analysis/DebugInfo.h"
+#include "llvm/Analysis/DIBuilder.h"
#include "llvm/Analysis/Dominators.h"
#include "llvm/Analysis/InstructionSimplify.h"
#include "llvm/ADT/DenseMap.h"
@@ -190,7 +191,7 @@ namespace {
///
std::vector<AllocaInst*> Allocas;
DominatorTree &DT;
- DIFactory *DIF;
+ DIBuilder *DIB;
/// AST - An AliasSetTracker object to update. If null, don't update it.
///
@@ -235,9 +236,9 @@ namespace {
public:
PromoteMem2Reg(const std::vector<AllocaInst*> &A, DominatorTree &dt,
AliasSetTracker *ast)
- : Allocas(A), DT(dt), DIF(0), AST(ast) {}
+ : Allocas(A), DT(dt), DIB(0), AST(ast) {}
~PromoteMem2Reg() {
- delete DIF;
+ delete DIB;
}
void run();
@@ -951,9 +952,9 @@ void PromoteMem2Reg::ConvertDebugDeclareToDebugValue(DbgDeclareInst *DDI,
if (!DIVar.Verify())
return;
- if (!DIF)
- DIF = new DIFactory(*SI->getParent()->getParent()->getParent());
- Instruction *DbgVal = DIF->InsertDbgValueIntrinsic(SI->getOperand(0), 0,
+ if (!DIB)
+ DIB = new DIBuilder(*SI->getParent()->getParent()->getParent());
+ Instruction *DbgVal = DIB->insertDbgValueIntrinsic(SI->getOperand(0), 0,
DIVar, SI);
// Propagate any debug metadata from the store onto the dbg.value.
diff --git a/contrib/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/contrib/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index fb660db..c670885 100644
--- a/contrib/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/contrib/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -247,6 +247,11 @@ static bool DominatesMergePoint(Value *V, BasicBlock *BB,
if (PBB->getFirstNonPHIOrDbg() != I)
return false;
break;
+ case Instruction::GetElementPtr:
+ // GEPs are cheap if all indices are constant.
+ if (!cast<GetElementPtrInst>(I)->hasAllConstantIndices())
+ return false;
+ break;
case Instruction::Add:
case Instruction::Sub:
case Instruction::And:
diff --git a/contrib/llvm/tools/clang/include/clang-c/Index.h b/contrib/llvm/tools/clang/include/clang-c/Index.h
index b3b49c7..722f6be 100644
--- a/contrib/llvm/tools/clang/include/clang-c/Index.h
+++ b/contrib/llvm/tools/clang/include/clang-c/Index.h
@@ -35,7 +35,7 @@ extern "C" {
#define CINDEX_LINKAGE
#endif
-/** \defgroup CINDEX C Interface to Clang
+/** \defgroup CINDEX libclang: C Interface to Clang
*
* The C Interface to Clang provides a relatively small API that exposes
* facilities for parsing source code into an abstract syntax tree (AST),
diff --git a/contrib/llvm/tools/clang/include/clang/AST/ASTContext.h b/contrib/llvm/tools/clang/include/clang/AST/ASTContext.h
index 0e88713..c0eeb5a 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/ASTContext.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/ASTContext.h
@@ -115,6 +115,7 @@ class ASTContext {
llvm::FoldingSet<PackExpansionType> PackExpansionTypes;
mutable llvm::FoldingSet<ObjCObjectTypeImpl> ObjCObjectTypes;
mutable llvm::FoldingSet<ObjCObjectPointerType> ObjCObjectPointerTypes;
+ mutable llvm::FoldingSet<AutoType> AutoTypes;
llvm::FoldingSet<AttributedType> AttributedTypes;
mutable llvm::FoldingSet<QualifiedTemplateName> QualifiedTemplateNames;
@@ -551,11 +552,6 @@ public:
return cudaConfigureCallDecl;
}
- /// This gets the struct used to keep track of pointer to blocks, complete
- /// with captured variables.
- QualType getBlockParmType(bool BlockHasCopyDispose,
- llvm::SmallVectorImpl<const Expr *> &Layout) const;
-
/// This builds the struct used for __block variables.
QualType BuildByRefType(llvm::StringRef DeclName, QualType Ty) const;
@@ -1525,7 +1521,6 @@ private:
/// \brief A counter used to uniquely identify "blocks".
mutable unsigned int UniqueBlockByRefTypeID;
- mutable unsigned int UniqueBlockParmTypeID;
friend class DeclContext;
friend class DeclarationNameTable;
diff --git a/contrib/llvm/tools/clang/include/clang/AST/ASTImporter.h b/contrib/llvm/tools/clang/include/clang/AST/ASTImporter.h
index b659ce7..e153596 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/ASTImporter.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/ASTImporter.h
@@ -145,7 +145,14 @@ namespace clang {
/// \returns the equivalent nested-name-specifier in the "to"
/// context, or NULL if an error occurred.
NestedNameSpecifier *Import(NestedNameSpecifier *FromNNS);
-
+
+ /// \brief Import the given nested-name-specifier from the "from"
+ /// context into the "to" context.
+ ///
+ /// \returns the equivalent nested-name-specifier in the "to"
+ /// context.
+ NestedNameSpecifierLoc Import(NestedNameSpecifierLoc FromNNS);
+
/// \brief Import the goven template name from the "from" context into the
/// "to" context.
TemplateName Import(TemplateName From);
diff --git a/contrib/llvm/tools/clang/include/clang/AST/Decl.h b/contrib/llvm/tools/clang/include/clang/AST/Decl.h
index ee515da..31cee24 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/Decl.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/Decl.h
@@ -119,6 +119,14 @@ public:
return getIdentifier() ? getIdentifier()->getName() : "";
}
+ llvm::StringRef getMessageUnavailableAttr(bool unavailable) const {
+ if (!unavailable)
+ return "";
+ if (const UnavailableAttr *UA = getAttr<UnavailableAttr>())
+ return UA->getMessage();
+ return "";
+ }
+
/// getNameAsString - Get a human-readable name for the declaration, even if
/// it is one of the special kinds of names (C++ constructor, Objective-C
/// selector, etc). Creating this name requires expensive string
@@ -475,10 +483,7 @@ public:
/// QualifierInfo - A struct with extended info about a syntactic
/// name qualifier, to be used for the case of out-of-line declarations.
struct QualifierInfo {
- /// NNS - The syntactic name qualifier.
- NestedNameSpecifier *NNS;
- /// NNSRange - The source range for the qualifier.
- SourceRange NNSRange;
+ NestedNameSpecifierLoc QualifierLoc;
/// NumTemplParamLists - The number of template parameter lists
/// that were matched against the template-ids occurring into the NNS.
unsigned NumTemplParamLists;
@@ -487,8 +492,7 @@ struct QualifierInfo {
TemplateParameterList** TemplParamLists;
/// Default constructor.
- QualifierInfo()
- : NNS(0), NNSRange(), NumTemplParamLists(0), TemplParamLists(0) {}
+ QualifierInfo() : QualifierLoc(), NumTemplParamLists(0), TemplParamLists(0) {}
/// setTemplateParameterListsInfo - Sets info about matched template
/// parameter lists.
void setTemplateParameterListsInfo(ASTContext &Context,
@@ -545,14 +549,22 @@ public:
return SourceRange(getOuterLocStart(), getLocation());
}
+ /// \brief Retrieve the nested-name-specifier that qualifies the name of this
+ /// declaration, if it was present in the source.
NestedNameSpecifier *getQualifier() const {
- return hasExtInfo() ? getExtInfo()->NNS : 0;
+ return hasExtInfo() ? getExtInfo()->QualifierLoc.getNestedNameSpecifier()
+ : 0;
}
- SourceRange getQualifierRange() const {
- return hasExtInfo() ? getExtInfo()->NNSRange : SourceRange();
+
+ /// \brief Retrieve the nested-name-specifier (with source-location
+ /// information) that qualifies the name of this declaration, if it was
+ /// present in the source.
+ NestedNameSpecifierLoc getQualifierLoc() const {
+ return hasExtInfo() ? getExtInfo()->QualifierLoc
+ : NestedNameSpecifierLoc();
}
- void setQualifierInfo(NestedNameSpecifier *Qualifier,
- SourceRange QualifierRange);
+
+ void setQualifierInfo(NestedNameSpecifierLoc QualifierLoc);
unsigned getNumTemplateParameterLists() const {
return hasExtInfo() ? getExtInfo()->NumTemplParamLists : 0;
@@ -652,10 +664,6 @@ private:
/// slot of its function, enabling the named return value optimization (NRVO).
bool NRVOVariable : 1;
- /// \brief Whether this variable has a deduced C++0x auto type for which we're
- /// currently parsing the initializer.
- bool ParsingAutoInit : 1;
-
friend class StmtIteratorBase;
friend class ASTDeclReader;
@@ -665,7 +673,7 @@ protected:
StorageClass SCAsWritten)
: DeclaratorDecl(DK, DC, L, Id, T, TInfo), Init(),
ThreadSpecified(false), HasCXXDirectInit(false),
- ExceptionVar(false), NRVOVariable(false), ParsingAutoInit(false) {
+ ExceptionVar(false), NRVOVariable(false) {
SClass = SC;
SClassAsWritten = SCAsWritten;
}
@@ -889,18 +897,6 @@ public:
void setInit(Expr *I);
- /// \brief Check whether we are in the process of parsing an initializer
- /// needed to deduce the type of this variable.
- bool isParsingAutoInit() const {
- return ParsingAutoInit;
- }
-
- /// \brief Note whether we are currently parsing an initializer needed to
- /// deduce the type of this variable.
- void setParsingAutoInit(bool P) {
- ParsingAutoInit = P;
- }
-
EvaluatedStmt *EnsureEvaluatedStmt() const {
EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>();
if (!Eval) {
@@ -1050,16 +1046,18 @@ public:
};
class ImplicitParamDecl : public VarDecl {
-protected:
- ImplicitParamDecl(Kind DK, DeclContext *DC, SourceLocation L,
- IdentifierInfo *Id, QualType Tw)
- : VarDecl(DK, DC, L, Id, Tw, /*TInfo=*/0, SC_None, SC_None) {
- setImplicit();
- }
public:
static ImplicitParamDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id,
QualType T);
+
+ ImplicitParamDecl(DeclContext *DC, SourceLocation loc,
+ IdentifierInfo *name, QualType type)
+ : VarDecl(ImplicitParam, DC, loc, name, type,
+ /*tinfo*/ 0, SC_None, SC_None) {
+ setImplicit();
+ }
+
// Implement isa/cast/dyncast/etc.
static bool classof(const ImplicitParamDecl *D) { return true; }
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
@@ -2154,14 +2152,22 @@ public:
void setTypedefForAnonDecl(TypedefDecl *TDD);
+ /// \brief Retrieve the nested-name-specifier that qualifies the name of this
+ /// declaration, if it was present in the source.
NestedNameSpecifier *getQualifier() const {
- return hasExtInfo() ? getExtInfo()->NNS : 0;
+ return hasExtInfo() ? getExtInfo()->QualifierLoc.getNestedNameSpecifier()
+ : 0;
}
- SourceRange getQualifierRange() const {
- return hasExtInfo() ? getExtInfo()->NNSRange : SourceRange();
+
+ /// \brief Retrieve the nested-name-specifier (with source-location
+ /// information) that qualifies the name of this declaration, if it was
+ /// present in the source.
+ NestedNameSpecifierLoc getQualifierLoc() const {
+ return hasExtInfo() ? getExtInfo()->QualifierLoc
+ : NestedNameSpecifierLoc();
}
- void setQualifierInfo(NestedNameSpecifier *Qualifier,
- SourceRange QualifierRange);
+
+ void setQualifierInfo(NestedNameSpecifierLoc QualifierLoc);
unsigned getNumTemplateParameterLists() const {
return hasExtInfo() ? getExtInfo()->NumTemplParamLists : 0;
diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclBase.h b/contrib/llvm/tools/clang/include/clang/AST/DeclBase.h
index bf249ce..b35d134 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/DeclBase.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclBase.h
@@ -299,6 +299,13 @@ public:
return const_cast<Decl*>(this)->getDeclContext();
}
+ /// Finds the innermost non-closure context of this declaration.
+ /// That is, walk out the DeclContext chain, skipping any blocks.
+ DeclContext *getNonClosureContext();
+ const DeclContext *getNonClosureContext() const {
+ return const_cast<Decl*>(this)->getNonClosureContext();
+ }
+
TranslationUnitDecl *getTranslationUnitDecl();
const TranslationUnitDecl *getTranslationUnitDecl() const {
return const_cast<Decl*>(this)->getTranslationUnitDecl();
@@ -787,6 +794,10 @@ public:
return cast<Decl>(this)->getASTContext();
}
+ bool isClosure() const {
+ return DeclKind == Decl::Block;
+ }
+
bool isFunctionOrMethod() const {
switch (DeclKind) {
case Decl::Block:
diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclCXX.h b/contrib/llvm/tools/clang/include/clang/AST/DeclCXX.h
index d11ee8f..1656a7e 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/DeclCXX.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclCXX.h
@@ -1741,13 +1741,8 @@ class UsingDirectiveDecl : public NamedDecl {
/// SourceLocation - Location of 'namespace' token.
SourceLocation NamespaceLoc;
- /// \brief The source range that covers the nested-name-specifier
- /// preceding the namespace name.
- SourceRange QualifierRange;
-
- /// \brief The nested-name-specifier that precedes the namespace
- /// name, if any.
- NestedNameSpecifier *Qualifier;
+ /// \brief The nested-name-specifier that precedes the namespace.
+ NestedNameSpecifierLoc QualifierLoc;
/// NominatedNamespace - Namespace nominated by using-directive.
NamedDecl *NominatedNamespace;
@@ -1765,25 +1760,24 @@ class UsingDirectiveDecl : public NamedDecl {
UsingDirectiveDecl(DeclContext *DC, SourceLocation UsingLoc,
SourceLocation NamespcLoc,
- SourceRange QualifierRange,
- NestedNameSpecifier *Qualifier,
+ NestedNameSpecifierLoc QualifierLoc,
SourceLocation IdentLoc,
NamedDecl *Nominated,
DeclContext *CommonAncestor)
: NamedDecl(UsingDirective, DC, IdentLoc, getName()), UsingLoc(UsingLoc),
- NamespaceLoc(NamespcLoc), QualifierRange(QualifierRange),
- Qualifier(Qualifier), NominatedNamespace(Nominated),
- CommonAncestor(CommonAncestor) {
- }
+ NamespaceLoc(NamespcLoc), QualifierLoc(QualifierLoc),
+ NominatedNamespace(Nominated), CommonAncestor(CommonAncestor) { }
public:
- /// \brief Retrieve the source range of the nested-name-specifier
- /// that qualifies the namespace name.
- SourceRange getQualifierRange() const { return QualifierRange; }
-
+ /// \brief Retrieve the nested-name-specifier that qualifies the
+ /// name of the namespace, with source-location information.
+ NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
+
/// \brief Retrieve the nested-name-specifier that qualifies the
/// name of the namespace.
- NestedNameSpecifier *getQualifier() const { return Qualifier; }
+ NestedNameSpecifier *getQualifier() const {
+ return QualifierLoc.getNestedNameSpecifier();
+ }
NamedDecl *getNominatedNamespaceAsWritten() { return NominatedNamespace; }
const NamedDecl *getNominatedNamespaceAsWritten() const {
@@ -1815,8 +1809,7 @@ public:
static UsingDirectiveDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation UsingLoc,
SourceLocation NamespaceLoc,
- SourceRange QualifierRange,
- NestedNameSpecifier *Qualifier,
+ NestedNameSpecifierLoc QualifierLoc,
SourceLocation IdentLoc,
NamedDecl *Nominated,
DeclContext *CommonAncestor);
@@ -1844,49 +1837,37 @@ class NamespaceAliasDecl : public NamedDecl {
/// \brief The location of the "namespace" keyword.
SourceLocation NamespaceLoc;
- /// \brief The source range that covers the nested-name-specifier
- /// preceding the namespace name.
- SourceRange QualifierRange;
-
- /// \brief The nested-name-specifier that precedes the namespace
- /// name, if any.
- NestedNameSpecifier *Qualifier;
-
/// IdentLoc - Location of namespace identifier. Accessed by TargetNameLoc.
SourceLocation IdentLoc;
-
+
+ /// \brief The nested-name-specifier that precedes the namespace.
+ NestedNameSpecifierLoc QualifierLoc;
+
/// Namespace - The Decl that this alias points to. Can either be a
/// NamespaceDecl or a NamespaceAliasDecl.
NamedDecl *Namespace;
NamespaceAliasDecl(DeclContext *DC, SourceLocation NamespaceLoc,
SourceLocation AliasLoc, IdentifierInfo *Alias,
- SourceRange QualifierRange,
- NestedNameSpecifier *Qualifier,
+ NestedNameSpecifierLoc QualifierLoc,
SourceLocation IdentLoc, NamedDecl *Namespace)
: NamedDecl(NamespaceAlias, DC, AliasLoc, Alias),
- NamespaceLoc(NamespaceLoc), QualifierRange(QualifierRange),
- Qualifier(Qualifier), IdentLoc(IdentLoc), Namespace(Namespace) { }
+ NamespaceLoc(NamespaceLoc), IdentLoc(IdentLoc),
+ QualifierLoc(QualifierLoc), Namespace(Namespace) { }
friend class ASTDeclReader;
public:
- /// \brief Retrieve the source range of the nested-name-specifier
- /// that qualifiers the namespace name.
- SourceRange getQualifierRange() const { return QualifierRange; }
-
- /// \brief Set the source range of the nested-name-specifier that qualifies
- /// the namespace name.
- void setQualifierRange(SourceRange R) { QualifierRange = R; }
-
+ /// \brief Retrieve the nested-name-specifier that qualifies the
+ /// name of the namespace, with source-location information.
+ NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
+
/// \brief Retrieve the nested-name-specifier that qualifies the
/// name of the namespace.
- NestedNameSpecifier *getQualifier() const { return Qualifier; }
-
- /// \brief Set the nested-name-specifier that qualifies the name of the
- /// namespace.
- void setQualifier(NestedNameSpecifier *NNS) { Qualifier = NNS; }
-
+ NestedNameSpecifier *getQualifier() const {
+ return QualifierLoc.getNestedNameSpecifier();
+ }
+
/// \brief Retrieve the namespace declaration aliased by this directive.
NamespaceDecl *getNamespace() {
if (NamespaceAliasDecl *AD = dyn_cast<NamespaceAliasDecl>(Namespace))
@@ -1917,8 +1898,7 @@ public:
SourceLocation NamespaceLoc,
SourceLocation AliasLoc,
IdentifierInfo *Alias,
- SourceRange QualifierRange,
- NestedNameSpecifier *Qualifier,
+ NestedNameSpecifierLoc QualifierLoc,
SourceLocation IdentLoc,
NamedDecl *Namespace);
@@ -2002,15 +1982,11 @@ public:
/// UsingDecl - Represents a C++ using-declaration. For example:
/// using someNameSpace::someIdentifier;
class UsingDecl : public NamedDecl {
- /// \brief The source range that covers the nested-name-specifier
- /// preceding the declaration name.
- SourceRange NestedNameRange;
-
/// \brief The source location of the "using" location itself.
SourceLocation UsingLocation;
- /// \brief Target nested name specifier.
- NestedNameSpecifier* TargetNestedName;
+ /// \brief The nested-name-specifier that precedes the name.
+ NestedNameSpecifierLoc QualifierLoc;
/// DNLoc - Provides source/type location info for the
/// declaration name embedded in the ValueDecl base class.
@@ -2023,37 +1999,34 @@ class UsingDecl : public NamedDecl {
// \brief Has 'typename' keyword.
bool IsTypeName;
- UsingDecl(DeclContext *DC, SourceRange NNR,
- SourceLocation UL, NestedNameSpecifier* TargetNNS,
+ UsingDecl(DeclContext *DC, SourceLocation UL,
+ NestedNameSpecifierLoc QualifierLoc,
const DeclarationNameInfo &NameInfo, bool IsTypeNameArg)
: NamedDecl(Using, DC, NameInfo.getLoc(), NameInfo.getName()),
- NestedNameRange(NNR), UsingLocation(UL), TargetNestedName(TargetNNS),
+ UsingLocation(UL), QualifierLoc(QualifierLoc),
DNLoc(NameInfo.getInfo()), FirstUsingShadow(0),IsTypeName(IsTypeNameArg) {
}
public:
- /// \brief Returns the source range that covers the nested-name-specifier
- /// preceding the namespace name.
- SourceRange getNestedNameRange() const { return NestedNameRange; }
-
- /// \brief Set the source range of the nested-name-specifier.
- void setNestedNameRange(SourceRange R) { NestedNameRange = R; }
-
- // FIXME: Naming is inconsistent with other get*Loc functions.
/// \brief Returns the source location of the "using" keyword.
SourceLocation getUsingLocation() const { return UsingLocation; }
/// \brief Set the source location of the 'using' keyword.
void setUsingLocation(SourceLocation L) { UsingLocation = L; }
- /// \brief Get the target nested name declaration.
- NestedNameSpecifier* getTargetNestedNameDecl() const {
- return TargetNestedName;
+ /// \brief Retrieve the nested-name-specifier that qualifies the name,
+ /// with source-location information.
+ NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
+
+ /// \brief Retrieve the nested-name-specifier that qualifies the name.
+ NestedNameSpecifier *getQualifier() const {
+ return QualifierLoc.getNestedNameSpecifier();
}
- /// \brief Set the target nested name declaration.
- void setTargetNestedNameDecl(NestedNameSpecifier *NNS) {
- TargetNestedName = NNS;
+ /// \brief Retrieve the source range of the nested-name-specifier
+ /// that qualifies the name.
+ SourceRange getQualifierRange() const {
+ return QualifierLoc.getSourceRange();
}
DeclarationNameInfo getNameInfo() const {
@@ -2119,8 +2092,8 @@ public:
void removeShadowDecl(UsingShadowDecl *S);
static UsingDecl *Create(ASTContext &C, DeclContext *DC,
- SourceRange NNR, SourceLocation UsingL,
- NestedNameSpecifier* TargetNNS,
+ SourceLocation UsingL,
+ NestedNameSpecifierLoc QualifierLoc,
const DeclarationNameInfo &NameInfo,
bool IsTypeNameArg);
@@ -2145,61 +2118,55 @@ public:
/// using Base<T>::foo;
/// };
class UnresolvedUsingValueDecl : public ValueDecl {
- /// \brief The source range that covers the nested-name-specifier
- /// preceding the declaration name.
- SourceRange TargetNestedNameRange;
-
/// \brief The source location of the 'using' keyword
SourceLocation UsingLocation;
- NestedNameSpecifier *TargetNestedNameSpecifier;
+ /// \brief The nested-name-specifier that precedes the name.
+ NestedNameSpecifierLoc QualifierLoc;
/// DNLoc - Provides source/type location info for the
/// declaration name embedded in the ValueDecl base class.
DeclarationNameLoc DNLoc;
UnresolvedUsingValueDecl(DeclContext *DC, QualType Ty,
- SourceLocation UsingLoc, SourceRange TargetNNR,
- NestedNameSpecifier *TargetNNS,
+ SourceLocation UsingLoc,
+ NestedNameSpecifierLoc QualifierLoc,
const DeclarationNameInfo &NameInfo)
: ValueDecl(UnresolvedUsingValue, DC,
NameInfo.getLoc(), NameInfo.getName(), Ty),
- TargetNestedNameRange(TargetNNR), UsingLocation(UsingLoc),
- TargetNestedNameSpecifier(TargetNNS), DNLoc(NameInfo.getInfo())
+ UsingLocation(UsingLoc), QualifierLoc(QualifierLoc),
+ DNLoc(NameInfo.getInfo())
{ }
public:
- /// \brief Returns the source range that covers the nested-name-specifier
- /// preceding the namespace name.
- SourceRange getTargetNestedNameRange() const { return TargetNestedNameRange; }
-
- /// \brief Set the source range coverting the nested-name-specifier preceding
- /// the namespace name.
- void setTargetNestedNameRange(SourceRange R) { TargetNestedNameRange = R; }
-
- /// \brief Get target nested name declaration.
- NestedNameSpecifier* getTargetNestedNameSpecifier() const {
- return TargetNestedNameSpecifier;
- }
-
- /// \brief Set the nested name declaration.
- void setTargetNestedNameSpecifier(NestedNameSpecifier* NNS) {
- TargetNestedNameSpecifier = NNS;
- }
-
/// \brief Returns the source location of the 'using' keyword.
SourceLocation getUsingLoc() const { return UsingLocation; }
/// \brief Set the source location of the 'using' keyword.
void setUsingLoc(SourceLocation L) { UsingLocation = L; }
+ /// \brief Retrieve the nested-name-specifier that qualifies the name,
+ /// with source-location information.
+ NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
+
+ /// \brief Retrieve the nested-name-specifier that qualifies the name.
+ NestedNameSpecifier *getQualifier() const {
+ return QualifierLoc.getNestedNameSpecifier();
+ }
+
+ /// \brief Retrieve the source range of the nested-name-specifier
+ /// that qualifies the name.
+ SourceRange getQualifierRange() const {
+ return QualifierLoc.getSourceRange();
+ }
+
DeclarationNameInfo getNameInfo() const {
return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc);
}
static UnresolvedUsingValueDecl *
Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc,
- SourceRange TargetNNR, NestedNameSpecifier *TargetNNS,
+ NestedNameSpecifierLoc QualifierLoc,
const DeclarationNameInfo &NameInfo);
SourceRange getSourceRange() const {
@@ -2224,49 +2191,52 @@ public:
/// The type associated with a unresolved using typename decl is
/// currently always a typename type.
class UnresolvedUsingTypenameDecl : public TypeDecl {
- /// \brief The source range that covers the nested-name-specifier
- /// preceding the declaration name.
- SourceRange TargetNestedNameRange;
-
/// \brief The source location of the 'using' keyword
SourceLocation UsingLocation;
/// \brief The source location of the 'typename' keyword
SourceLocation TypenameLocation;
- NestedNameSpecifier *TargetNestedNameSpecifier;
+ /// \brief The nested-name-specifier that precedes the name.
+ NestedNameSpecifierLoc QualifierLoc;
UnresolvedUsingTypenameDecl(DeclContext *DC, SourceLocation UsingLoc,
- SourceLocation TypenameLoc,
- SourceRange TargetNNR, NestedNameSpecifier *TargetNNS,
- SourceLocation TargetNameLoc, IdentifierInfo *TargetName)
+ SourceLocation TypenameLoc,
+ NestedNameSpecifierLoc QualifierLoc,
+ SourceLocation TargetNameLoc,
+ IdentifierInfo *TargetName)
: TypeDecl(UnresolvedUsingTypename, DC, TargetNameLoc, TargetName),
- TargetNestedNameRange(TargetNNR), UsingLocation(UsingLoc),
- TypenameLocation(TypenameLoc), TargetNestedNameSpecifier(TargetNNS)
- { }
+ UsingLocation(UsingLoc), TypenameLocation(TypenameLoc),
+ QualifierLoc(QualifierLoc) { }
friend class ASTDeclReader;
public:
- /// \brief Returns the source range that covers the nested-name-specifier
- /// preceding the namespace name.
- SourceRange getTargetNestedNameRange() const { return TargetNestedNameRange; }
-
- /// \brief Get target nested name declaration.
- NestedNameSpecifier* getTargetNestedNameSpecifier() {
- return TargetNestedNameSpecifier;
- }
-
/// \brief Returns the source location of the 'using' keyword.
SourceLocation getUsingLoc() const { return UsingLocation; }
/// \brief Returns the source location of the 'typename' keyword.
SourceLocation getTypenameLoc() const { return TypenameLocation; }
+ /// \brief Retrieve the nested-name-specifier that qualifies the name,
+ /// with source-location information.
+ NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
+
+ /// \brief Retrieve the nested-name-specifier that qualifies the name.
+ NestedNameSpecifier *getQualifier() const {
+ return QualifierLoc.getNestedNameSpecifier();
+ }
+
+ /// \brief Retrieve the source range of the nested-name-specifier
+ /// that qualifies the name.
+ SourceRange getQualifierRange() const {
+ return QualifierLoc.getSourceRange();
+ }
+
+ // FIXME: DeclarationNameInfo
static UnresolvedUsingTypenameDecl *
Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc,
- SourceLocation TypenameLoc,
- SourceRange TargetNNR, NestedNameSpecifier *TargetNNS,
+ SourceLocation TypenameLoc, NestedNameSpecifierLoc QualifierLoc,
SourceLocation TargetNameLoc, DeclarationName TargetName);
SourceRange getSourceRange() const {
diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclGroup.h b/contrib/llvm/tools/clang/include/clang/AST/DeclGroup.h
index cb9e168..63cdac5 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/DeclGroup.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclGroup.h
@@ -39,12 +39,12 @@ public:
Decl*& operator[](unsigned i) {
assert (i < NumDecls && "Out-of-bounds access.");
- return *((Decl**) (this+1));
+ return ((Decl**) (this+1))[i];
}
Decl* const& operator[](unsigned i) const {
assert (i < NumDecls && "Out-of-bounds access.");
- return *((Decl* const*) (this+1));
+ return ((Decl* const*) (this+1))[i];
}
};
diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclTemplate.h b/contrib/llvm/tools/clang/include/clang/AST/DeclTemplate.h
index 176c6ba..f41859c 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/DeclTemplate.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclTemplate.h
@@ -48,6 +48,7 @@ class TemplateParameterList {
/// parameter list.
unsigned NumParams;
+protected:
TemplateParameterList(SourceLocation TemplateLoc, SourceLocation LAngleLoc,
NamedDecl **Params, unsigned NumParams,
SourceLocation RAngleLoc);
@@ -107,6 +108,19 @@ public:
}
};
+/// FixedSizeTemplateParameterList - Stores a list of template parameters for a
+/// TemplateDecl and its derived classes. Suitable for creating on the stack.
+template<size_t N>
+class FixedSizeTemplateParameterList : public TemplateParameterList {
+ NamedDecl *Params[N];
+
+public:
+ FixedSizeTemplateParameterList(SourceLocation TemplateLoc, SourceLocation LAngleLoc,
+ NamedDecl **Params, SourceLocation RAngleLoc) :
+ TemplateParameterList(TemplateLoc, LAngleLoc, Params, N, RAngleLoc) {
+ }
+};
+
/// \brief A template argument list.
class TemplateArgumentList {
/// \brief The template argument list.
@@ -914,6 +928,9 @@ class TemplateTypeParmDecl : public TypeDecl {
TypeForDecl = Type.getTypePtrOrNull();
}
+ /// Sema creates these on the stack during auto type deduction.
+ friend class Sema;
+
public:
static TemplateTypeParmDecl *Create(const ASTContext &C, DeclContext *DC,
SourceLocation L, unsigned D, unsigned P,
diff --git a/contrib/llvm/tools/clang/include/clang/AST/Expr.h b/contrib/llvm/tools/clang/include/clang/AST/Expr.h
index a17205c..95bfad5 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/Expr.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/Expr.h
@@ -1843,9 +1843,7 @@ public:
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
- SourceRange getSourceRange() const {
- return SourceRange(getCallee()->getLocStart(), RParenLoc);
- }
+ SourceRange getSourceRange() const;
static bool classof(const Stmt *T) {
return T->getStmtClass() >= firstCallExprConstant &&
diff --git a/contrib/llvm/tools/clang/include/clang/AST/ExprCXX.h b/contrib/llvm/tools/clang/include/clang/AST/ExprCXX.h
index 85ce962..225db3c 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/ExprCXX.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/ExprCXX.h
@@ -108,8 +108,6 @@ public:
/// FIXME: Returns 0 for member pointer call exprs.
CXXRecordDecl *getRecordDecl();
- SourceRange getSourceRange() const;
-
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXMemberCallExprClass;
}
@@ -1333,13 +1331,9 @@ class CXXPseudoDestructorExpr : public Expr {
/// \brief The location of the '.' or '->' operator.
SourceLocation OperatorLoc;
-
+
/// \brief The nested-name-specifier that follows the operator, if present.
- NestedNameSpecifier *Qualifier;
-
- /// \brief The source range that covers the nested-name-specifier, if
- /// present.
- SourceRange QualifierRange;
+ NestedNameSpecifierLoc QualifierLoc;
/// \brief The type that precedes the '::' in a qualified pseudo-destructor
/// expression.
@@ -1356,11 +1350,12 @@ class CXXPseudoDestructorExpr : public Expr {
/// resolve the name.
PseudoDestructorTypeStorage DestroyedType;
+ friend class ASTStmtReader;
+
public:
CXXPseudoDestructorExpr(ASTContext &Context,
Expr *Base, bool isArrow, SourceLocation OperatorLoc,
- NestedNameSpecifier *Qualifier,
- SourceRange QualifierRange,
+ NestedNameSpecifierLoc QualifierLoc,
TypeSourceInfo *ScopeType,
SourceLocation ColonColonLoc,
SourceLocation TildeLoc,
@@ -1368,36 +1363,32 @@ public:
explicit CXXPseudoDestructorExpr(EmptyShell Shell)
: Expr(CXXPseudoDestructorExprClass, Shell),
- Base(0), IsArrow(false), Qualifier(0), ScopeType(0) { }
+ Base(0), IsArrow(false), QualifierLoc(), ScopeType(0) { }
- void setBase(Expr *E) { Base = E; }
Expr *getBase() const { return cast<Expr>(Base); }
/// \brief Determines whether this member expression actually had
/// a C++ nested-name-specifier prior to the name of the member, e.g.,
/// x->Base::foo.
- bool hasQualifier() const { return Qualifier != 0; }
-
- /// \brief If the member name was qualified, retrieves the source range of
- /// the nested-name-specifier that precedes the member name. Otherwise,
- /// returns an empty source range.
- SourceRange getQualifierRange() const { return QualifierRange; }
- void setQualifierRange(SourceRange R) { QualifierRange = R; }
+ bool hasQualifier() const { return QualifierLoc; }
+ /// \brief Retrieves the nested-name-specifier that qualifies the type name,
+ /// with source-location information.
+ NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
+
/// \brief If the member name was qualified, retrieves the
/// nested-name-specifier that precedes the member name. Otherwise, returns
/// NULL.
- NestedNameSpecifier *getQualifier() const { return Qualifier; }
- void setQualifier(NestedNameSpecifier *NNS) { Qualifier = NNS; }
+ NestedNameSpecifier *getQualifier() const {
+ return QualifierLoc.getNestedNameSpecifier();
+ }
/// \brief Determine whether this pseudo-destructor expression was written
/// using an '->' (otherwise, it used a '.').
bool isArrow() const { return IsArrow; }
- void setArrow(bool A) { IsArrow = A; }
/// \brief Retrieve the location of the '.' or '->' operator.
SourceLocation getOperatorLoc() const { return OperatorLoc; }
- void setOperatorLoc(SourceLocation L) { OperatorLoc = L; }
/// \brief Retrieve the scope type in a qualified pseudo-destructor
/// expression.
@@ -1409,16 +1400,13 @@ public:
/// nested-name-specifier. It is stored as the "scope type" of the pseudo-
/// destructor expression.
TypeSourceInfo *getScopeTypeInfo() const { return ScopeType; }
- void setScopeTypeInfo(TypeSourceInfo *Info) { ScopeType = Info; }
/// \brief Retrieve the location of the '::' in a qualified pseudo-destructor
/// expression.
SourceLocation getColonColonLoc() const { return ColonColonLoc; }
- void setColonColonLoc(SourceLocation L) { ColonColonLoc = L; }
/// \brief Retrieve the location of the '~'.
SourceLocation getTildeLoc() const { return TildeLoc; }
- void setTildeLoc(SourceLocation L) { TildeLoc = L; }
/// \brief Retrieve the source location information for the type
/// being destroyed.
@@ -1885,30 +1873,24 @@ public:
/// ("value"). Such expressions will instantiate to a DeclRefExpr once the
/// declaration can be found.
class DependentScopeDeclRefExpr : public Expr {
- /// The name of the entity we will be referencing.
- DeclarationNameInfo NameInfo;
-
- /// QualifierRange - The source range that covers the
- /// nested-name-specifier.
- SourceRange QualifierRange;
-
/// \brief The nested-name-specifier that qualifies this unresolved
/// declaration name.
- NestedNameSpecifier *Qualifier;
+ NestedNameSpecifierLoc QualifierLoc;
+
+ /// The name of the entity we will be referencing.
+ DeclarationNameInfo NameInfo;
/// \brief Whether the name includes explicit template arguments.
bool HasExplicitTemplateArgs;
DependentScopeDeclRefExpr(QualType T,
- NestedNameSpecifier *Qualifier,
- SourceRange QualifierRange,
+ NestedNameSpecifierLoc QualifierLoc,
const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *Args);
public:
static DependentScopeDeclRefExpr *Create(ASTContext &C,
- NestedNameSpecifier *Qualifier,
- SourceRange QualifierRange,
+ NestedNameSpecifierLoc QualifierLoc,
const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *TemplateArgs = 0);
@@ -1918,24 +1900,23 @@ public:
/// \brief Retrieve the name that this expression refers to.
const DeclarationNameInfo &getNameInfo() const { return NameInfo; }
- void setNameInfo(const DeclarationNameInfo &N) { NameInfo = N; }
/// \brief Retrieve the name that this expression refers to.
DeclarationName getDeclName() const { return NameInfo.getName(); }
- void setDeclName(DeclarationName N) { NameInfo.setName(N); }
/// \brief Retrieve the location of the name within the expression.
SourceLocation getLocation() const { return NameInfo.getLoc(); }
- void setLocation(SourceLocation L) { NameInfo.setLoc(L); }
-
- /// \brief Retrieve the source range of the nested-name-specifier.
- SourceRange getQualifierRange() const { return QualifierRange; }
- void setQualifierRange(SourceRange R) { QualifierRange = R; }
+ /// \brief Retrieve the nested-name-specifier that qualifies the
+ /// name, with source location information.
+ NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
+
+
/// \brief Retrieve the nested-name-specifier that qualifies this
/// declaration.
- NestedNameSpecifier *getQualifier() const { return Qualifier; }
- void setQualifier(NestedNameSpecifier *NNS) { Qualifier = NNS; }
+ NestedNameSpecifier *getQualifier() const {
+ return QualifierLoc.getNestedNameSpecifier();
+ }
/// Determines whether this lookup had explicit template arguments.
bool hasExplicitTemplateArgs() const { return HasExplicitTemplateArgs; }
@@ -1986,7 +1967,7 @@ public:
}
SourceRange getSourceRange() const {
- SourceRange Range(QualifierRange.getBegin(), getLocation());
+ SourceRange Range(QualifierLoc.getBeginLoc(), getLocation());
if (hasExplicitTemplateArgs())
Range.setEnd(getRAngleLoc());
return Range;
diff --git a/contrib/llvm/tools/clang/include/clang/AST/NestedNameSpecifier.h b/contrib/llvm/tools/clang/include/clang/AST/NestedNameSpecifier.h
index 99cc1f2..024bf40 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/NestedNameSpecifier.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/NestedNameSpecifier.h
@@ -25,10 +25,12 @@ namespace llvm {
namespace clang {
class ASTContext;
+class NamespaceAliasDecl;
class NamespaceDecl;
class IdentifierInfo;
struct PrintingPolicy;
class Type;
+class TypeLoc;
class LangOptions;
/// \brief Represents a C++ nested name specifier, such as
@@ -41,13 +43,22 @@ class LangOptions;
/// (for dependent names), or the global specifier ('::', must be the
/// first specifier).
class NestedNameSpecifier : public llvm::FoldingSetNode {
+
+ /// \brief Enumeration describing
+ enum StoredSpecifierKind {
+ StoredIdentifier = 0,
+ StoredNamespaceOrAlias = 1,
+ StoredTypeSpec = 2,
+ StoredTypeSpecWithTemplate = 3
+ };
+
/// \brief The nested name specifier that precedes this nested name
/// specifier.
///
/// The pointer is the nested-name-specifier that precedes this
/// one. The integer stores one of the first four values of type
/// SpecifierKind.
- llvm::PointerIntPair<NestedNameSpecifier *, 2> Prefix;
+ llvm::PointerIntPair<NestedNameSpecifier *, 2, StoredSpecifierKind> Prefix;
/// \brief The last component in the nested name specifier, which
/// can be an identifier, a declaration, or a type.
@@ -63,21 +74,23 @@ public:
/// specifier.
enum SpecifierKind {
/// \brief An identifier, stored as an IdentifierInfo*.
- Identifier = 0,
- /// \brief A namespace, stored as a Namespace*.
- Namespace = 1,
+ Identifier,
+ /// \brief A namespace, stored as a NamespaceDecl*.
+ Namespace,
+ /// \brief A namespace alias, stored as a NamespaceAliasDecl*.
+ NamespaceAlias,
/// \brief A type, stored as a Type*.
- TypeSpec = 2,
+ TypeSpec,
/// \brief A type that was preceded by the 'template' keyword,
/// stored as a Type*.
- TypeSpecWithTemplate = 3,
+ TypeSpecWithTemplate,
/// \brief The global specifier '::'. There is no stored value.
- Global = 4
+ Global
};
private:
/// \brief Builds the global specifier.
- NestedNameSpecifier() : Prefix(0, 0), Specifier(0) { }
+ NestedNameSpecifier() : Prefix(0, StoredIdentifier), Specifier(0) { }
/// \brief Copy constructor used internally to clone nested name
/// specifiers.
@@ -108,6 +121,11 @@ public:
NestedNameSpecifier *Prefix,
NamespaceDecl *NS);
+ /// \brief Builds a nested name specifier that names a namespace alias.
+ static NestedNameSpecifier *Create(const ASTContext &Context,
+ NestedNameSpecifier *Prefix,
+ NamespaceAliasDecl *Alias);
+
/// \brief Builds a nested name specifier that names a type.
static NestedNameSpecifier *Create(const ASTContext &Context,
NestedNameSpecifier *Prefix,
@@ -136,16 +154,12 @@ public:
NestedNameSpecifier *getPrefix() const { return Prefix.getPointer(); }
/// \brief Determine what kind of nested name specifier is stored.
- SpecifierKind getKind() const {
- if (Specifier == 0)
- return Global;
- return (SpecifierKind)Prefix.getInt();
- }
+ SpecifierKind getKind() const;
/// \brief Retrieve the identifier stored in this nested name
/// specifier.
IdentifierInfo *getAsIdentifier() const {
- if (Prefix.getInt() == Identifier)
+ if (Prefix.getInt() == StoredIdentifier)
return (IdentifierInfo *)Specifier;
return 0;
@@ -153,17 +167,16 @@ public:
/// \brief Retrieve the namespace stored in this nested name
/// specifier.
- NamespaceDecl *getAsNamespace() const {
- if (Prefix.getInt() == Namespace)
- return (NamespaceDecl *)Specifier;
+ NamespaceDecl *getAsNamespace() const;
- return 0;
- }
+ /// \brief Retrieve the namespace alias stored in this nested name
+ /// specifier.
+ NamespaceAliasDecl *getAsNamespaceAlias() const;
/// \brief Retrieve the type stored in this nested name specifier.
const Type *getAsType() const {
- if (Prefix.getInt() == TypeSpec ||
- Prefix.getInt() == TypeSpecWithTemplate)
+ if (Prefix.getInt() == StoredTypeSpec ||
+ Prefix.getInt() == StoredTypeSpecWithTemplate)
return (const Type *)Specifier;
return 0;
@@ -191,6 +204,114 @@ public:
void dump(const LangOptions &LO);
};
+/// \brief A C++ nested-name-specifier augmented with source location
+/// information.
+class NestedNameSpecifierLoc {
+ NestedNameSpecifier *Qualifier;
+ void *Data;
+
+ /// \brief Determines the data length for the last component in the
+ /// given nested-name-specifier.
+ static unsigned getLocalDataLength(NestedNameSpecifier *Qualifier);
+
+ /// \brief Determines the data length for the entire
+ /// nested-name-specifier.
+ static unsigned getDataLength(NestedNameSpecifier *Qualifier);
+
+public:
+ /// \brief Construct an empty nested-name-specifier.
+ NestedNameSpecifierLoc() : Qualifier(0), Data(0) { }
+
+ /// \brief Construct a nested-name-specifier with source location information
+ /// from
+ NestedNameSpecifierLoc(NestedNameSpecifier *Qualifier, void *Data)
+ : Qualifier(Qualifier), Data(Data) { }
+
+ /// \brief Evalutes true when this nested-name-specifier location is
+ /// non-empty.
+ operator bool() const { return Qualifier; }
+
+ /// \brief Retrieve the nested-name-specifier to which this instance
+ /// refers.
+ NestedNameSpecifier *getNestedNameSpecifier() const {
+ return Qualifier;
+ }
+
+ /// \brief Retrieve the opaque pointer that refers to source-location data.
+ void *getOpaqueData() const { return Data; }
+
+ /// \brief Retrieve the source range covering the entirety of this
+ /// nested-name-specifier.
+ ///
+ /// For example, if this instance refers to a nested-name-specifier
+ /// \c ::std::vector<int>::, the returned source range would cover
+ /// from the initial '::' to the last '::'.
+ SourceRange getSourceRange() const;
+
+ /// \brief Retrieve the source range covering just the last part of
+ /// this nested-name-specifier, not including the prefix.
+ ///
+ /// For example, if this instance refers to a nested-name-specifier
+ /// \c ::std::vector<int>::, the returned source range would cover
+ /// from "vector" to the last '::'.
+ SourceRange getLocalSourceRange() const;
+
+ /// \brief Retrieve the location of the beginning of this
+ /// nested-name-specifier.
+ SourceLocation getBeginLoc() const {
+ return getSourceRange().getBegin();
+ }
+
+ /// \brief Retrieve the location of the end of this
+ /// nested-name-specifier.
+ SourceLocation getEndLoc() const {
+ return getSourceRange().getEnd();
+ }
+
+ /// \brief Retrieve the location of the beginning of this
+ /// component of the nested-name-specifier.
+ SourceLocation getLocalBeginLoc() const {
+ return getLocalSourceRange().getBegin();
+ }
+
+ /// \brief Retrieve the location of the end of this component of the
+ /// nested-name-specifier.
+ SourceLocation getLocalEndLoc() const {
+ return getLocalSourceRange().getEnd();
+ }
+
+ /// \brief Return the prefix of this nested-name-specifier.
+ ///
+ /// For example, if this instance refers to a nested-name-specifier
+ /// \c ::std::vector<int>::, the prefix is \c ::std::. Note that the
+ /// returned prefix may be empty, if this is the first component of
+ /// the nested-name-specifier.
+ NestedNameSpecifierLoc getPrefix() const {
+ if (!Qualifier)
+ return *this;
+
+ return NestedNameSpecifierLoc(Qualifier->getPrefix(), Data);
+ }
+
+ /// \brief For a nested-name-specifier that refers to a type,
+ /// retrieve the type with source-location information.
+ TypeLoc getTypeLoc() const;
+
+ /// \brief Determines the data length for the entire
+ /// nested-name-specifier.
+ unsigned getDataLength() const { return getDataLength(Qualifier); }
+
+ friend bool operator==(NestedNameSpecifierLoc X,
+ NestedNameSpecifierLoc Y) {
+ return X.Qualifier == Y.Qualifier && X.Data == Y.Data;
+ }
+
+ friend bool operator!=(NestedNameSpecifierLoc X,
+ NestedNameSpecifierLoc Y) {
+ return !(X == Y);
+ }
+};
+
/// Insertion operator for diagnostics. This allows sending NestedNameSpecifiers
/// into a diagnostic with <<.
inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
diff --git a/contrib/llvm/tools/clang/include/clang/AST/RecursiveASTVisitor.h b/contrib/llvm/tools/clang/include/clang/AST/RecursiveASTVisitor.h
index 921b799..e85b6dc 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -181,6 +181,12 @@ public:
/// \returns false if the visitation was terminated early, true otherwise.
bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS);
+ /// \brief Recursively visit a C++ nested-name-specifier with location
+ /// information.
+ ///
+ /// \returns false if the visitation was terminated early, true otherwise.
+ bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS);
+
/// \brief Recursively visit a template name and dispatch to the
/// appropriate method.
///
@@ -502,6 +508,7 @@ bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifier(
switch (NNS->getKind()) {
case NestedNameSpecifier::Identifier:
case NestedNameSpecifier::Namespace:
+ case NestedNameSpecifier::NamespaceAlias:
case NestedNameSpecifier::Global:
return true;
@@ -514,6 +521,31 @@ bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifier(
}
template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifierLoc(
+ NestedNameSpecifierLoc NNS) {
+ if (!NNS)
+ return true;
+
+ if (NestedNameSpecifierLoc Prefix = NNS.getPrefix())
+ TRY_TO(TraverseNestedNameSpecifierLoc(Prefix));
+
+ switch (NNS.getNestedNameSpecifier()->getKind()) {
+ case NestedNameSpecifier::Identifier:
+ case NestedNameSpecifier::Namespace:
+ case NestedNameSpecifier::NamespaceAlias:
+ case NestedNameSpecifier::Global:
+ return true;
+
+ case NestedNameSpecifier::TypeSpec:
+ case NestedNameSpecifier::TypeSpecWithTemplate:
+ TRY_TO(TraverseTypeLoc(NNS.getTypeLoc()));
+ break;
+ }
+
+ return true;
+}
+
+template<typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseTemplateName(TemplateName Template) {
if (DependentTemplateName *DTN = Template.getAsDependentTemplateName())
TRY_TO(TraverseNestedNameSpecifier(DTN->getQualifier()));
@@ -1142,11 +1174,11 @@ DEF_TRAVERSE_DECL(ObjCPropertyDecl, {
})
DEF_TRAVERSE_DECL(UsingDecl, {
- TRY_TO(TraverseNestedNameSpecifier(D->getTargetNestedNameDecl()));
+ TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
})
DEF_TRAVERSE_DECL(UsingDirectiveDecl, {
- TRY_TO(TraverseNestedNameSpecifier(D->getQualifier()));
+ TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
})
DEF_TRAVERSE_DECL(UsingShadowDecl, { })
@@ -1312,7 +1344,7 @@ DEF_TRAVERSE_DECL(TypedefDecl, {
DEF_TRAVERSE_DECL(UnresolvedUsingTypenameDecl, {
// A dependent using declaration which was marked with 'typename'.
// template<class T> class A : public B<T> { using typename B<T>::foo; };
- TRY_TO(TraverseNestedNameSpecifier(D->getTargetNestedNameSpecifier()));
+ TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
// We shouldn't traverse D->getTypeForDecl(); it's a result of
// declaring the type, not something that was written in the
// source.
@@ -1425,7 +1457,7 @@ DEF_TRAVERSE_DECL(EnumConstantDecl, {
DEF_TRAVERSE_DECL(UnresolvedUsingValueDecl, {
// Like UnresolvedUsingTypenameDecl, but without the 'typename':
// template <class T> Class A : public Base<T> { using Base<T>::foo; };
- TRY_TO(TraverseNestedNameSpecifier(D->getTargetNestedNameSpecifier()));
+ TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
})
DEF_TRAVERSE_DECL(IndirectFieldDecl, {})
@@ -1660,20 +1692,18 @@ DEF_TRAVERSE_STMT(CXXDependentScopeMemberExpr, {
})
DEF_TRAVERSE_STMT(DeclRefExpr, {
+ TRY_TO(TraverseNestedNameSpecifier(S->getQualifier()));
TRY_TO(TraverseTemplateArgumentLocsHelper(
S->getTemplateArgs(), S->getNumTemplateArgs()));
- // FIXME: Should we be recursing on the qualifier?
- TRY_TO(TraverseNestedNameSpecifier(S->getQualifier()));
})
DEF_TRAVERSE_STMT(DependentScopeDeclRefExpr, {
- // FIXME: Should we be recursing on these two things?
+ TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
if (S->hasExplicitTemplateArgs()) {
TRY_TO(TraverseTemplateArgumentLocsHelper(
S->getExplicitTemplateArgs().getTemplateArgs(),
S->getNumTemplateArgs()));
}
- TRY_TO(TraverseNestedNameSpecifier(S->getQualifier()));
})
DEF_TRAVERSE_STMT(MemberExpr, {
@@ -1814,7 +1844,7 @@ DEF_TRAVERSE_STMT(CXXDeleteExpr, { })
DEF_TRAVERSE_STMT(ExprWithCleanups, { })
DEF_TRAVERSE_STMT(CXXNullPtrLiteralExpr, { })
DEF_TRAVERSE_STMT(CXXPseudoDestructorExpr, {
- TRY_TO(TraverseNestedNameSpecifier(S->getQualifier()));
+ TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
if (TypeSourceInfo *ScopeInfo = S->getScopeTypeInfo())
TRY_TO(TraverseTypeLoc(ScopeInfo->getTypeLoc()));
if (TypeSourceInfo *DestroyedTypeInfo = S->getDestroyedTypeInfo())
diff --git a/contrib/llvm/tools/clang/include/clang/AST/Stmt.h b/contrib/llvm/tools/clang/include/clang/AST/Stmt.h
index 7ede9ce..d1f7d66 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/Stmt.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/Stmt.h
@@ -1328,7 +1328,8 @@ public:
}
Expr *getInputExpr(unsigned i);
-
+ void setInputExpr(unsigned i, Expr *E);
+
const Expr *getInputExpr(unsigned i) const {
return const_cast<AsmStmt*>(this)->getInputExpr(i);
}
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h
new file mode 100644
index 0000000..72f644a
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h
@@ -0,0 +1,49 @@
+//==- CFGReachabilityAnalysis.h - Basic reachability analysis ----*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a flow-sensitive, (mostly) path-insensitive reachability
+// analysis based on Clang's CFGs. Clients can query if a given basic block
+// is reachable within the CFG.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_ANALYSIS_CFG_REACHABILITY
+#define CLANG_ANALYSIS_CFG_REACHABILITY
+
+#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/DenseMap.h"
+
+namespace clang {
+
+class CFG;
+class CFGBlock;
+
+// A class that performs reachability queries for CFGBlocks. Several internal
+// checks in this checker require reachability information. The requests all
+// tend to have a common destination, so we lazily do a predecessor search
+// from the destination node and cache the results to prevent work
+// duplication.
+class CFGReachabilityAnalysis {
+ typedef llvm::BitVector ReachableSet;
+ typedef llvm::DenseMap<unsigned, ReachableSet> ReachableMap;
+ ReachableSet analyzed;
+ ReachableMap reachable;
+public:
+ CFGReachabilityAnalysis(const CFG &cfg);
+
+ /// Returns true if the block 'Dst' can be reached from block 'Src'.
+ bool isReachable(const CFGBlock *Src, const CFGBlock *Dst);
+
+private:
+ void mapReachability(const CFGBlock *Dst);
+};
+
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/AnalysisContext.h b/contrib/llvm/tools/clang/include/clang/Analysis/AnalysisContext.h
index 2ecbfdc..8514514 100644
--- a/contrib/llvm/tools/clang/include/clang/Analysis/AnalysisContext.h
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/AnalysisContext.h
@@ -29,6 +29,8 @@ class Decl;
class Stmt;
class CFG;
class CFGBlock;
+class CFGReachabilityAnalysis;
+class CFGStmtMap;
class LiveVariables;
class ParentMap;
class PseudoConstantAnalysis;
@@ -48,11 +50,13 @@ class AnalysisContext {
// AnalysisContext owns the following data.
CFG *cfg, *completeCFG;
+ CFGStmtMap *cfgStmtMap;
bool builtCFG, builtCompleteCFG;
LiveVariables *liveness;
LiveVariables *relaxedLiveness;
ParentMap *PM;
PseudoConstantAnalysis *PCA;
+ CFGReachabilityAnalysis *CFA;
llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars;
llvm::BumpPtrAllocator A;
bool UseUnoptimizedCFG;
@@ -65,9 +69,9 @@ public:
bool addehedges = false,
bool addImplicitDtors = false,
bool addInitializers = false)
- : D(d), TU(tu), cfg(0), completeCFG(0),
+ : D(d), TU(tu), cfg(0), completeCFG(0), cfgStmtMap(0),
builtCFG(false), builtCompleteCFG(false),
- liveness(0), relaxedLiveness(0), PM(0), PCA(0),
+ liveness(0), relaxedLiveness(0), PM(0), PCA(0), CFA(0),
ReferencedBlockVars(0), UseUnoptimizedCFG(useUnoptimizedCFG),
AddEHEdges(addehedges), AddImplicitDtors(addImplicitDtors),
AddInitializers(addInitializers) {}
@@ -91,7 +95,11 @@ public:
Stmt *getBody();
CFG *getCFG();
+
+ CFGStmtMap *getCFGStmtMap();
+ CFGReachabilityAnalysis *getCFGReachablityAnalysis();
+
/// Return a version of the CFG without any edges pruned.
CFG *getUnoptimizedCFG();
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Builtins.def b/contrib/llvm/tools/clang/include/clang/Basic/Builtins.def
index 7d270ad..b73ac1f 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/Builtins.def
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Builtins.def
@@ -60,6 +60,7 @@
// n -> nothrow
// r -> noreturn
// c -> const
+// t -> signature is meaningless, use custom typechecking
// F -> this is a libc/libm function with a '__builtin_' prefix added.
// f -> this is a libc/libm function without the '__builtin_' prefix. It can
// be followed by ':headername:' to state which header this function
@@ -383,8 +384,8 @@ BUILTIN(__builtin_bswap32, "UiUi", "nc")
BUILTIN(__builtin_bswap64, "ULLiULLi", "nc")
// Random GCC builtins
-BUILTIN(__builtin_constant_p, "i.", "nc")
-BUILTIN(__builtin_classify_type, "i.", "nc")
+BUILTIN(__builtin_constant_p, "i.", "nct")
+BUILTIN(__builtin_classify_type, "i.", "nct")
BUILTIN(__builtin___CFStringMakeConstantString, "FC*cC*", "nc")
BUILTIN(__builtin___NSStringMakeConstantString, "FC*cC*", "nc")
BUILTIN(__builtin_va_start, "vA.", "n")
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Builtins.h b/contrib/llvm/tools/clang/include/clang/Basic/Builtins.h
index 4df4c8f..0d17e03 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/Builtins.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Builtins.h
@@ -117,6 +117,11 @@ public:
return strchr(GetRecord(ID).Attributes, 'f') != 0;
}
+ /// \brief Determines whether this builtin has custom typechecking.
+ bool hasCustomTypechecking(unsigned ID) const {
+ return strchr(GetRecord(ID).Attributes, 't') != 0;
+ }
+
/// \brief Completely forget that the given ID was ever considered a builtin,
/// e.g., because the user provided a conflicting signature.
void ForgetBuiltin(unsigned ID, IdentifierTable &Table);
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.h b/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.h
index 19e7c91..3fc60d1 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.h
@@ -474,8 +474,9 @@ public:
///
/// \param Loc The source location we are interested in finding out the
/// diagnostic state. Can be null in order to query the latest state.
- Level getDiagnosticLevel(unsigned DiagID, SourceLocation Loc) const {
- return (Level)Diags->getDiagnosticLevel(DiagID, Loc, *this);
+ Level getDiagnosticLevel(unsigned DiagID, SourceLocation Loc,
+ diag::Mapping *mapping = 0) const {
+ return (Level)Diags->getDiagnosticLevel(DiagID, Loc, *this, mapping);
}
/// Report - Issue the message to the client. @c DiagID is a member of the
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticFrontendKinds.td
index 5f9f4a7..3070676 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -177,12 +177,15 @@ def warn_pch_elide_constructors : Error<
def warn_pch_exceptions : Error<
"exceptions were %select{disabled|enabled}0 in PCH file but "
"are currently %select{disabled|enabled}1">;
-def warn_pch_sjlj_exceptions : Error<
- "sjlj-exceptions were %select{disabled|enabled}0 in PCH file but "
- "are currently %select{disabled|enabled}1">;
def warn_pch_objc_exceptions : Error<
"Objective-C exceptions were %select{disabled|enabled}0 in PCH file but "
"are currently %select{disabled|enabled}1">;
+def warn_pch_cxx_exceptions : Error<
+ "C++ exceptions were %select{disabled|enabled}0 in PCH file but "
+ "are currently %select{disabled|enabled}1">;
+def warn_pch_sjlj_exceptions : Error<
+ "sjlj-exceptions were %select{disabled|enabled}0 in PCH file but "
+ "are currently %select{disabled|enabled}1">;
def warn_pch_objc_runtime : Error<
"PCH file was compiled with the %select{NeXT|GNU}0 runtime but the "
"%select{NeXT|GNU}1 runtime is selected">;
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticGroups.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticGroups.td
index d4377c9..412fb58 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticGroups.td
@@ -198,9 +198,11 @@ def Unused : DiagGroup<"unused",
DiagCategory<"Unused Entity Issue">;
// Format settings.
-def Format : DiagGroup<"format", [FormatExtraArgs, FormatZeroLength, NonNull]>,
+def FormatSecurity : DiagGroup<"format-security">;
+def Format : DiagGroup<"format",
+ [FormatExtraArgs, FormatZeroLength, NonNull,
+ FormatSecurity]>,
DiagCategory<"Format String Issue">;
-def FormatSecurity : DiagGroup<"format-security", [Format]>;
def FormatNonLiteral : DiagGroup<"format-nonliteral", [FormatSecurity]>;
def FormatY2K : DiagGroup<"format-y2k", [Format]>;
def Format2 : DiagGroup<"format=2",
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticIDs.h b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticIDs.h
index b463805..2b03cae 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticIDs.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticIDs.h
@@ -188,14 +188,16 @@ private:
/// \param Loc The source location we are interested in finding out the
/// diagnostic state. Can be null in order to query the latest state.
DiagnosticIDs::Level getDiagnosticLevel(unsigned DiagID, SourceLocation Loc,
- const Diagnostic &Diag) const;
+ const Diagnostic &Diag,
+ diag::Mapping *mapping = 0) const;
/// getDiagnosticLevel - This is an internal implementation helper used when
/// DiagClass is already known.
DiagnosticIDs::Level getDiagnosticLevel(unsigned DiagID,
unsigned DiagClass,
SourceLocation Loc,
- const Diagnostic &Diag) const;
+ const Diagnostic &Diag,
+ diag::Mapping *mapping = 0) const;
/// ProcessDiag - This is the method used to report a diagnostic that is
/// finally fully formed.
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticParseKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticParseKinds.td
index 9d7ec9d..9a68af9 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -28,6 +28,10 @@ def ext_extra_struct_semi : Extension<
def ext_extra_ivar_semi : Extension<
"extra ';' inside instance variable list">;
+def auto_storage_class : ExtWarn<
+ "'auto' storage class specifier is redundant and will be "
+ "removed in future releases">;
+
def ext_duplicate_declspec : Extension<"duplicate '%0' declaration specifier">;
def ext_plain_complex : ExtWarn<
"plain '_Complex' requires a type specifier; assuming '_Complex double'">;
@@ -57,6 +61,11 @@ def ext_enumerator_list_comma : Extension<
"feature">;
def err_enumerator_list_missing_comma : Error<
"missing ',' between enumerators">;
+def err_enumerator_unnamed_no_def : Error<
+ "unnamed enumeration must be a definition">;
+def ext_ms_enum_fixed_underlying_type : Extension<
+ "enumeration types with a fixed underlying type are a Microsoft extension">,
+ InGroup<Microsoft>;
def ext_gnu_indirect_goto : Extension<
"use of GNU indirect-goto extension">, InGroup<GNU>;
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 2e7f274..a9fb2da 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -351,12 +351,18 @@ def note_required_for_protocol_at :
def warn_conflicting_ret_types : Warning<
"conflicting return type in implementation of %0: %1 vs %2">;
+def warn_conflicting_ret_type_modifiers : Warning<
+ "conflicting distributed object modifiers on return type "
+ "in implementation of %0">;
def warn_non_covariant_ret_types : Warning<
"conflicting return type in implementation of %0: %1 vs %2">,
InGroup<DiagGroup<"method-signatures">>, DefaultIgnore;
def warn_conflicting_param_types : Warning<
"conflicting parameter types in implementation of %0: %1 vs %2">;
+def warn_conflicting_param_modifiers : Warning<
+ "conflicting distributed object modifiers on parameter type "
+ "in implementation of %0">;
def warn_non_contravariant_param_types : Warning<
"conflicting parameter types in implementation of %0: %1 vs %2">,
InGroup<DiagGroup<"method-signatures">>, DefaultIgnore;
@@ -898,7 +904,8 @@ def err_new_array_of_auto : Error<
def err_auto_not_allowed : Error<
"'auto' not allowed %select{in function prototype|in struct member"
"|in union member|in class member|in exception declaration"
- "|in template parameter|in block literal|in template argument|here}0">;
+ "|in template parameter|in block literal|in template argument"
+ "|in typedef|in function return type|here}0">;
def err_auto_var_requires_init : Error<
"declaration of variable %0 with type %1 requires an initializer">;
def err_auto_new_requires_ctor_arg : Error<
@@ -911,6 +918,8 @@ def err_auto_missing_trailing_return : Error<
"'auto' return without trailing return type">;
def err_trailing_return_without_auto : Error<
"function with trailing return type must specify return type 'auto', not %0">;
+def err_trailing_return_in_parens : Error<
+ "trailing return type may not be nested within parentheses">;
def err_auto_var_deduction_failure : Error<
"variable %0 with type %1 has incompatible initializer of type %2">;
def err_auto_new_deduction_failure : Error<
@@ -1145,6 +1154,9 @@ def warn_impcast_literal_float_to_integer : Warning<
"implicit conversion turns literal floating-point number into integer: "
"%0 to %1">,
InGroup<DiagGroup<"literal-conversion">>, DefaultIgnore;
+def warn_impcast_different_enum_types : Warning<
+ "implicit conversion from enumeration type %0 to different enumeration type "
+ "%1">, InGroup<DiagGroup<"conversion">>;
def warn_cast_align : Warning<
"cast from %0 to %1 increases required alignment from %2 to %3">,
@@ -1299,11 +1311,11 @@ def err_ovl_no_viable_member_function_in_call : Error<
def err_ovl_ambiguous_call : Error<
"call to %0 is ambiguous">;
def err_ovl_deleted_call : Error<
- "call to %select{unavailable|deleted}0 function %1">;
+ "call to %select{unavailable|deleted}0 function %1 %2">;
def err_ovl_ambiguous_member_call : Error<
"call to member function %0 is ambiguous">;
def err_ovl_deleted_member_call : Error<
- "call to %select{unavailable|deleted}0 member function %1">;
+ "call to %select{unavailable|deleted}0 member function %1 %2">;
def note_ovl_too_many_candidates : Note<
"remaining %0 candidate%s0 omitted; "
"pass -fshow-overloads=all to show them">;
@@ -1455,7 +1467,7 @@ def err_ovl_ambiguous_oper_binary : Error<
"use of overloaded operator '%0' is ambiguous (with operand types %1 and %2)">;
def err_ovl_no_viable_oper : Error<"no viable overloaded '%0'">;
def err_ovl_deleted_oper : Error<
- "overload resolution selected %select{unavailable|deleted}0 operator '%1'">;
+ "overload resolution selected %select{unavailable|deleted}0 operator '%1' %2">;
def err_ovl_no_viable_subscript :
Error<"no viable overloaded operator[] for type %0">;
def err_ovl_no_oper :
@@ -1469,7 +1481,7 @@ def err_ovl_no_viable_object_call : Error<
def err_ovl_ambiguous_object_call : Error<
"call to object of type %0 is ambiguous">;
def err_ovl_deleted_object_call : Error<
- "call to %select{unavailable|deleted}0 function call operator in type %1">;
+ "call to %select{unavailable|deleted}0 function call operator in type %1 %2">;
def note_ovl_surrogate_cand : Note<"conversion candidate of type %0">;
def err_member_call_without_object : Error<
"call to non-static member function without an object argument">;
@@ -2015,9 +2027,10 @@ def err_redefinition_extern_inline : Error<
// This should eventually be an error.
def warn_undefined_internal : Warning<
- "%select{function|variable}0 %q1 has internal linkage but is not defined">;
+ "%select{function|variable}0 %q1 has internal linkage but is not defined">,
+ DiagGroup<"undefined-internal">;
def note_used_here : Note<"used here">;
-
+
def warn_redefinition_of_typedef : Warning<
"redefinition of typedef %0 is invalid in C">,
InGroup<DiagGroup<"typedef-redefinition"> >, DefaultError;
@@ -2328,6 +2341,13 @@ def warn_division_by_zero : Warning<"division by zero is undefined">;
def warn_remainder_by_zero : Warning<"remainder by zero is undefined">;
def warn_shift_negative : Warning<"shift count is negative">;
def warn_shift_gt_typewidth : Warning<"shift count >= width of type">;
+def warn_shift_result_gt_typewidth : Warning<
+ "shift result (%0) requires %1 bits to represent, but %2 only has %3 bits">,
+ InGroup<DiagGroup<"shift-overflow">>;
+def warn_shift_result_overrides_sign_bit : Warning<
+ "shift result (%0) overrides the sign bit of the shift expression's type "
+ "(%1) and becomes negative">,
+ InGroup<DiagGroup<"shift-sign-overflow">>, DefaultIgnore;
def warn_precedence_bitwise_rel : Warning<
"%0 has lower precedence than %1; %1 will be evaluated first">,
@@ -2387,13 +2407,10 @@ def err_typecheck_member_reference_type : Error<
def err_typecheck_member_reference_unknown : Error<
"cannot refer to member %0 in %1 with '%select{.|->}2'">;
def err_member_reference_needs_call : Error<
- "base of member reference is an overloaded function; perhaps you meant "
- "to call %select{it|the 0-argument overload}0?">;
+ "base of member reference is %select{a function|an overloaded function}0; "
+ "perhaps you meant to call it%select{| with no arguments}1?">;
def note_member_ref_possible_intended_overload : Note<
"possibly valid overload here">;
-def err_member_reference_needs_call_zero_arg : Error<
- "base of member reference has function type %0; perhaps you meant to call "
- "this function with '()'?">;
def warn_subscript_is_char : Warning<"array subscript is of type 'char'">,
InGroup<CharSubscript>, DefaultIgnore;
@@ -2452,6 +2469,13 @@ def err_typecheck_incomplete_array_needs_initializer : Error<
def err_array_init_not_init_list : Error<
"array initializer must be an initializer "
"list%select{| or string literal}0">;
+def err_array_init_different_type : Error<
+ "cannot initialize array of type %0 with array of type %1">;
+def err_array_init_non_constant_array : Error<
+ "cannot initialize array of type %0 with non-constant array of type %1">;
+def ext_array_init_copy : Extension<
+ "initialization of an array of type %0 from a compound literal of type %1 is "
+ "a GNU extension">;
def warn_deprecated_string_literal_conversion : Warning<
"conversion from string literal to %0 is deprecated">, InGroup<DeprecatedWritableStr>;
def err_realimag_invalid_type : Error<"invalid type %0 to %1 operator">;
@@ -2950,10 +2974,7 @@ def note_equality_comparison_silence : Note<
def warn_synthesized_ivar_access : Warning<
"direct access of synthesized ivar by using property access %0">,
InGroup<NonfragileAbi2>, DefaultIgnore;
-def warn_ivar_variable_conflict : Warning<
- "when default property synthesis is on, "
- "%0 lookup will access property ivar instead of global variable">,
- InGroup<NonfragileAbi2>;
+
def note_global_declared_at : Note<"global variable declared here">;
// assignment related diagnostics (also for argument passing, returning, etc).
@@ -3108,6 +3129,8 @@ def err_kern_type_not_void_return : Error<
"kernel function type %0 must have void return type">;
def err_config_scalar_return : Error<
"CUDA special function 'cudaConfigureCall' must have scalar return type">;
+def err_kern_call_not_global_function : Error<
+ "kernel call to non-global function %0">;
def err_cannot_pass_objc_interface_to_vararg : Error<
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.h b/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.h
index b148943..a9fd25c 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.h
@@ -53,8 +53,9 @@ public:
unsigned LaxVectorConversions : 1;
unsigned AltiVec : 1; // Support AltiVec-style vector initializers.
unsigned Exceptions : 1; // Support exception handling.
- unsigned SjLjExceptions : 1; // Use setjmp-longjump exception handling.
unsigned ObjCExceptions : 1; // Support Objective-C exceptions.
+ unsigned CXXExceptions : 1; // Support C++ exceptions.
+ unsigned SjLjExceptions : 1; // Use setjmp-longjump exception handling.
unsigned RTTI : 1; // Support RTTI information.
unsigned MSBitfields : 1; // MS-compatible structure layout
@@ -166,8 +167,8 @@ public:
NoConstantCFStrings = 0; InlineVisibilityHidden = 0;
C99 = Microsoft = Borland = CPlusPlus = CPlusPlus0x = 0;
CXXOperatorNames = PascalStrings = WritableStrings = ConstStrings = 0;
- Exceptions = SjLjExceptions = Freestanding = NoBuiltin = 0;
- ObjCExceptions = 1;
+ Exceptions = ObjCExceptions = CXXExceptions = SjLjExceptions = 0;
+ Freestanding = NoBuiltin = 0;
MSBitfields = 0;
NeXTRuntime = 1;
RTTI = 1;
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/PartialDiagnostic.h b/contrib/llvm/tools/clang/include/clang/Basic/PartialDiagnostic.h
index d00195b..c636194 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/PartialDiagnostic.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/PartialDiagnostic.h
@@ -75,7 +75,7 @@ public:
/// \brief An allocator for Storage objects, which uses a small cache to
/// objects, used to reduce malloc()/free() traffic for partial diagnostics.
class StorageAllocator {
- static const unsigned NumCached = 4;
+ static const unsigned NumCached = 16;
Storage Cached[NumCached];
Storage *FreeList[NumCached];
unsigned NumFreeListEntries;
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/SourceManager.h b/contrib/llvm/tools/clang/include/clang/Basic/SourceManager.h
index c0fbd08..b1443da 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/SourceManager.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/SourceManager.h
@@ -684,10 +684,10 @@ public:
/// before calling this method.
unsigned getColumnNumber(FileID FID, unsigned FilePos,
bool *Invalid = 0) const;
- unsigned getSpellingColumnNumber(SourceLocation Loc,
- bool *Invalid = 0) const;
+ unsigned getSpellingColumnNumber(SourceLocation Loc, bool *Invalid = 0) const;
unsigned getInstantiationColumnNumber(SourceLocation Loc,
bool *Invalid = 0) const;
+ unsigned getPresumedColumnNumber(SourceLocation Loc, bool *Invalid = 0) const;
/// getLineNumber - Given a SourceLocation, return the spelling line number
@@ -695,10 +695,10 @@ public:
/// line offsets for the MemoryBuffer, so this is not cheap: use only when
/// about to emit a diagnostic.
unsigned getLineNumber(FileID FID, unsigned FilePos, bool *Invalid = 0) const;
-
+ unsigned getSpellingLineNumber(SourceLocation Loc, bool *Invalid = 0) const;
unsigned getInstantiationLineNumber(SourceLocation Loc,
bool *Invalid = 0) const;
- unsigned getSpellingLineNumber(SourceLocation Loc, bool *Invalid = 0) const;
+ unsigned getPresumedLineNumber(SourceLocation Loc, bool *Invalid = 0) const;
/// Return the filename or buffer identifier of the buffer the location is in.
/// Note that this name does not respect #line directives. Use getPresumedLoc
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/CC1Options.td b/contrib/llvm/tools/clang/include/clang/Driver/CC1Options.td
index 57107ba..186ba9b 100644
--- a/contrib/llvm/tools/clang/include/clang/Driver/CC1Options.td
+++ b/contrib/llvm/tools/clang/include/clang/Driver/CC1Options.td
@@ -73,9 +73,6 @@ def analyzer_display_progress : Flag<"-analyzer-display-progress">,
HelpText<"Emit verbose output about the analyzer's progress">;
def analyzer_experimental_checks : Flag<"-analyzer-experimental-checks">,
HelpText<"Use experimental path-sensitive checks">;
-def analyzer_experimental_internal_checks :
- Flag<"-analyzer-experimental-internal-checks">,
- HelpText<"Use new default path-sensitive checks currently in testing">;
def analyze_function : Separate<"-analyze-function">,
HelpText<"Run analysis on specific function">;
def analyze_function_EQ : Joined<"-analyze-function=">, Alias<analyze_function>;
@@ -108,6 +105,9 @@ def analyzer_disable_checker : Separate<"-analyzer-disable-checker">,
def analyzer_disable_checker_EQ : Joined<"-analyzer-disable-checker=">,
Alias<analyzer_disable_checker>;
+def analyzer_checker_help : Flag<"-analyzer-checker-help">,
+ HelpText<"Display the list of analyzer checkers that are available">;
+
//===----------------------------------------------------------------------===//
// CodeGen Options
//===----------------------------------------------------------------------===//
@@ -418,10 +418,12 @@ def fblocks : Flag<"-fblocks">,
def fheinous_gnu_extensions : Flag<"-fheinous-gnu-extensions">;
def fexceptions : Flag<"-fexceptions">,
HelpText<"Enable support for exception handling">;
+def fobjc_exceptions : Flag<"-fobjc-exceptions">,
+ HelpText<"Enable Objective-C exceptions">;
+def fcxx_exceptions : Flag<"-fcxx-exceptions">,
+ HelpText<"Enable C++ exceptions">;
def fsjlj_exceptions : Flag<"-fsjlj-exceptions">,
HelpText<"Use SjLj style exceptions">;
-def fno_objc_exceptions : Flag<"-fno-objc-exceptions">,
- HelpText<"Disable Objective-C exceptions">;
def ffreestanding : Flag<"-ffreestanding">,
HelpText<"Assert that the compilation takes place in a freestanding environment">;
def fformat_extensions : Flag<"-fformat-extensions">,
@@ -538,6 +540,8 @@ def idirafter : JoinedOrSeparate<"-idirafter">, MetaVarName<"<directory>">,
HelpText<"Add directory to AFTER include search path">;
def iquote : JoinedOrSeparate<"-iquote">, MetaVarName<"<directory>">,
HelpText<"Add directory to QUOTE include search path">;
+def cxx_isystem : JoinedOrSeparate<"-cxx-isystem">, MetaVarName<"<directory>">,
+ HelpText<"Add directory to the C++ SYSTEM include search path">;
def isystem : JoinedOrSeparate<"-isystem">, MetaVarName<"<directory>">,
HelpText<"Add directory to SYSTEM include search path">;
def iwithsysroot : JoinedOrSeparate<"-iwithsysroot">,MetaVarName<"<directory>">,
@@ -552,8 +556,6 @@ def iwithprefixbefore : JoinedOrSeparate<"-iwithprefixbefore">,
HelpText<"Set directory to include search path with prefix">;
def isysroot : JoinedOrSeparate<"-isysroot">, MetaVarName<"<dir>">,
HelpText<"Set the system root directory (usually /)">;
-def cxx_system_include : Separate<"-cxx-system-include">,
- HelpText<"Add a system #include directory for the C++ standard library">;
def v : Flag<"-v">, HelpText<"Enable verbose output">;
//===----------------------------------------------------------------------===//
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Options.td b/contrib/llvm/tools/clang/include/clang/Driver/Options.td
index 1a8a150..0faab3b 100644
--- a/contrib/llvm/tools/clang/include/clang/Driver/Options.td
+++ b/contrib/llvm/tools/clang/include/clang/Driver/Options.td
@@ -208,6 +208,7 @@ def compatibility__version : JoinedOrSeparate<"-compatibility_version">;
def coverage : Flag<"-coverage">;
def cpp_precomp : Flag<"-cpp-precomp">;
def current__version : JoinedOrSeparate<"-current_version">;
+def cxx_isystem : JoinedOrSeparate<"-cxx-isystem">, Group<clang_i_Group>;
def c : Flag<"-c">, Flags<[DriverOption]>,
HelpText<"Only run preprocess, compile, and assemble steps">;
def dA : Flag<"-dA">, Group<d_Group>;
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/AnalyzerOptions.h b/contrib/llvm/tools/clang/include/clang/Frontend/AnalyzerOptions.h
index 5806928..64263c1 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/AnalyzerOptions.h
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/AnalyzerOptions.h
@@ -64,6 +64,7 @@ public:
std::string AnalyzeSpecificFunction;
unsigned MaxNodes;
unsigned MaxLoop;
+ unsigned ShowCheckerHelp : 1;
unsigned AnalyzeAll : 1;
unsigned AnalyzerDisplayProgress : 1;
unsigned AnalyzeNestedBlocks : 1;
@@ -75,7 +76,6 @@ public:
unsigned VisualizeEGDot : 1;
unsigned VisualizeEGUbi : 1;
unsigned EnableExperimentalChecks : 1;
- unsigned EnableExperimentalInternalChecks : 1;
unsigned InlineCall : 1;
unsigned UnoptimizedCFG : 1;
unsigned CFGAddImplicitDtors : 1;
@@ -87,6 +87,7 @@ public:
AnalysisStoreOpt = BasicStoreModel;
AnalysisConstraintsOpt = RangeConstraintsModel;
AnalysisDiagOpt = PD_HTML;
+ ShowCheckerHelp = 0;
AnalyzeAll = 0;
AnalyzerDisplayProgress = 0;
AnalyzeNestedBlocks = 0;
@@ -98,7 +99,6 @@ public:
VisualizeEGDot = 0;
VisualizeEGUbi = 0;
EnableExperimentalChecks = 0;
- EnableExperimentalInternalChecks = 0;
InlineCall = 0;
UnoptimizedCFG = 0;
CFGAddImplicitDtors = 0;
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/DeclXML.def b/contrib/llvm/tools/clang/include/clang/Frontend/DeclXML.def
index 1b158fd..58f7e55 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/DeclXML.def
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/DeclXML.def
@@ -349,7 +349,7 @@ NODE_XML(UsingDecl, "Using")
ID_ATTRIBUTE_XML
ATTRIBUTE_FILE_LOCATION_XML
ATTRIBUTE_XML(getDeclContext(), "context")
- ATTRIBUTE_XML(getTargetNestedNameDecl(), "target_nested_namespace_decl")
+ ATTRIBUTE_XML(getQualifier(), "target_nested_namespace_decl")
ATTRIBUTE_XML(isTypeName(), "is_typename")
END_NODE_XML
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/HeaderSearchOptions.h b/contrib/llvm/tools/clang/include/clang/Frontend/HeaderSearchOptions.h
index cbb4a57..b0669eb 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/HeaderSearchOptions.h
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/HeaderSearchOptions.h
@@ -22,6 +22,7 @@ namespace frontend {
Quoted = 0, ///< `#include ""` paths. Thing `gcc -iquote`.
Angled, ///< Paths for both `#include ""` and `#include <>`. (`-I`)
System, ///< Like Angled, but marks system directories.
+ CXXSystem, ///< Like System, but only used for C++.
After ///< Like System, but searched after the system directories.
};
}
@@ -54,9 +55,6 @@ public:
/// User specified include entries.
std::vector<Entry> UserEntries;
- /// If non-empty, the list of C++ standard include paths to use.
- std::vector<std::string> CXXSystemIncludes;
-
/// A (system-path) delimited list of include paths to be added from the
/// environment following the user specified includes (but prior to builtin
/// and standard includes). This is parsed in the same manner as the CPATH
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/Utils.h b/contrib/llvm/tools/clang/include/clang/Frontend/Utils.h
index 485161b..02342c1 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/Utils.h
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/Utils.h
@@ -28,6 +28,7 @@ class Decl;
class DependencyOutputOptions;
class Diagnostic;
class DiagnosticOptions;
+class FileManager;
class HeaderSearch;
class HeaderSearchOptions;
class IdentifierTable;
@@ -42,7 +43,8 @@ class FrontendOptions;
/// Normalize \arg File for use in a user defined #include directive (in the
/// predefines buffer).
-std::string NormalizeDashIncludePath(llvm::StringRef File);
+std::string NormalizeDashIncludePath(llvm::StringRef File,
+ FileManager &FileMgr);
/// Apply the header search options to get given HeaderSearch object.
void ApplyHeaderSearchOptions(HeaderSearch &HS,
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/Preprocessor.h b/contrib/llvm/tools/clang/include/clang/Lex/Preprocessor.h
index 018f7e9..9005adc 100644
--- a/contrib/llvm/tools/clang/include/clang/Lex/Preprocessor.h
+++ b/contrib/llvm/tools/clang/include/clang/Lex/Preprocessor.h
@@ -942,9 +942,6 @@ private:
/// is not enclosed within a string literal.
void HandleMicrosoft__pragma(Token &Tok);
- void Handle_Pragma(unsigned Introducer, const std::string &StrVal,
- SourceLocation PragmaLoc, SourceLocation RParenLoc);
-
/// EnterSourceFileWithLexer - Add a lexer to the top of the include stack and
/// start lexing tokens from it instead of the current buffer.
void EnterSourceFileWithLexer(Lexer *TheLexer, const DirectoryLookup *Dir);
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/TokenLexer.h b/contrib/llvm/tools/clang/include/clang/Lex/TokenLexer.h
index 3f13e9c..6ae00cd 100644
--- a/contrib/llvm/tools/clang/include/clang/Lex/TokenLexer.h
+++ b/contrib/llvm/tools/clang/include/clang/Lex/TokenLexer.h
@@ -121,6 +121,10 @@ public:
/// Lex - Lex and return a token from this macro stream.
void Lex(Token &Tok);
+ /// isParsingPreprocessorDirective - Return true if we are in the middle of a
+ /// preprocessor directive.
+ bool isParsingPreprocessorDirective() const;
+
private:
void destroy();
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/AnalysisBasedWarnings.h b/contrib/llvm/tools/clang/include/clang/Sema/AnalysisBasedWarnings.h
index 0a6656e..8b389b1 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/AnalysisBasedWarnings.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/AnalysisBasedWarnings.h
@@ -25,6 +25,9 @@ class FunctionDecl;
class ObjCMethodDecl;
class QualType;
class Sema;
+namespace sema {
+ class FunctionScopeInfo;
+}
namespace sema {
@@ -47,16 +50,14 @@ private:
enum VisitFlag { NotVisited = 0, Visited = 1, Pending = 2 };
llvm::DenseMap<const FunctionDecl*, VisitFlag> VisitedFD;
- void IssueWarnings(Policy P, const Decl *D, QualType BlockTy);
public:
AnalysisBasedWarnings(Sema &s);
- Policy getDefaultPolicy() { return DefaultPolicy; }
+ void IssueWarnings(Policy P, FunctionScopeInfo *fscope,
+ const Decl *D, const BlockExpr *blkExpr);
- void IssueWarnings(Policy P, const BlockExpr *E);
- void IssueWarnings(Policy P, const FunctionDecl *D);
- void IssueWarnings(Policy P, const ObjCMethodDecl *D);
+ Policy getDefaultPolicy() { return DefaultPolicy; }
};
}} // end namespace clang::sema
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/DeclSpec.h b/contrib/llvm/tools/clang/include/clang/Sema/DeclSpec.h
index 9c4bb64..64126bd 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/DeclSpec.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/DeclSpec.h
@@ -29,10 +29,15 @@
#include "llvm/Support/ErrorHandling.h"
namespace clang {
+ class ASTContext;
+ class TypeLoc;
class LangOptions;
class Diagnostic;
class IdentifierInfo;
+ class NamespaceAliasDecl;
+ class NamespaceDecl;
class NestedNameSpecifier;
+ class NestedNameSpecifierLoc;
class Preprocessor;
class Declarator;
struct TemplateIdAnnotation;
@@ -52,9 +57,29 @@ class CXXScopeSpec {
SourceRange Range;
NestedNameSpecifier *ScopeRep;
-public:
- CXXScopeSpec() : Range(), ScopeRep() { }
+ /// \brief Buffer used to store source-location information for the
+ /// nested-name-specifier.
+ ///
+ /// Note that we explicitly manage the buffer (rather than using a
+ /// SmallVector) because \c Declarator expects it to be possible to memcpy()
+ /// a \c CXXScopeSpec.
+ char *Buffer;
+
+ /// \brief The size of the buffer used to store source-location information
+ /// for the nested-name-specifier.
+ unsigned BufferSize;
+
+ /// \brief The capacity of the buffer used to store source-location
+ /// information for the nested-name-specifier.
+ unsigned BufferCapacity;
+public:
+ CXXScopeSpec() : Range(), ScopeRep(), Buffer(0), BufferSize(0),
+ BufferCapacity(0) { }
+ CXXScopeSpec(const CXXScopeSpec &Other);
+ CXXScopeSpec &operator=(const CXXScopeSpec &Other);
+ ~CXXScopeSpec();
+
const SourceRange &getRange() const { return Range; }
void setRange(const SourceRange &R) { Range = R; }
void setBeginLoc(SourceLocation Loc) { Range.setBegin(Loc); }
@@ -63,7 +88,87 @@ public:
SourceLocation getEndLoc() const { return Range.getEnd(); }
NestedNameSpecifier *getScopeRep() const { return ScopeRep; }
- void setScopeRep(NestedNameSpecifier *S) { ScopeRep = S; }
+
+ /// \brief Extend the current nested-name-specifier by another
+ /// nested-name-specifier component of the form 'type::'.
+ ///
+ /// \param Context The AST context in which this nested-name-specifier
+ /// resides.
+ ///
+ /// \param TemplateKWLoc The location of the 'template' keyword, if present.
+ ///
+ /// \param TL The TypeLoc that describes the type preceding the '::'.
+ ///
+ /// \param ColonColonLoc The location of the trailing '::'.
+ void Extend(ASTContext &Context, SourceLocation TemplateKWLoc, TypeLoc TL,
+ SourceLocation ColonColonLoc);
+
+ /// \brief Extend the current nested-name-specifier by another
+ /// nested-name-specifier component of the form 'identifier::'.
+ ///
+ /// \param Context The AST context in which this nested-name-specifier
+ /// resides.
+ ///
+ /// \param Identifier The identifier.
+ ///
+ /// \param IdentifierLoc The location of the identifier.
+ ///
+ /// \param ColonColonLoc The location of the trailing '::'.
+ void Extend(ASTContext &Context, IdentifierInfo *Identifier,
+ SourceLocation IdentifierLoc, SourceLocation ColonColonLoc);
+
+ /// \brief Extend the current nested-name-specifier by another
+ /// nested-name-specifier component of the form 'namespace::'.
+ ///
+ /// \param Context The AST context in which this nested-name-specifier
+ /// resides.
+ ///
+ /// \param Namespace The namespace.
+ ///
+ /// \param NamespaceLoc The location of the namespace name.
+ ///
+ /// \param ColonColonLoc The location of the trailing '::'.
+ void Extend(ASTContext &Context, NamespaceDecl *Namespace,
+ SourceLocation NamespaceLoc, SourceLocation ColonColonLoc);
+
+ /// \brief Extend the current nested-name-specifier by another
+ /// nested-name-specifier component of the form 'namespace-alias::'.
+ ///
+ /// \param Context The AST context in which this nested-name-specifier
+ /// resides.
+ ///
+ /// \param Alias The namespace alias.
+ ///
+ /// \param AliasLoc The location of the namespace alias
+ /// name.
+ ///
+ /// \param ColonColonLoc The location of the trailing '::'.
+ void Extend(ASTContext &Context, NamespaceAliasDecl *Alias,
+ SourceLocation AliasLoc, SourceLocation ColonColonLoc);
+
+ /// \brief Turn this (empty) nested-name-specifier into the global
+ /// nested-name-specifier '::'.
+ void MakeGlobal(ASTContext &Context, SourceLocation ColonColonLoc);
+
+ /// \brief Make a new nested-name-specifier from incomplete source-location
+ /// information.
+ ///
+ /// FIXME: This routine should be used very, very rarely, in cases where we
+ /// need to synthesize a nested-name-specifier. Most code should instead use
+ /// \c Adopt() with a proper \c NestedNameSpecifierLoc.
+ void MakeTrivial(ASTContext &Context, NestedNameSpecifier *Qualifier,
+ SourceRange R);
+
+ /// \brief Adopt an existing nested-name-specifier (with source-range
+ /// information).
+ void Adopt(NestedNameSpecifierLoc Other);
+
+ /// \brief Retrieve a nested-name-specifier with location information, copied
+ /// into the given AST context.
+ ///
+ /// \param Context The context into which this nested-name-specifier will be
+ /// copied.
+ NestedNameSpecifierLoc getWithLocInContext(ASTContext &Context) const;
/// No scope specifier.
bool isEmpty() const { return !Range.isValid(); }
@@ -75,6 +180,15 @@ public:
/// A scope specifier is present, and it refers to a real scope.
bool isValid() const { return isNotEmpty() && ScopeRep != 0; }
+ /// \brief Indicate that this nested-name-specifier is invalid.
+ void SetInvalid(SourceRange R) {
+ assert(R.isValid() && "Must have a valid source range");
+ if (Range.getBegin().isInvalid())
+ Range.setBegin(R.getBegin());
+ Range.setEnd(R.getEnd());
+ ScopeRep = 0;
+ }
+
/// Deprecated. Some call sites intend isNotEmpty() while others intend
/// isValid().
bool isSet() const { return ScopeRep != 0; }
@@ -83,6 +197,13 @@ public:
Range = SourceRange();
ScopeRep = 0;
}
+
+ /// \brief Retrieve the data associated with the source-location information.
+ char *location_data() const { return Buffer; }
+
+ /// \brief Retrieve the size of the data associated with source-location
+ /// information.
+ unsigned location_size() const { return BufferSize; }
};
/// DeclSpec - This class captures information about "declaration specifiers",
@@ -825,6 +946,16 @@ struct DeclaratorChunk {
struct PointerTypeInfo : TypeInfoCommon {
/// The type qualifiers: const/volatile/restrict.
unsigned TypeQuals : 3;
+
+ /// The location of the const-qualifier, if any.
+ unsigned ConstQualLoc;
+
+ /// The location of the volatile-qualifier, if any.
+ unsigned VolatileQualLoc;
+
+ /// The location of the restrict-qualifier, if any.
+ unsigned RestrictQualLoc;
+
void destroy() {
}
};
@@ -1055,12 +1186,18 @@ struct DeclaratorChunk {
/// getPointer - Return a DeclaratorChunk for a pointer.
///
static DeclaratorChunk getPointer(unsigned TypeQuals, SourceLocation Loc,
+ SourceLocation ConstQualLoc,
+ SourceLocation VolatileQualLoc,
+ SourceLocation RestrictQualLoc,
const ParsedAttributes &attrs) {
DeclaratorChunk I;
- I.Kind = Pointer;
- I.Loc = Loc;
- I.Ptr.TypeQuals = TypeQuals;
- I.Ptr.AttrList = attrs.getList();
+ I.Kind = Pointer;
+ I.Loc = Loc;
+ I.Ptr.TypeQuals = TypeQuals;
+ I.Ptr.ConstQualLoc = ConstQualLoc.getRawEncoding();
+ I.Ptr.VolatileQualLoc = VolatileQualLoc.getRawEncoding();
+ I.Ptr.RestrictQualLoc = RestrictQualLoc.getRawEncoding();
+ I.Ptr.AttrList = attrs.getList();
return I;
}
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/ExternalSemaSource.h b/contrib/llvm/tools/clang/include/clang/Sema/ExternalSemaSource.h
index 6d7bc63..e2b083e 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/ExternalSemaSource.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/ExternalSemaSource.h
@@ -20,6 +20,8 @@ namespace clang {
struct ObjCMethodList;
class Sema;
+class Scope;
+class LookupResult;
/// \brief An abstract interface that should be implemented by
/// external AST sources that also provide information for semantic
@@ -47,6 +49,16 @@ public:
/// instance and factory methods, respectively, with this selector.
virtual std::pair<ObjCMethodList,ObjCMethodList> ReadMethodPool(Selector Sel);
+ /// \brief Do last resort, unqualified lookup on a LookupResult that
+ /// Sema cannot find.
+ ///
+ /// \param R a LookupResult that is being recovered.
+ ///
+ /// \param S the Scope of the identifier occurrence.
+ ///
+ /// \return true to tell Sema to recover using the LookupResult.
+ virtual bool LookupUnqualified(LookupResult &R, Scope *S) { return false; }
+
// isa/cast/dyn_cast support
static bool classof(const ExternalASTSource *Source) {
return Source->SemaSource;
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/Initialization.h b/contrib/llvm/tools/clang/include/clang/Sema/Initialization.h
index c191565..bdf0d8e 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/Initialization.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/Initialization.h
@@ -467,7 +467,10 @@ public:
CAssignment,
/// \brief String initialization
- StringInit
+ StringInit,
+
+ /// \brief Array initialization from another array (GNU C extension).
+ ArrayInit
};
/// \brief Describes the kind of a particular step in an initialization
@@ -513,7 +516,10 @@ public:
SK_StringInit,
/// \brief An initialization that "converts" an Objective-C object
/// (not a point to an object) to another Objective-C object type.
- SK_ObjCObjectConversion
+ SK_ObjCObjectConversion,
+ /// \brief Array initialization (from an array rvalue).
+ /// This is a GNU C extension.
+ SK_ArrayInit
};
/// \brief A single step in the initialization sequence.
@@ -563,6 +569,10 @@ public:
/// \brief Array must be initialized with an initializer list or a
/// string literal.
FK_ArrayNeedsInitListOrStringLiteral,
+ /// \brief Array type mismatch.
+ FK_ArrayTypeMismatch,
+ /// \brief Non-constant array initializer
+ FK_NonConstantArrayInit,
/// \brief Cannot resolve the address of an overloaded function.
FK_AddressOfOverloadFailed,
/// \brief Overloading due to reference initialization failed.
@@ -775,6 +785,9 @@ public:
/// always a no-op.
void AddObjCObjectConversionStep(QualType T);
+ /// \brief Add an array initialization step.
+ void AddArrayInitStep(QualType T);
+
/// \brief Note that this initialization sequence failed.
void SetFailed(FailureKind Failure) {
SequenceKind = FailedSequence;
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/ParsedTemplate.h b/contrib/llvm/tools/clang/include/clang/Sema/ParsedTemplate.h
index 5aa6f47..9e1a616 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/ParsedTemplate.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/ParsedTemplate.h
@@ -177,6 +177,12 @@ namespace clang {
= (TemplateIdAnnotation *)std::malloc(sizeof(TemplateIdAnnotation) +
sizeof(ParsedTemplateArgument) * NumArgs);
TemplateId->NumArgs = NumArgs;
+
+ // Default-construct parsed template arguments.
+ ParsedTemplateArgument *TemplateArgs = TemplateId->getTemplateArgs();
+ for (unsigned I = 0; I != NumArgs; ++I)
+ new (TemplateArgs + I) ParsedTemplateArgument();
+
return TemplateId;
}
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/ScopeInfo.h b/contrib/llvm/tools/clang/include/clang/Sema/ScopeInfo.h
index b0bb955..51297ae 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/ScopeInfo.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/ScopeInfo.h
@@ -15,6 +15,7 @@
#define LLVM_CLANG_SEMA_SCOPE_INFO_H
#include "clang/AST/Type.h"
+#include "clang/Basic/PartialDiagnostic.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/SetVector.h"
@@ -30,6 +31,17 @@ class SwitchStmt;
namespace sema {
+class PossiblyUnreachableDiag {
+public:
+ PartialDiagnostic PD;
+ SourceLocation Loc;
+ const Stmt *stmt;
+
+ PossiblyUnreachableDiag(const PartialDiagnostic &PD, SourceLocation Loc,
+ const Stmt *stmt)
+ : PD(PD), Loc(Loc), stmt(stmt) {}
+};
+
/// \brief Retains information about a function, method, or block that is
/// currently being parsed.
class FunctionScopeInfo {
@@ -60,6 +72,11 @@ public:
/// block, if there is any chance of applying the named return value
/// optimization.
llvm::SmallVector<ReturnStmt*, 4> Returns;
+
+ /// \brief A list of PartialDiagnostics created but delayed within the
+ /// current function scope. These diagnostics are vetted for reachability
+ /// prior to being emitted.
+ llvm::SmallVector<PossiblyUnreachableDiag, 4> PossiblyUnreachableDiags;
void setHasBranchIntoScope() {
HasBranchIntoScope = true;
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/Sema.h b/contrib/llvm/tools/clang/include/clang/Sema/Sema.h
index 91d6914..a937398 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/Sema.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/Sema.h
@@ -267,6 +267,10 @@ public:
/// same list more than once.
llvm::OwningPtr<RecordDeclSetTy> PureVirtualClassDiagSet;
+ /// ParsingInitForAutoVars - a set of declarations with auto types for which
+ /// we are currently parsing the initializer.
+ llvm::SmallPtrSet<const Decl*, 4> ParsingInitForAutoVars;
+
/// \brief A mapping from external names to the most recent
/// locally-scoped external declaration with that name.
///
@@ -684,7 +688,8 @@ public:
void PushFunctionScope();
void PushBlockScope(Scope *BlockScope, BlockDecl *Block);
- void PopFunctionOrBlockScope();
+ void PopFunctionOrBlockScope(const sema::AnalysisBasedWarnings::Policy *WP =0,
+ const Decl *D = 0, const BlockExpr *blkExpr = 0);
sema::FunctionScopeInfo *getCurFunction() const {
return FunctionScopes.back();
@@ -856,9 +861,12 @@ public:
void ActOnUninitializedDecl(Decl *dcl, bool TypeMayContainAuto);
void ActOnInitializerError(Decl *Dcl);
void SetDeclDeleted(Decl *dcl, SourceLocation DelLoc);
+ void FinalizeDeclaration(Decl *D);
DeclGroupPtrTy FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
Decl **Group,
unsigned NumDecls);
+ DeclGroupPtrTy BuildDeclaratorGroup(Decl **Group, unsigned NumDecls,
+ bool TypeMayContainAuto = true);
void ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D,
SourceLocation LocAfterDecls);
Decl *ActOnStartOfFunctionDef(Scope *S, Declarator &D);
@@ -1518,7 +1526,8 @@ public:
void WarnUndefinedMethod(SourceLocation ImpLoc, ObjCMethodDecl *method,
bool &IncompleteImpl, unsigned DiagID);
void WarnConflictingTypedMethods(ObjCMethodDecl *ImpMethod,
- ObjCMethodDecl *IntfMethod);
+ ObjCMethodDecl *MethodDecl,
+ bool IsProtocolMethodDecl);
bool isPropertyReadonly(ObjCPropertyDecl *PropertyDecl,
ObjCInterfaceDecl *IDecl);
@@ -1883,7 +1892,16 @@ public:
void MarkDeclarationReferenced(SourceLocation Loc, Decl *D);
void MarkDeclarationsReferencedInType(SourceLocation Loc, QualType T);
void MarkDeclarationsReferencedInExpr(Expr *E);
- bool DiagRuntimeBehavior(SourceLocation Loc, const PartialDiagnostic &PD);
+
+ /// \brief Conditionally issue a diagnostic based on the current
+ /// evaluation context.
+ ///
+ /// \param stmt - If stmt is non-null, delay reporting the diagnostic until
+ /// the function body is parsed, and then do a basic reachability analysis to
+ /// determine if the statement is reachable. If it is unreachable, the
+ /// diagnostic will not be emitted.
+ bool DiagRuntimeBehavior(SourceLocation Loc, const Stmt *stmt,
+ const PartialDiagnostic &PD);
// Primary Expressions.
SourceRange getExprRange(Expr *E) const;
@@ -2573,11 +2591,19 @@ public:
CXXRecordDecl *getCurrentInstantiationOf(NestedNameSpecifier *NNS);
bool isUnknownSpecialization(const CXXScopeSpec &SS);
- /// ActOnCXXGlobalScopeSpecifier - Return the object that represents the
- /// global scope ('::').
- NestedNameSpecifier *
- ActOnCXXGlobalScopeSpecifier(Scope *S, SourceLocation CCLoc);
-
+ /// \brief The parser has parsed a global nested-name-specifier '::'.
+ ///
+ /// \param S The scope in which this nested-name-specifier occurs.
+ ///
+ /// \param CCLoc The location of the '::'.
+ ///
+ /// \param SS The nested-name-specifier, which will be updated in-place
+ /// to reflect the parsed nested-name-specifier.
+ ///
+ /// \returns true if an error occurred, false otherwise.
+ bool ActOnCXXGlobalScopeSpecifier(Scope *S, SourceLocation CCLoc,
+ CXXScopeSpec &SS);
+
bool isAcceptableNestedNameSpecifier(NamedDecl *SD);
NamedDecl *FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS);
@@ -2586,43 +2612,97 @@ public:
IdentifierInfo &II,
ParsedType ObjectType);
- NestedNameSpecifier *BuildCXXNestedNameSpecifier(Scope *S,
- CXXScopeSpec &SS,
- SourceLocation IdLoc,
- SourceLocation CCLoc,
- IdentifierInfo &II,
- QualType ObjectType,
- NamedDecl *ScopeLookupResult,
- bool EnteringContext,
- bool ErrorRecoveryLookup);
-
- NestedNameSpecifier *ActOnCXXNestedNameSpecifier(Scope *S,
- CXXScopeSpec &SS,
- SourceLocation IdLoc,
- SourceLocation CCLoc,
- IdentifierInfo &II,
- ParsedType ObjectType,
- bool EnteringContext);
+ bool BuildCXXNestedNameSpecifier(Scope *S,
+ IdentifierInfo &Identifier,
+ SourceLocation IdentifierLoc,
+ SourceLocation CCLoc,
+ QualType ObjectType,
+ bool EnteringContext,
+ CXXScopeSpec &SS,
+ NamedDecl *ScopeLookupResult,
+ bool ErrorRecoveryLookup);
+
+ /// \brief The parser has parsed a nested-name-specifier 'identifier::'.
+ ///
+ /// \param S The scope in which this nested-name-specifier occurs.
+ ///
+ /// \param Identifier The identifier preceding the '::'.
+ ///
+ /// \param IdentifierLoc The location of the identifier.
+ ///
+ /// \param CCLoc The location of the '::'.
+ ///
+ /// \param ObjectType The type of the object, if we're parsing
+ /// nested-name-specifier in a member access expression.
+ ///
+ /// \param EnteringContext Whether we're entering the context nominated by
+ /// this nested-name-specifier.
+ ///
+ /// \param SS The nested-name-specifier, which is both an input
+ /// parameter (the nested-name-specifier before this type) and an
+ /// output parameter (containing the full nested-name-specifier,
+ /// including this new type).
+ ///
+ /// \returns true if an error occurred, false otherwise.
+ bool ActOnCXXNestedNameSpecifier(Scope *S,
+ IdentifierInfo &Identifier,
+ SourceLocation IdentifierLoc,
+ SourceLocation CCLoc,
+ ParsedType ObjectType,
+ bool EnteringContext,
+ CXXScopeSpec &SS);
bool IsInvalidUnlessNestedName(Scope *S, CXXScopeSpec &SS,
- IdentifierInfo &II,
+ IdentifierInfo &Identifier,
+ SourceLocation IdentifierLoc,
+ SourceLocation ColonLoc,
ParsedType ObjectType,
bool EnteringContext);
- /// ActOnCXXNestedNameSpecifier - Called during parsing of a
- /// nested-name-specifier that involves a template-id, e.g.,
- /// "foo::bar<int, float>::", and now we need to build a scope
- /// specifier. \p SS is empty or the previously parsed nested-name
- /// part ("foo::"), \p Type is the already-parsed class template
- /// specialization (or other template-id that names a type), \p
- /// TypeRange is the source range where the type is located, and \p
- /// CCLoc is the location of the trailing '::'.
- CXXScopeTy *ActOnCXXNestedNameSpecifier(Scope *S,
- const CXXScopeSpec &SS,
- ParsedType Type,
- SourceRange TypeRange,
- SourceLocation CCLoc);
-
+ /// \brief The parser has parsed a nested-name-specifier 'type::'.
+ ///
+ /// \param S The scope in which this nested-name-specifier occurs.
+ ///
+ /// \param Type The type, which will be a template specialization
+ /// type, preceding the '::'.
+ ///
+ /// \param CCLoc The location of the '::'.
+ ///
+ /// \param SS The nested-name-specifier, which is both an input
+ /// parameter (the nested-name-specifier before this type) and an
+ /// output parameter (containing the full nested-name-specifier,
+ /// including this new type).
+ ///
+ /// \returns true if an error occurred, false otherwise.
+ bool ActOnCXXNestedNameSpecifier(Scope *S,
+ ParsedType Type,
+ SourceLocation CCLoc,
+ CXXScopeSpec &SS);
+
+ /// \brief Given a C++ nested-name-specifier, produce an annotation value
+ /// that the parser can use later to reconstruct the given
+ /// nested-name-specifier.
+ ///
+ /// \param SS A nested-name-specifier.
+ ///
+ /// \returns A pointer containing all of the information in the
+ /// nested-name-specifier \p SS.
+ void *SaveNestedNameSpecifierAnnotation(CXXScopeSpec &SS);
+
+ /// \brief Given an annotation pointer for a nested-name-specifier, restore
+ /// the nested-name-specifier structure.
+ ///
+ /// \param Annotation The annotation pointer, produced by
+ /// \c SaveNestedNameSpecifierAnnotation().
+ ///
+ /// \param AnnotationRange The source range corresponding to the annotation.
+ ///
+ /// \param SS The nested-name-specifier that will be updated with the contents
+ /// of the annotation pointer.
+ void RestoreNestedNameSpecifierAnnotation(void *Annotation,
+ SourceRange AnnotationRange,
+ CXXScopeSpec &SS);
+
bool ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS);
/// ActOnCXXEnterDeclaratorScope - Called when a C++ scope specifier (global
@@ -4213,6 +4293,11 @@ public:
SubstNestedNameSpecifier(NestedNameSpecifier *NNS,
SourceRange Range,
const MultiLevelTemplateArgumentList &TemplateArgs);
+
+ NestedNameSpecifierLoc
+ SubstNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+
DeclarationNameInfo
SubstDeclarationNameInfo(const DeclarationNameInfo &NameInfo,
const MultiLevelTemplateArgumentList &TemplateArgs);
@@ -4772,7 +4857,8 @@ public:
QualType CheckSubtractionOperands( // C99 6.5.6
Expr *&lex, Expr *&rex, SourceLocation OpLoc, QualType* CompLHSTy = 0);
QualType CheckShiftOperands( // C99 6.5.7
- Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isCompAssign = false);
+ Expr *&lex, Expr *&rex, SourceLocation OpLoc, unsigned Opc,
+ bool isCompAssign = false);
QualType CheckCompareOperands( // C99 6.5.8/9
Expr *&lex, Expr *&rex, SourceLocation OpLoc, unsigned Opc,
bool isRelational);
diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/ASTReader.h b/contrib/llvm/tools/clang/include/clang/Serialization/ASTReader.h
index 9799b8d..424e78c 100644
--- a/contrib/llvm/tools/clang/include/clang/Serialization/ASTReader.h
+++ b/contrib/llvm/tools/clang/include/clang/Serialization/ASTReader.h
@@ -116,7 +116,8 @@ public:
/// \returns true to indicate the predefines are invalid or false otherwise.
virtual bool ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers,
llvm::StringRef OriginalFileName,
- std::string &SuggestedPredefines) {
+ std::string &SuggestedPredefines,
+ FileManager &FileMgr) {
return false;
}
@@ -143,7 +144,8 @@ public:
virtual bool ReadTargetTriple(llvm::StringRef Triple);
virtual bool ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers,
llvm::StringRef OriginalFileName,
- std::string &SuggestedPredefines);
+ std::string &SuggestedPredefines,
+ FileManager &FileMgr);
virtual void ReadHeaderFileInfo(const HeaderFileInfo &HFI, unsigned ID);
virtual void ReadCounter(unsigned Value);
@@ -1131,6 +1133,10 @@ public:
NestedNameSpecifier *ReadNestedNameSpecifier(const RecordData &Record,
unsigned &Idx);
+ NestedNameSpecifierLoc ReadNestedNameSpecifierLoc(PerFileData &F,
+ const RecordData &Record,
+ unsigned &Idx);
+
/// \brief Read a template name.
TemplateName ReadTemplateName(PerFileData &F, const RecordData &Record,
unsigned &Idx);
diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/ASTWriter.h b/contrib/llvm/tools/clang/include/clang/Serialization/ASTWriter.h
index beb4936..04ad93f 100644
--- a/contrib/llvm/tools/clang/include/clang/Serialization/ASTWriter.h
+++ b/contrib/llvm/tools/clang/include/clang/Serialization/ASTWriter.h
@@ -443,6 +443,9 @@ public:
/// \brief Emits a reference to a declarator info.
void AddTypeSourceInfo(TypeSourceInfo *TInfo, RecordDataImpl &Record);
+ /// \brief Emits a type with source-location information.
+ void AddTypeLoc(TypeLoc TL, RecordDataImpl &Record);
+
/// \brief Emits a template argument location info.
void AddTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind,
const TemplateArgumentLocInfo &Arg,
@@ -474,6 +477,10 @@ public:
/// \brief Emit a nested name specifier.
void AddNestedNameSpecifier(NestedNameSpecifier *NNS, RecordDataImpl &Record);
+
+ /// \brief Emit a nested name specifier with source-location information.
+ void AddNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
+ RecordDataImpl &Record);
/// \brief Emit a template name.
void AddTemplateName(TemplateName Name, RecordDataImpl &Record);
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/LocalCheckers.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/LocalCheckers.h
index 42feb78..afba12d 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/LocalCheckers.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/LocalCheckers.h
@@ -40,7 +40,6 @@ TransferFuncs* MakeCFRefCountTF(ASTContext& Ctx, bool GCEnabled,
const LangOptions& lopts);
void RegisterExperimentalChecks(ExprEngine &Eng);
-void RegisterExperimentalInternalChecks(ExprEngine &Eng);
void RegisterCallInliner(ExprEngine &Eng);
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
index 1786fe6..93d7958 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
@@ -72,6 +72,7 @@ protected:
friend class BugReportEquivClass;
virtual void Profile(llvm::FoldingSetNodeID& hash) const {
+ hash.AddPointer(&BT);
hash.AddInteger(getLocation().getRawEncoding());
hash.AddString(Description);
}
@@ -277,6 +278,8 @@ private:
void FlushReport(BugReportEquivClass& EQ);
+ llvm::FoldingSet<BugReportEquivClass> EQClasses;
+
protected:
BugReporter(BugReporterData& d, Kind k) : BugTypes(F.getEmptySet()), kind(k),
D(d) {}
@@ -302,6 +305,10 @@ public:
iterator begin() { return BugTypes.begin(); }
iterator end() { return BugTypes.end(); }
+ typedef llvm::FoldingSet<BugReportEquivClass>::iterator EQClasses_iterator;
+ EQClasses_iterator EQClasses_begin() { return EQClasses.begin(); }
+ EQClasses_iterator EQClasses_end() { return EQClasses.end(); }
+
ASTContext& getContext() { return D.getASTContext(); }
SourceManager& getSourceManager() { return D.getSourceManager(); }
@@ -344,6 +351,13 @@ public:
}
static bool classof(const BugReporter* R) { return true; }
+
+private:
+ llvm::StringMap<BugType *> StrBugTypes;
+
+ /// \brief Returns a BugType that is associated with the given name and
+ /// category.
+ BugType *getBugTypeForName(llvm::StringRef name, llvm::StringRef category);
};
// FIXME: Get rid of GRBugReporter. It's the wrong abstraction.
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h
index 2793284..7b9bb03 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h
@@ -29,8 +29,6 @@ class BugType {
private:
const std::string Name;
const std::string Category;
- llvm::FoldingSet<BugReportEquivClass> EQClasses;
- friend class BugReporter;
bool SuppressonSink;
public:
BugType(llvm::StringRef name, llvm::StringRef cat)
@@ -48,14 +46,6 @@ public:
void setSuppressOnSink(bool x) { SuppressonSink = x; }
virtual void FlushReports(BugReporter& BR);
-
- typedef llvm::FoldingSet<BugReportEquivClass>::iterator iterator;
- iterator begin() { return EQClasses.begin(); }
- iterator end() { return EQClasses.end(); }
-
- typedef llvm::FoldingSet<BugReportEquivClass>::const_iterator const_iterator;
- const_iterator begin() const { return EQClasses.begin(); }
- const_iterator end() const { return EQClasses.end(); }
};
class BuiltinBug : public BugType {
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h
index 65c8b80..2768195 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h
@@ -14,23 +14,92 @@
#ifndef LLVM_CLANG_SA_CORE_CHECKERMANAGER_H
#define LLVM_CLANG_SA_CORE_CHECKERMANAGER_H
+#include "clang/Basic/LangOptions.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/FoldingSet.h"
#include <vector>
namespace clang {
class Decl;
+ class Stmt;
+ class CallExpr;
namespace ento {
class ExprEngine;
class AnalysisManager;
class BugReporter;
+ class CheckerContext;
+ class ObjCMessage;
+ class SVal;
+ class ExplodedNode;
+ class ExplodedNodeSet;
+ class ExplodedGraph;
+ class GRState;
+ class EndOfFunctionNodeBuilder;
+ class MemRegion;
+ class SymbolReaper;
+
+class GraphExpander {
+public:
+ virtual ~GraphExpander();
+ virtual void expandGraph(ExplodedNodeSet &Dst, ExplodedNode *Pred) = 0;
+};
+
+struct VoidCheckerFnParm {};
+template <typename P1=VoidCheckerFnParm, typename P2=VoidCheckerFnParm,
+ typename P3=VoidCheckerFnParm, typename P4=VoidCheckerFnParm>
+class CheckerFn {
+ typedef void (*Func)(void *, P1, P2, P3, P4);
+ Func Fn;
+public:
+ void *Checker;
+ CheckerFn(void *checker, Func fn) : Fn(fn), Checker(checker) { }
+ void operator()(P1 p1, P2 p2, P3 p3, P4 p4) { Fn(Checker, p1, p2, p3, p4); }
+};
+
+template <typename P1, typename P2, typename P3>
+class CheckerFn<P1, P2, P3, VoidCheckerFnParm> {
+ typedef void (*Func)(void *, P1, P2, P3);
+ Func Fn;
+public:
+ void *Checker;
+ CheckerFn(void *checker, Func fn) : Fn(fn), Checker(checker) { }
+ void operator()(P1 p1, P2 p2, P3 p3) { Fn(Checker, p1, p2, p3); }
+};
+
+template <typename P1, typename P2>
+class CheckerFn<P1, P2, VoidCheckerFnParm, VoidCheckerFnParm> {
+ typedef void (*Func)(void *, P1, P2);
+ Func Fn;
+public:
+ void *Checker;
+ CheckerFn(void *checker, Func fn) : Fn(fn), Checker(checker) { }
+ void operator()(P1 p1, P2 p2) { Fn(Checker, p1, p2); }
+};
+
+template <>
+class CheckerFn<VoidCheckerFnParm, VoidCheckerFnParm, VoidCheckerFnParm,
+ VoidCheckerFnParm> {
+ typedef void (*Func)(void *);
+ Func Fn;
+public:
+ void *Checker;
+ CheckerFn(void *checker, Func fn) : Fn(fn), Checker(checker) { }
+ void operator()() { Fn(Checker); }
+};
class CheckerManager {
+ const LangOptions LangOpts;
+
public:
+ CheckerManager(const LangOptions &langOpts) : LangOpts(langOpts) { }
~CheckerManager();
+ const LangOptions &getLangOptions() const { return LangOpts; }
+
typedef void *CheckerRef;
+ typedef CheckerFn<> CheckerDtor;
//===----------------------------------------------------------------------===//
// registerChecker
@@ -40,17 +109,12 @@ public:
template <typename CHECKER>
void registerChecker() {
CHECKER *checker = new CHECKER();
- Checkers.push_back(std::pair<CheckerRef, Dtor>(checker, destruct<CHECKER>));
+ CheckerDtors.push_back(CheckerDtor(checker, destruct<CHECKER>));
CHECKER::_register(checker, *this);
}
- typedef void (*RegisterToEngFunc)(ExprEngine &Eng);
- void addCheckerRegisterFunction(RegisterToEngFunc fn) {
- Funcs.push_back(fn);
- }
-
//===----------------------------------------------------------------------===//
-// Functions for running checkers.
+// Functions for running checkers for AST traversing..
//===----------------------------------------------------------------------===//
/// \brief Run checkers handling Decls.
@@ -62,48 +126,290 @@ public:
BugReporter &BR);
//===----------------------------------------------------------------------===//
-// Internal registration functions.
+// Functions for running checkers for path-sensitive checking.
+//===----------------------------------------------------------------------===//
+
+ /// \brief Run checkers for pre-visiting Stmts.
+ void runCheckersForPreStmt(ExplodedNodeSet &Dst,
+ const ExplodedNodeSet &Src,
+ const Stmt *S,
+ ExprEngine &Eng) {
+ runCheckersForStmt(/*isPreVisit=*/true, Dst, Src, S, Eng);
+ }
+
+ /// \brief Run checkers for post-visiting Stmts.
+ void runCheckersForPostStmt(ExplodedNodeSet &Dst,
+ const ExplodedNodeSet &Src,
+ const Stmt *S,
+ ExprEngine &Eng) {
+ runCheckersForStmt(/*isPreVisit=*/false, Dst, Src, S, Eng);
+ }
+
+ /// \brief Run checkers for visiting Stmts.
+ void runCheckersForStmt(bool isPreVisit,
+ ExplodedNodeSet &Dst, const ExplodedNodeSet &Src,
+ const Stmt *S, ExprEngine &Eng);
+
+ /// \brief Run checkers for pre-visiting obj-c messages.
+ void runCheckersForPreObjCMessage(ExplodedNodeSet &Dst,
+ const ExplodedNodeSet &Src,
+ const ObjCMessage &msg,
+ ExprEngine &Eng) {
+ runCheckersForObjCMessage(/*isPreVisit=*/true, Dst, Src, msg, Eng);
+ }
+
+ /// \brief Run checkers for post-visiting obj-c messages.
+ void runCheckersForPostObjCMessage(ExplodedNodeSet &Dst,
+ const ExplodedNodeSet &Src,
+ const ObjCMessage &msg,
+ ExprEngine &Eng) {
+ runCheckersForObjCMessage(/*isPreVisit=*/false, Dst, Src, msg, Eng);
+ }
+
+ /// \brief Run checkers for visiting obj-c messages.
+ void runCheckersForObjCMessage(bool isPreVisit,
+ ExplodedNodeSet &Dst,
+ const ExplodedNodeSet &Src,
+ const ObjCMessage &msg, ExprEngine &Eng);
+
+ /// \brief Run checkers for load/store of a location.
+ void runCheckersForLocation(ExplodedNodeSet &Dst,
+ const ExplodedNodeSet &Src,
+ SVal location, bool isLoad,
+ const Stmt *S,
+ ExprEngine &Eng);
+
+ /// \brief Run checkers for end of analysis.
+ void runCheckersForEndAnalysis(ExplodedGraph &G, BugReporter &BR,
+ ExprEngine &Eng);
+
+ /// \brief Run checkers for end of path.
+ void runCheckersForEndPath(EndOfFunctionNodeBuilder &B, ExprEngine &Eng);
+
+ /// \brief Run checkers for live symbols.
+ void runCheckersForLiveSymbols(const GRState *state,
+ SymbolReaper &SymReaper);
+
+ /// \brief Run checkers for dead symbols.
+ void runCheckersForDeadSymbols(ExplodedNodeSet &Dst,
+ const ExplodedNodeSet &Src,
+ SymbolReaper &SymReaper, const Stmt *S,
+ ExprEngine &Eng);
+
+ /// \brief True if at least one checker wants to check region changes.
+ bool wantsRegionChangeUpdate(const GRState *state);
+
+ /// \brief Run checkers for region changes.
+ const GRState *runCheckersForRegionChanges(const GRState *state,
+ const MemRegion * const *Begin,
+ const MemRegion * const *End);
+
+ /// \brief Run checkers for evaluating a call.
+ void runCheckersForEvalCall(ExplodedNodeSet &Dst,
+ const ExplodedNodeSet &Src,
+ const CallExpr *CE, ExprEngine &Eng,
+ GraphExpander *defaultEval = 0);
+
+//===----------------------------------------------------------------------===//
+// Internal registration functions for AST traversing.
//===----------------------------------------------------------------------===//
// Functions used by the registration mechanism, checkers should not touch
// these directly.
- typedef void (*CheckDeclFunc)(CheckerRef checker, const Decl *D,
- AnalysisManager& mgr, BugReporter &BR);
+ typedef CheckerFn<const Decl *, AnalysisManager&, BugReporter &>
+ CheckDeclFunc;
+ typedef CheckerFn<const Stmt *, CheckerContext &> CheckStmtFunc;
+
typedef bool (*HandlesDeclFunc)(const Decl *D);
- void _registerForDecl(CheckerRef checker, CheckDeclFunc checkfn,
- HandlesDeclFunc isForDeclFn);
+ void _registerForDecl(CheckDeclFunc checkfn, HandlesDeclFunc isForDeclFn);
- void _registerForBody(CheckerRef checker, CheckDeclFunc checkfn);
-
- void registerCheckersToEngine(ExprEngine &eng);
+ void _registerForBody(CheckDeclFunc checkfn);
+
+//===----------------------------------------------------------------------===//
+// Internal registration functions for path-sensitive checking.
+//===----------------------------------------------------------------------===//
+
+ typedef CheckerFn<const ObjCMessage &, CheckerContext &> CheckObjCMessageFunc;
+ typedef CheckerFn<const SVal &/*location*/, bool/*isLoad*/, CheckerContext &>
+ CheckLocationFunc;
+ typedef CheckerFn<ExplodedGraph &, BugReporter &, ExprEngine &>
+ CheckEndAnalysisFunc;
+ typedef CheckerFn<EndOfFunctionNodeBuilder &, ExprEngine &> CheckEndPathFunc;
+ typedef CheckerFn<SymbolReaper &, CheckerContext &> CheckDeadSymbolsFunc;
+ typedef CheckerFn<const GRState *, SymbolReaper &> CheckLiveSymbolsFunc;
+
+ typedef bool (*HandlesStmtFunc)(const Stmt *D);
+ void _registerForPreStmt(CheckStmtFunc checkfn,
+ HandlesStmtFunc isForStmtFn);
+ void _registerForPostStmt(CheckStmtFunc checkfn,
+ HandlesStmtFunc isForStmtFn);
+
+ void _registerForPreObjCMessage(CheckObjCMessageFunc checkfn);
+ void _registerForPostObjCMessage(CheckObjCMessageFunc checkfn);
+
+ void _registerForLocation(CheckLocationFunc checkfn);
+
+ void _registerForEndAnalysis(CheckEndAnalysisFunc checkfn);
+
+ void _registerForEndPath(CheckEndPathFunc checkfn);
+
+ void _registerForLiveSymbols(CheckLiveSymbolsFunc checkfn);
+
+ void _registerForDeadSymbols(CheckDeadSymbolsFunc checkfn);
+
+ class CheckRegionChangesFunc {
+ typedef const GRState * (*Func)(void *, const GRState *,
+ const MemRegion * const *,
+ const MemRegion * const *);
+ Func Fn;
+ public:
+ void *Checker;
+ CheckRegionChangesFunc(void *checker, Func fn) : Fn(fn), Checker(checker) {}
+ const GRState *operator()(const GRState *state,
+ const MemRegion * const *begin,
+ const MemRegion * const *end) {
+ return Fn(Checker, state, begin, end);
+ }
+ };
+
+ class WantsRegionChangeUpdateFunc {
+ typedef bool (*Func)(void *, const GRState *);
+ Func Fn;
+ public:
+ void *Checker;
+ WantsRegionChangeUpdateFunc(void *checker, Func fn)
+ : Fn(fn), Checker(checker) { }
+ bool operator()(const GRState *state) {
+ return Fn(Checker, state);
+ }
+ };
+
+ void _registerForRegionChanges(CheckRegionChangesFunc checkfn,
+ WantsRegionChangeUpdateFunc wantUpdateFn);
+
+ class EvalCallFunc {
+ typedef bool (*Func)(void *, const CallExpr *, CheckerContext &);
+ Func Fn;
+ public:
+ void *Checker;
+ EvalCallFunc(void *checker, Func fn) : Fn(fn), Checker(checker) { }
+ bool operator()(const CallExpr *CE, CheckerContext &C) {
+ return Fn(Checker, CE, C);
+ }
+ };
+
+ void _registerForEvalCall(EvalCallFunc checkfn);
+
+//===----------------------------------------------------------------------===//
+// Implementation details.
+//===----------------------------------------------------------------------===//
private:
template <typename CHECKER>
static void destruct(void *obj) { delete static_cast<CHECKER *>(obj); }
- std::vector<RegisterToEngFunc> Funcs;
+ std::vector<CheckerDtor> CheckerDtors;
struct DeclCheckerInfo {
- CheckerRef Checker;
CheckDeclFunc CheckFn;
HandlesDeclFunc IsForDeclFn;
};
std::vector<DeclCheckerInfo> DeclCheckers;
- std::vector<std::pair<CheckerRef, CheckDeclFunc> > BodyCheckers;
-
- typedef void (*Dtor)(void *);
- std::vector<std::pair<CheckerRef, Dtor> > Checkers;
+ std::vector<CheckDeclFunc> BodyCheckers;
- typedef llvm::SmallVector<std::pair<CheckerRef, CheckDeclFunc>, 4>
- CachedDeclCheckers;
+ typedef llvm::SmallVector<CheckDeclFunc, 4> CachedDeclCheckers;
typedef llvm::DenseMap<unsigned, CachedDeclCheckers> CachedDeclCheckersMapTy;
CachedDeclCheckersMapTy CachedDeclCheckersMap;
+
+ struct StmtCheckerInfo {
+ CheckStmtFunc CheckFn;
+ HandlesStmtFunc IsForStmtFn;
+ bool IsPreVisit;
+ };
+ std::vector<StmtCheckerInfo> StmtCheckers;
+
+ struct CachedStmtCheckersKey {
+ unsigned StmtKind;
+ bool IsPreVisit;
+
+ CachedStmtCheckersKey() : StmtKind(0), IsPreVisit(0) { }
+ CachedStmtCheckersKey(unsigned stmtKind, bool isPreVisit)
+ : StmtKind(stmtKind), IsPreVisit(isPreVisit) { }
+
+ static CachedStmtCheckersKey getSentinel() {
+ return CachedStmtCheckersKey(~0U, 0);
+ }
+ unsigned getHashValue() const {
+ llvm::FoldingSetNodeID ID;
+ ID.AddInteger(StmtKind);
+ ID.AddBoolean(IsPreVisit);
+ return ID.ComputeHash();
+ }
+ bool operator==(const CachedStmtCheckersKey &RHS) const {
+ return StmtKind == RHS.StmtKind && IsPreVisit == RHS.IsPreVisit;
+ }
+ };
+ friend struct llvm::DenseMapInfo<CachedStmtCheckersKey>;
+
+ typedef llvm::SmallVector<CheckStmtFunc, 4> CachedStmtCheckers;
+ typedef llvm::DenseMap<CachedStmtCheckersKey, CachedStmtCheckers>
+ CachedStmtCheckersMapTy;
+ CachedStmtCheckersMapTy CachedStmtCheckersMap;
+
+ CachedStmtCheckers *getCachedStmtCheckersFor(const Stmt *S, bool isPreVisit);
+
+ std::vector<CheckObjCMessageFunc> PreObjCMessageCheckers;
+ std::vector<CheckObjCMessageFunc> PostObjCMessageCheckers;
+
+ std::vector<CheckLocationFunc> LocationCheckers;
+
+ std::vector<CheckEndAnalysisFunc> EndAnalysisCheckers;
+
+ std::vector<CheckEndPathFunc> EndPathCheckers;
+
+ std::vector<CheckLiveSymbolsFunc> LiveSymbolsCheckers;
+
+ std::vector<CheckDeadSymbolsFunc> DeadSymbolsCheckers;
+
+ struct RegionChangesCheckerInfo {
+ CheckRegionChangesFunc CheckFn;
+ WantsRegionChangeUpdateFunc WantUpdateFn;
+ };
+ std::vector<RegionChangesCheckerInfo> RegionChangesCheckers;
+
+ std::vector<EvalCallFunc> EvalCallCheckers;
};
} // end ento namespace
} // end clang namespace
+namespace llvm {
+ /// Define DenseMapInfo so that CachedStmtCheckersKey can be used as key
+ /// in DenseMap and DenseSets.
+ template <>
+ struct DenseMapInfo<clang::ento::CheckerManager::CachedStmtCheckersKey> {
+ static inline clang::ento::CheckerManager::CachedStmtCheckersKey
+ getEmptyKey() {
+ return clang::ento::CheckerManager::CachedStmtCheckersKey();
+ }
+ static inline clang::ento::CheckerManager::CachedStmtCheckersKey
+ getTombstoneKey() {
+ return clang::ento::CheckerManager::CachedStmtCheckersKey::getSentinel();
+ }
+
+ static unsigned
+ getHashValue(clang::ento::CheckerManager::CachedStmtCheckersKey S) {
+ return S.getHashValue();
+ }
+
+ static bool isEqual(clang::ento::CheckerManager::CachedStmtCheckersKey LHS,
+ clang::ento::CheckerManager::CachedStmtCheckersKey RHS) {
+ return LHS == RHS;
+ }
+ };
+} // end namespace llvm
+
#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerProvider.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerProvider.h
index 414ad92..40b838e 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerProvider.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerProvider.h
@@ -17,6 +17,10 @@
#include "llvm/ADT/StringRef.h"
#include <vector>
+namespace llvm {
+ class raw_ostream;
+}
+
namespace clang {
namespace ento {
@@ -45,6 +49,7 @@ public:
virtual ~CheckerProvider();
virtual void registerCheckers(CheckerManager &checkerMgr,
CheckerOptInfo *checkOpts, unsigned numCheckOpts) = 0;
+ virtual void printHelp(llvm::raw_ostream &OS) = 0;
};
} // end ento namespace
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerV2.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerV2.h
index 8c96866..e080d19 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerV2.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerV2.h
@@ -41,7 +41,9 @@ class ASTDecl {
public:
template <typename CHECKER>
static void _register(CHECKER *checker, CheckerManager &mgr) {
- mgr._registerForDecl(checker, _checkDecl<CHECKER>, _handlesDecl);
+ mgr._registerForDecl(CheckerManager::CheckDeclFunc(checker,
+ _checkDecl<CHECKER>),
+ _handlesDecl);
}
};
@@ -55,12 +57,197 @@ class ASTCodeBody {
public:
template <typename CHECKER>
static void _register(CHECKER *checker, CheckerManager &mgr) {
- mgr._registerForBody(checker, _checkBody<CHECKER>);
+ mgr._registerForBody(CheckerManager::CheckDeclFunc(checker,
+ _checkBody<CHECKER>));
+ }
+};
+
+template <typename STMT>
+class PreStmt {
+ template <typename CHECKER>
+ static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) {
+ ((const CHECKER *)checker)->checkPreStmt(llvm::cast<STMT>(S), C);
+ }
+
+ static bool _handlesStmt(const Stmt *S) {
+ return llvm::isa<STMT>(S);
+ }
+public:
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr) {
+ mgr._registerForPreStmt(CheckerManager::CheckStmtFunc(checker,
+ _checkStmt<CHECKER>),
+ _handlesStmt);
+ }
+};
+
+template <typename STMT>
+class PostStmt {
+ template <typename CHECKER>
+ static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) {
+ ((const CHECKER *)checker)->checkPostStmt(llvm::cast<STMT>(S), C);
+ }
+
+ static bool _handlesStmt(const Stmt *S) {
+ return llvm::isa<STMT>(S);
+ }
+public:
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr) {
+ mgr._registerForPostStmt(CheckerManager::CheckStmtFunc(checker,
+ _checkStmt<CHECKER>),
+ _handlesStmt);
+ }
+};
+
+class PreObjCMessage {
+ template <typename CHECKER>
+ static void _checkObjCMessage(void *checker, const ObjCMessage &msg,
+ CheckerContext &C) {
+ ((const CHECKER *)checker)->checkPreObjCMessage(msg, C);
+ }
+
+public:
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr) {
+ mgr._registerForPreObjCMessage(
+ CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>));
+ }
+};
+
+class PostObjCMessage {
+ template <typename CHECKER>
+ static void _checkObjCMessage(void *checker, const ObjCMessage &msg,
+ CheckerContext &C) {
+ ((const CHECKER *)checker)->checkPostObjCMessage(msg, C);
+ }
+
+public:
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr) {
+ mgr._registerForPostObjCMessage(
+ CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>));
+ }
+};
+
+class Location {
+ template <typename CHECKER>
+ static void _checkLocation(void *checker, const SVal &location, bool isLoad,
+ CheckerContext &C) {
+ ((const CHECKER *)checker)->checkLocation(location, isLoad, C);
+ }
+
+public:
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr) {
+ mgr._registerForLocation(
+ CheckerManager::CheckLocationFunc(checker, _checkLocation<CHECKER>));
+ }
+};
+
+class EndAnalysis {
+ template <typename CHECKER>
+ static void _checkEndAnalysis(void *checker, ExplodedGraph &G,
+ BugReporter &BR, ExprEngine &Eng) {
+ ((const CHECKER *)checker)->checkEndAnalysis(G, BR, Eng);
+ }
+
+public:
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr) {
+ mgr._registerForEndAnalysis(
+ CheckerManager::CheckEndAnalysisFunc(checker, _checkEndAnalysis<CHECKER>));
+ }
+};
+
+class EndPath {
+ template <typename CHECKER>
+ static void _checkEndPath(void *checker, EndOfFunctionNodeBuilder &B,
+ ExprEngine &Eng) {
+ ((const CHECKER *)checker)->checkEndPath(B, Eng);
+ }
+
+public:
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr) {
+ mgr._registerForEndPath(
+ CheckerManager::CheckEndPathFunc(checker, _checkEndPath<CHECKER>));
+ }
+};
+
+class LiveSymbols {
+ template <typename CHECKER>
+ static void _checkLiveSymbols(void *checker, const GRState *state,
+ SymbolReaper &SR) {
+ ((const CHECKER *)checker)->checkLiveSymbols(state, SR);
+ }
+
+public:
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr) {
+ mgr._registerForLiveSymbols(
+ CheckerManager::CheckLiveSymbolsFunc(checker, _checkLiveSymbols<CHECKER>));
+ }
+};
+
+class DeadSymbols {
+ template <typename CHECKER>
+ static void _checkDeadSymbols(void *checker,
+ SymbolReaper &SR, CheckerContext &C) {
+ ((const CHECKER *)checker)->checkDeadSymbols(SR, C);
+ }
+
+public:
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr) {
+ mgr._registerForDeadSymbols(
+ CheckerManager::CheckDeadSymbolsFunc(checker, _checkDeadSymbols<CHECKER>));
+ }
+};
+
+class RegionChanges {
+ template <typename CHECKER>
+ static const GRState *_checkRegionChanges(void *checker, const GRState *state,
+ const MemRegion * const *Begin,
+ const MemRegion * const *End) {
+ return ((const CHECKER *)checker)->checkRegionChanges(state, Begin, End);
+ }
+ template <typename CHECKER>
+ static bool _wantsRegionChangeUpdate(void *checker, const GRState *state) {
+ return ((const CHECKER *)checker)->wantsRegionChangeUpdate(state);
+ }
+
+public:
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr) {
+ mgr._registerForRegionChanges(
+ CheckerManager::CheckRegionChangesFunc(checker,
+ _checkRegionChanges<CHECKER>),
+ CheckerManager::WantsRegionChangeUpdateFunc(checker,
+ _wantsRegionChangeUpdate<CHECKER>));
}
};
} // end check namespace
+namespace eval {
+
+class Call {
+ template <typename CHECKER>
+ static bool _evalCall(void *checker, const CallExpr *CE, CheckerContext &C) {
+ return ((const CHECKER *)checker)->evalCall(CE, C);
+ }
+
+public:
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr) {
+ mgr._registerForEvalCall(
+ CheckerManager::EvalCallFunc(checker, _evalCall<CHECKER>));
+ }
+};
+
+} // end eval namespace
+
template <typename CHECK1, typename CHECK2=check::_VoidCheck,
typename CHECK3=check::_VoidCheck, typename CHECK4=check::_VoidCheck,
typename CHECK5=check::_VoidCheck, typename CHECK6=check::_VoidCheck,
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Checker.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Checker.h
index 22c2027..627bc0a 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Checker.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Checker.h
@@ -15,8 +15,7 @@
#ifndef LLVM_CLANG_GR_CHECKER
#define LLVM_CLANG_GR_CHECKER
-#include "clang/Analysis/Support/SaveAndRestore.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
//===----------------------------------------------------------------------===//
// Checker interface.
@@ -26,163 +25,6 @@ namespace clang {
namespace ento {
-class CheckerContext {
- ExplodedNodeSet &Dst;
- StmtNodeBuilder &B;
- ExprEngine &Eng;
- ExplodedNode *Pred;
- SaveAndRestore<bool> OldSink;
- const void *checkerTag;
- SaveAndRestore<ProgramPoint::Kind> OldPointKind;
- SaveOr OldHasGen;
- const GRState *ST;
- const Stmt *statement;
- const unsigned size;
-public:
- bool *respondsToCallback;
-public:
- CheckerContext(ExplodedNodeSet &dst, StmtNodeBuilder &builder,
- ExprEngine &eng, ExplodedNode *pred,
- const void *tag, ProgramPoint::Kind K,
- bool *respondsToCB = 0,
- const Stmt *stmt = 0, const GRState *st = 0)
- : Dst(dst), B(builder), Eng(eng), Pred(pred),
- OldSink(B.BuildSinks),
- checkerTag(tag),
- OldPointKind(B.PointKind, K),
- OldHasGen(B.hasGeneratedNode),
- ST(st), statement(stmt), size(Dst.size()),
- respondsToCallback(respondsToCB) {}
-
- ~CheckerContext();
-
- ExprEngine &getEngine() {
- return Eng;
- }
-
- AnalysisManager &getAnalysisManager() {
- return Eng.getAnalysisManager();
- }
-
- ConstraintManager &getConstraintManager() {
- return Eng.getConstraintManager();
- }
-
- StoreManager &getStoreManager() {
- return Eng.getStoreManager();
- }
-
- ExplodedNodeSet &getNodeSet() { return Dst; }
- StmtNodeBuilder &getNodeBuilder() { return B; }
- ExplodedNode *&getPredecessor() { return Pred; }
- const GRState *getState() { return ST ? ST : B.GetState(Pred); }
-
- ASTContext &getASTContext() {
- return Eng.getContext();
- }
-
- BugReporter &getBugReporter() {
- return Eng.getBugReporter();
- }
-
- SourceManager &getSourceManager() {
- return getBugReporter().getSourceManager();
- }
-
- SValBuilder &getSValBuilder() {
- return Eng.getSValBuilder();
- }
-
- ExplodedNode *generateNode(bool autoTransition = true) {
- assert(statement && "Only transitions with statements currently supported");
- ExplodedNode *N = generateNodeImpl(statement, getState(), false,
- checkerTag);
- if (N && autoTransition)
- Dst.Add(N);
- return N;
- }
-
- ExplodedNode *generateNode(const Stmt *stmt, const GRState *state,
- bool autoTransition = true, const void *tag = 0) {
- assert(state);
- ExplodedNode *N = generateNodeImpl(stmt, state, false,
- tag ? tag : checkerTag);
- if (N && autoTransition)
- addTransition(N);
- return N;
- }
-
- ExplodedNode *generateNode(const GRState *state, ExplodedNode *pred,
- bool autoTransition = true) {
- assert(statement && "Only transitions with statements currently supported");
- ExplodedNode *N = generateNodeImpl(statement, state, pred, false);
- if (N && autoTransition)
- addTransition(N);
- return N;
- }
-
- ExplodedNode *generateNode(const GRState *state, bool autoTransition = true,
- const void *tag = 0) {
- assert(statement && "Only transitions with statements currently supported");
- ExplodedNode *N = generateNodeImpl(statement, state, false,
- tag ? tag : checkerTag);
- if (N && autoTransition)
- addTransition(N);
- return N;
- }
-
- ExplodedNode *generateSink(const Stmt *stmt, const GRState *state = 0) {
- return generateNodeImpl(stmt, state ? state : getState(), true,
- checkerTag);
- }
-
- ExplodedNode *generateSink(const GRState *state = 0) {
- assert(statement && "Only transitions with statements currently supported");
- return generateNodeImpl(statement, state ? state : getState(), true,
- checkerTag);
- }
-
- void addTransition(ExplodedNode *node) {
- Dst.Add(node);
- }
-
- void addTransition(const GRState *state, const void *tag = 0) {
- assert(state);
- // If the 'state' is not new, we need to check if the cached state 'ST'
- // is new.
- if (state != getState() || (ST && ST != B.GetState(Pred)))
- // state is new or equals to ST.
- generateNode(state, true, tag);
- else
- Dst.Add(Pred);
- }
-
- void EmitReport(BugReport *R) {
- Eng.getBugReporter().EmitReport(R);
- }
-
- AnalysisContext *getCurrentAnalysisContext() const {
- return Pred->getLocationContext()->getAnalysisContext();
- }
-
-private:
- ExplodedNode *generateNodeImpl(const Stmt* stmt, const GRState *state,
- bool markAsSink, const void *tag) {
- ExplodedNode *node = B.generateNode(stmt, state, Pred, tag);
- if (markAsSink && node)
- node->markAsSink();
- return node;
- }
-
- ExplodedNode *generateNodeImpl(const Stmt* stmt, const GRState *state,
- ExplodedNode *pred, bool markAsSink) {
- ExplodedNode *node = B.generateNode(stmt, state, pred, checkerTag);
- if (markAsSink && node)
- node->markAsSink();
- return node;
- }
-};
-
class Checker {
private:
friend class ExprEngine;
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
new file mode 100644
index 0000000..4429c6b
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
@@ -0,0 +1,187 @@
+//== CheckerContext.h - Context info for path-sensitive checkers--*- C++ -*--=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines CheckerContext that provides contextual info for
+// path-sensitive checkers.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SA_CORE_PATHSENSITIVE_CHECKERCONTEXT
+#define LLVM_CLANG_SA_CORE_PATHSENSITIVE_CHECKERCONTEXT
+
+#include "clang/Analysis/Support/SaveAndRestore.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
+
+namespace clang {
+
+namespace ento {
+
+class CheckerContext {
+ ExplodedNodeSet &Dst;
+ StmtNodeBuilder &B;
+ ExprEngine &Eng;
+ ExplodedNode *Pred;
+ SaveAndRestore<bool> OldSink;
+ const void *checkerTag;
+ SaveAndRestore<ProgramPoint::Kind> OldPointKind;
+ SaveOr OldHasGen;
+ const GRState *ST;
+ const Stmt *statement;
+ const unsigned size;
+public:
+ bool *respondsToCallback;
+public:
+ CheckerContext(ExplodedNodeSet &dst, StmtNodeBuilder &builder,
+ ExprEngine &eng, ExplodedNode *pred,
+ const void *tag, ProgramPoint::Kind K,
+ bool *respondsToCB = 0,
+ const Stmt *stmt = 0, const GRState *st = 0)
+ : Dst(dst), B(builder), Eng(eng), Pred(pred),
+ OldSink(B.BuildSinks),
+ checkerTag(tag),
+ OldPointKind(B.PointKind, K),
+ OldHasGen(B.hasGeneratedNode),
+ ST(st), statement(stmt), size(Dst.size()),
+ respondsToCallback(respondsToCB) {}
+
+ ~CheckerContext();
+
+ ExprEngine &getEngine() {
+ return Eng;
+ }
+
+ AnalysisManager &getAnalysisManager() {
+ return Eng.getAnalysisManager();
+ }
+
+ ConstraintManager &getConstraintManager() {
+ return Eng.getConstraintManager();
+ }
+
+ StoreManager &getStoreManager() {
+ return Eng.getStoreManager();
+ }
+
+ ExplodedNodeSet &getNodeSet() { return Dst; }
+ StmtNodeBuilder &getNodeBuilder() { return B; }
+ ExplodedNode *&getPredecessor() { return Pred; }
+ const GRState *getState() { return ST ? ST : B.GetState(Pred); }
+ const Stmt *getStmt() const { return statement; }
+
+ ASTContext &getASTContext() {
+ return Eng.getContext();
+ }
+
+ BugReporter &getBugReporter() {
+ return Eng.getBugReporter();
+ }
+
+ SourceManager &getSourceManager() {
+ return getBugReporter().getSourceManager();
+ }
+
+ SValBuilder &getSValBuilder() {
+ return Eng.getSValBuilder();
+ }
+
+ ExplodedNode *generateNode(bool autoTransition = true) {
+ assert(statement && "Only transitions with statements currently supported");
+ ExplodedNode *N = generateNodeImpl(statement, getState(), false,
+ checkerTag);
+ if (N && autoTransition)
+ Dst.Add(N);
+ return N;
+ }
+
+ ExplodedNode *generateNode(const Stmt *stmt, const GRState *state,
+ bool autoTransition = true, const void *tag = 0) {
+ assert(state);
+ ExplodedNode *N = generateNodeImpl(stmt, state, false,
+ tag ? tag : checkerTag);
+ if (N && autoTransition)
+ addTransition(N);
+ return N;
+ }
+
+ ExplodedNode *generateNode(const GRState *state, ExplodedNode *pred,
+ bool autoTransition = true) {
+ assert(statement && "Only transitions with statements currently supported");
+ ExplodedNode *N = generateNodeImpl(statement, state, pred, false);
+ if (N && autoTransition)
+ addTransition(N);
+ return N;
+ }
+
+ ExplodedNode *generateNode(const GRState *state, bool autoTransition = true,
+ const void *tag = 0) {
+ assert(statement && "Only transitions with statements currently supported");
+ ExplodedNode *N = generateNodeImpl(statement, state, false,
+ tag ? tag : checkerTag);
+ if (N && autoTransition)
+ addTransition(N);
+ return N;
+ }
+
+ ExplodedNode *generateSink(const Stmt *stmt, const GRState *state = 0) {
+ return generateNodeImpl(stmt, state ? state : getState(), true,
+ checkerTag);
+ }
+
+ ExplodedNode *generateSink(const GRState *state = 0) {
+ assert(statement && "Only transitions with statements currently supported");
+ return generateNodeImpl(statement, state ? state : getState(), true,
+ checkerTag);
+ }
+
+ void addTransition(ExplodedNode *node) {
+ Dst.Add(node);
+ }
+
+ void addTransition(const GRState *state, const void *tag = 0) {
+ assert(state);
+ // If the 'state' is not new, we need to check if the cached state 'ST'
+ // is new.
+ if (state != getState() || (ST && ST != B.GetState(Pred)))
+ // state is new or equals to ST.
+ generateNode(state, true, tag);
+ else
+ Dst.Add(Pred);
+ }
+
+ void EmitReport(BugReport *R) {
+ Eng.getBugReporter().EmitReport(R);
+ }
+
+ AnalysisContext *getCurrentAnalysisContext() const {
+ return Pred->getLocationContext()->getAnalysisContext();
+ }
+
+private:
+ ExplodedNode *generateNodeImpl(const Stmt* stmt, const GRState *state,
+ bool markAsSink, const void *tag) {
+ ExplodedNode *node = B.generateNode(stmt, state, Pred, tag);
+ if (markAsSink && node)
+ node->markAsSink();
+ return node;
+ }
+
+ ExplodedNode *generateNodeImpl(const Stmt* stmt, const GRState *state,
+ ExplodedNode *pred, bool markAsSink) {
+ ExplodedNode *node = B.generateNode(stmt, state, pred, checkerTag);
+ if (markAsSink && node)
+ node->markAsSink();
+ return node;
+ }
+};
+
+} // end GR namespace
+
+} // end clang namespace
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
index 800e63a..25c6447 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
@@ -447,16 +447,22 @@ class EndOfFunctionNodeBuilder {
CoreEngine &Eng;
const CFGBlock& B;
ExplodedNode* Pred;
+ void *Tag;
public:
bool hasGeneratedNode;
public:
- EndOfFunctionNodeBuilder(const CFGBlock* b, ExplodedNode* N, CoreEngine* e)
- : Eng(*e), B(*b), Pred(N), hasGeneratedNode(false) {}
+ EndOfFunctionNodeBuilder(const CFGBlock* b, ExplodedNode* N, CoreEngine* e,
+ void *checkerTag = 0)
+ : Eng(*e), B(*b), Pred(N), Tag(checkerTag), hasGeneratedNode(false) {}
~EndOfFunctionNodeBuilder();
+ EndOfFunctionNodeBuilder withCheckerTag(void *tag) {
+ return EndOfFunctionNodeBuilder(&B, Pred, &Eng, tag);
+ }
+
WorkList &getWorkList() { return *Eng.WList; }
ExplodedNode* getPredecessor() const { return Pred; }
@@ -471,8 +477,8 @@ public:
B.getBlockID());
}
- ExplodedNode* generateNode(const GRState* State, const void *tag = 0,
- ExplodedNode *P = 0);
+ ExplodedNode* generateNode(const GRState* State, ExplodedNode *P = 0,
+ const void *tag = 0);
void GenerateCallExitNode(const GRState *state);
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
index 767644a..16f54ee 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
@@ -137,6 +137,10 @@ public:
virtual AnalysisManager &getAnalysisManager() { return AMgr; }
+ CheckerManager &getCheckerManager() const {
+ return *AMgr.getCheckerManager();
+ }
+
SValBuilder &getSValBuilder() { return svalBuilder; }
TransferFuncs& getTF() { return *TF; }
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h
index 411441f..07cdbf5 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h
@@ -151,7 +151,21 @@ namespace ento {
typedef bool data_type;
static inline data_type MakeData(void* const* p) {
- return (bool) (uintptr_t) p;
+ return p ? (data_type) (uintptr_t) *p
+ : data_type();
+ }
+ static inline void *MakeVoidPtr(data_type d) {
+ return (void*) (uintptr_t) d;
+ }
+ };
+
+ // Partial specialization for unsigned.
+ template <> struct GRStatePartialTrait<unsigned> {
+ typedef unsigned data_type;
+
+ static inline data_type MakeData(void* const* p) {
+ return p ? (data_type) (uintptr_t) *p
+ : data_type();
}
static inline void *MakeVoidPtr(data_type d) {
return (void*) (uintptr_t) d;
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h
index 4c3e379..9d6298f 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h
@@ -12,12 +12,15 @@
namespace clang {
class AnalyzerOptions;
+ class LangOptions;
class Diagnostic;
namespace ento {
class CheckerManager;
-CheckerManager *registerCheckers(const AnalyzerOptions &opts,Diagnostic &diags);
+CheckerManager *registerCheckers(const AnalyzerOptions &opts,
+ const LangOptions &langOpts,
+ Diagnostic &diags);
} // end ento namespace
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/FrontendActions.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/FrontendActions.h
index e3867a2..f014181 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/FrontendActions.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/FrontendActions.h
@@ -26,6 +26,8 @@ protected:
llvm::StringRef InFile);
};
+void printCheckerHelp(llvm::raw_ostream &OS);
+
} // end GR namespace
} // end namespace clang
diff --git a/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp b/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp
index 945dfb8..9c24550 100644
--- a/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp
@@ -205,7 +205,7 @@ ASTContext::ASTContext(const LangOptions& LOpts, SourceManager &SM,
DeclarationNames(*this),
ExternalSource(0), Listener(0), PrintingPolicy(LOpts),
LastSDM(0, 0),
- UniqueBlockByRefTypeID(0), UniqueBlockParmTypeID(0) {
+ UniqueBlockByRefTypeID(0) {
ObjCIdRedefinitionType = QualType();
ObjCClassRedefinitionType = QualType();
ObjCSelRedefinitionType = QualType();
@@ -874,7 +874,7 @@ ASTContext::getTypeInfo(const Type *T) const {
case Type::Auto: {
const AutoType *A = cast<AutoType>(T);
assert(A->isDeduced() && "Cannot request the size of a dependent type");
- return getTypeInfo(cast<AutoType>(T)->getDeducedType().getTypePtr());
+ return getTypeInfo(A->getDeducedType().getTypePtr());
}
case Type::Paren:
@@ -2683,12 +2683,22 @@ QualType ASTContext::getDecltypeType(Expr *e) const {
return QualType(dt, 0);
}
-/// getAutoType - Unlike many "get<Type>" functions, we don't unique
-/// AutoType AST's.
+/// getAutoType - We only unique auto types after they've been deduced.
QualType ASTContext::getAutoType(QualType DeducedType) const {
- AutoType *at = new (*this, TypeAlignment) AutoType(DeducedType);
- Types.push_back(at);
- return QualType(at, 0);
+ void *InsertPos = 0;
+ if (!DeducedType.isNull()) {
+ // Look in the folding set for an existing type.
+ llvm::FoldingSetNodeID ID;
+ AutoType::Profile(ID, DeducedType);
+ if (AutoType *AT = AutoTypes.FindNodeOrInsertPos(ID, InsertPos))
+ return QualType(AT, 0);
+ }
+
+ AutoType *AT = new (*this, TypeAlignment) AutoType(DeducedType);
+ Types.push_back(AT);
+ if (InsertPos)
+ AutoTypes.InsertNode(AT, InsertPos);
+ return QualType(AT, 0);
}
/// getTagDeclType - Return the unique reference to the type for the
@@ -2971,7 +2981,15 @@ ASTContext::getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) const {
case NestedNameSpecifier::Namespace:
// A namespace is canonical; build a nested-name-specifier with
// this namespace and no prefix.
- return NestedNameSpecifier::Create(*this, 0, NNS->getAsNamespace());
+ return NestedNameSpecifier::Create(*this, 0,
+ NNS->getAsNamespace()->getOriginalNamespace());
+
+ case NestedNameSpecifier::NamespaceAlias:
+ // A namespace is canonical; build a nested-name-specifier with
+ // this namespace and no prefix.
+ return NestedNameSpecifier::Create(*this, 0,
+ NNS->getAsNamespaceAlias()->getNamespace()
+ ->getOriginalNamespace());
case NestedNameSpecifier::TypeSpec:
case NestedNameSpecifier::TypeSpecWithTemplate: {
@@ -3609,78 +3627,6 @@ ASTContext::BuildByRefType(llvm::StringRef DeclName, QualType Ty) const {
return getPointerType(getTagDeclType(T));
}
-
-QualType ASTContext::getBlockParmType(
- bool BlockHasCopyDispose,
- llvm::SmallVectorImpl<const Expr *> &Layout) const {
-
- // FIXME: Move up
- llvm::SmallString<36> Name;
- llvm::raw_svector_ostream(Name) << "__block_literal_"
- << ++UniqueBlockParmTypeID;
- RecordDecl *T;
- T = CreateRecordDecl(*this, TTK_Struct, TUDecl, SourceLocation(),
- &Idents.get(Name.str()));
- T->startDefinition();
- QualType FieldTypes[] = {
- getPointerType(VoidPtrTy),
- IntTy,
- IntTy,
- getPointerType(VoidPtrTy),
- (BlockHasCopyDispose ?
- getPointerType(getBlockDescriptorExtendedType()) :
- getPointerType(getBlockDescriptorType()))
- };
-
- const char *FieldNames[] = {
- "__isa",
- "__flags",
- "__reserved",
- "__FuncPtr",
- "__descriptor"
- };
-
- for (size_t i = 0; i < 5; ++i) {
- FieldDecl *Field = FieldDecl::Create(*this, T, SourceLocation(),
- &Idents.get(FieldNames[i]),
- FieldTypes[i], /*TInfo=*/0,
- /*BitWidth=*/0, /*Mutable=*/false);
- Field->setAccess(AS_public);
- T->addDecl(Field);
- }
-
- for (unsigned i = 0; i < Layout.size(); ++i) {
- const Expr *E = Layout[i];
-
- QualType FieldType = E->getType();
- IdentifierInfo *FieldName = 0;
- if (isa<CXXThisExpr>(E)) {
- FieldName = &Idents.get("this");
- } else if (const BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(E)) {
- const ValueDecl *D = BDRE->getDecl();
- FieldName = D->getIdentifier();
- if (BDRE->isByRef())
- FieldType = BuildByRefType(D->getName(), FieldType);
- } else {
- // Padding.
- assert(isa<ConstantArrayType>(FieldType) &&
- isa<DeclRefExpr>(E) &&
- !cast<DeclRefExpr>(E)->getDecl()->getDeclName() &&
- "doesn't match characteristics of padding decl");
- }
-
- FieldDecl *Field = FieldDecl::Create(*this, T, SourceLocation(),
- FieldName, FieldType, /*TInfo=*/0,
- /*BitWidth=*/0, /*Mutable=*/false);
- Field->setAccess(AS_public);
- T->addDecl(Field);
- }
-
- T->completeDefinition();
-
- return getPointerType(getTagDeclType(T));
-}
-
void ASTContext::setObjCFastEnumerationStateType(QualType T) {
const RecordType *Rec = T->getAs<RecordType>();
assert(Rec && "Invalid ObjCFAstEnumerationStateType");
diff --git a/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp b/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp
index 65c0a3b..21f10fb 100644
--- a/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp
@@ -2097,11 +2097,7 @@ Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) {
D->isScoped(), D->isScopedUsingClassTag(),
D->isFixed());
// Import the qualifier, if any.
- if (D->getQualifier()) {
- NestedNameSpecifier *NNS = Importer.Import(D->getQualifier());
- SourceRange NNSRange = Importer.Import(D->getQualifierRange());
- D2->setQualifierInfo(NNS, NNSRange);
- }
+ D2->setQualifierInfo(Importer.Import(D->getQualifierLoc()));
D2->setAccess(D->getAccess());
D2->setLexicalDeclContext(LexicalDC);
Importer.Imported(D, D2);
@@ -2225,12 +2221,8 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) {
Name.getAsIdentifierInfo(),
Importer.Import(D->getTagKeywordLoc()));
}
- // Import the qualifier, if any.
- if (D->getQualifier()) {
- NestedNameSpecifier *NNS = Importer.Import(D->getQualifier());
- SourceRange NNSRange = Importer.Import(D->getQualifierRange());
- D2->setQualifierInfo(NNS, NNSRange);
- }
+
+ D2->setQualifierInfo(Importer.Import(D->getQualifierLoc()));
D2->setLexicalDeclContext(LexicalDC);
LexicalDC->addDecl(D2);
}
@@ -2408,11 +2400,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
}
// Import the qualifier, if any.
- if (D->getQualifier()) {
- NestedNameSpecifier *NNS = Importer.Import(D->getQualifier());
- SourceRange NNSRange = Importer.Import(D->getQualifierRange());
- ToFunction->setQualifierInfo(NNS, NNSRange);
- }
+ ToFunction->setQualifierInfo(Importer.Import(D->getQualifierLoc()));
ToFunction->setAccess(D->getAccess());
ToFunction->setLexicalDeclContext(LexicalDC);
ToFunction->setVirtualAsWritten(D->isVirtualAsWritten());
@@ -2666,12 +2654,7 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) {
Name.getAsIdentifierInfo(), T, TInfo,
D->getStorageClass(),
D->getStorageClassAsWritten());
- // Import the qualifier, if any.
- if (D->getQualifier()) {
- NestedNameSpecifier *NNS = Importer.Import(D->getQualifier());
- SourceRange NNSRange = Importer.Import(D->getQualifierRange());
- ToVar->setQualifierInfo(NNS, NNSRange);
- }
+ ToVar->setQualifierInfo(Importer.Import(D->getQualifierLoc()));
ToVar->setAccess(D->getAccess());
ToVar->setLexicalDeclContext(LexicalDC);
Importer.Imported(D, ToVar);
@@ -3591,14 +3574,7 @@ Decl *ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
Name.getAsIdentifierInfo(),
Importer.Import(DTemplated->getTagKeywordLoc()));
D2Templated->setAccess(DTemplated->getAccess());
-
-
- // Import the qualifier, if any.
- if (DTemplated->getQualifier()) {
- NestedNameSpecifier *NNS = Importer.Import(DTemplated->getQualifier());
- SourceRange NNSRange = Importer.Import(DTemplated->getQualifierRange());
- D2Templated->setQualifierInfo(NNS, NNSRange);
- }
+ D2Templated->setQualifierInfo(Importer.Import(DTemplated->getQualifierLoc()));
D2Templated->setLexicalDeclContext(LexicalDC);
// Create the class template declaration itself.
@@ -3703,12 +3679,7 @@ Decl *ASTNodeImporter::VisitClassTemplateSpecializationDecl(
ClassTemplate->AddSpecialization(D2, InsertPos);
// Import the qualifier, if any.
- if (D->getQualifier()) {
- NestedNameSpecifier *NNS = Importer.Import(D->getQualifier());
- SourceRange NNSRange = Importer.Import(D->getQualifierRange());
- D2->setQualifierInfo(NNS, NNSRange);
- }
-
+ D2->setQualifierInfo(Importer.Import(D->getQualifierLoc()));
// Add the specialization to this context.
D2->setLexicalDeclContext(LexicalDC);
@@ -4067,6 +4038,11 @@ NestedNameSpecifier *ASTImporter::Import(NestedNameSpecifier *FromNNS) {
return 0;
}
+NestedNameSpecifierLoc ASTImporter::Import(NestedNameSpecifierLoc FromNNS) {
+ // FIXME: Implement!
+ return NestedNameSpecifierLoc();
+}
+
TemplateName ASTImporter::Import(TemplateName From) {
switch (From.getKind()) {
case TemplateName::Template:
diff --git a/contrib/llvm/tools/clang/lib/AST/Decl.cpp b/contrib/llvm/tools/clang/lib/AST/Decl.cpp
index 56db8c7..73fe117 100644
--- a/contrib/llvm/tools/clang/lib/AST/Decl.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/Decl.cpp
@@ -266,8 +266,12 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) {
return LinkageInfo::internal();
}
- if (D->isInAnonymousNamespace())
- return LinkageInfo::uniqueExternal();
+ if (D->isInAnonymousNamespace()) {
+ const VarDecl *Var = dyn_cast<VarDecl>(D);
+ const FunctionDecl *Func = dyn_cast<FunctionDecl>(D);
+ if ((!Var || !Var->isExternC()) && (!Func || !Func->isExternC()))
+ return LinkageInfo::uniqueExternal();
+ }
// Set up the defaults.
@@ -704,7 +708,7 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, LVFlags Flags) {
// external linkage.
if (D->getLexicalDeclContext()->isFunctionOrMethod()) {
if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
- if (Function->isInAnonymousNamespace())
+ if (Function->isInAnonymousNamespace() && !Function->isExternC())
return LinkageInfo::uniqueExternal();
LinkageInfo LV;
@@ -725,7 +729,7 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, LVFlags Flags) {
if (const VarDecl *Var = dyn_cast<VarDecl>(D))
if (Var->getStorageClass() == SC_Extern ||
Var->getStorageClass() == SC_PrivateExtern) {
- if (Var->isInAnonymousNamespace())
+ if (Var->isInAnonymousNamespace() && !Var->isExternC())
return LinkageInfo::uniqueExternal();
LinkageInfo LV;
@@ -837,8 +841,10 @@ bool NamedDecl::declarationReplaces(NamedDecl *OldD) const {
// UsingDirectiveDecl's are not really NamedDecl's, and all have same name.
// We want to keep it, unless it nominates same namespace.
if (getKind() == Decl::UsingDirective) {
- return cast<UsingDirectiveDecl>(this)->getNominatedNamespace() ==
- cast<UsingDirectiveDecl>(OldD)->getNominatedNamespace();
+ return cast<UsingDirectiveDecl>(this)->getNominatedNamespace()
+ ->getOriginalNamespace() ==
+ cast<UsingDirectiveDecl>(OldD)->getNominatedNamespace()
+ ->getOriginalNamespace();
}
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(this))
@@ -864,9 +870,13 @@ bool NamedDecl::declarationReplaces(NamedDecl *OldD) const {
return cast<UsingShadowDecl>(this)->getTargetDecl() ==
cast<UsingShadowDecl>(OldD)->getTargetDecl();
- if (isa<UsingDecl>(this) && isa<UsingDecl>(OldD))
- return cast<UsingDecl>(this)->getTargetNestedNameDecl() ==
- cast<UsingDecl>(OldD)->getTargetNestedNameDecl();
+ if (isa<UsingDecl>(this) && isa<UsingDecl>(OldD)) {
+ ASTContext &Context = getASTContext();
+ return Context.getCanonicalNestedNameSpecifier(
+ cast<UsingDecl>(this)->getQualifier()) ==
+ Context.getCanonicalNestedNameSpecifier(
+ cast<UsingDecl>(OldD)->getQualifier());
+ }
// For non-function declarations, if the declarations are of the
// same kind then this must be a redeclaration, or semantic analysis
@@ -927,9 +937,8 @@ SourceLocation DeclaratorDecl::getTypeSpecStartLoc() const {
return SourceLocation();
}
-void DeclaratorDecl::setQualifierInfo(NestedNameSpecifier *Qualifier,
- SourceRange QualifierRange) {
- if (Qualifier) {
+void DeclaratorDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) {
+ if (QualifierLoc) {
// Make sure the extended decl info is allocated.
if (!hasExtInfo()) {
// Save (non-extended) type source info pointer.
@@ -940,12 +949,10 @@ void DeclaratorDecl::setQualifierInfo(NestedNameSpecifier *Qualifier,
getExtInfo()->TInfo = savedTInfo;
}
// Set qualifier info.
- getExtInfo()->NNS = Qualifier;
- getExtInfo()->NNSRange = QualifierRange;
+ getExtInfo()->QualifierLoc = QualifierLoc;
}
else {
// Here Qualifier == 0, i.e., we are removing the qualifier (if any).
- assert(QualifierRange.isInvalid());
if (hasExtInfo()) {
// Save type source info pointer.
TypeSourceInfo *savedTInfo = getExtInfo()->TInfo;
@@ -967,7 +974,7 @@ QualifierInfo::setTemplateParameterListsInfo(ASTContext &Context,
TemplateParameterList **TPLists) {
assert((NumTPLists == 0 || TPLists != 0) &&
"Empty array of template parameters with positive size!");
- assert((NumTPLists == 0 || NNS) &&
+ assert((NumTPLists == 0 || QualifierLoc) &&
"Nonempty array of template parameters with no qualifier!");
// Free previous template parameters (if any).
@@ -1037,8 +1044,11 @@ bool VarDecl::isExternC() const {
getStorageClass() != SC_Static) ||
(getDeclContext()->isFunctionOrMethod() && hasExternalStorage());
- for (const DeclContext *DC = getDeclContext(); !DC->isTranslationUnit();
- DC = DC->getParent()) {
+ const DeclContext *DC = getDeclContext();
+ if (DC->isFunctionOrMethod())
+ return false;
+
+ for (; !DC->isTranslationUnit(); DC = DC->getParent()) {
if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC)) {
if (Linkage->getLanguage() == LinkageSpecDecl::lang_c)
return getStorageClass() != SC_Static;
@@ -1046,8 +1056,6 @@ bool VarDecl::isExternC() const {
break;
}
- if (DC->isFunctionOrMethod())
- return false;
}
return false;
@@ -1363,8 +1371,11 @@ bool FunctionDecl::isExternC() const {
if (!Context.getLangOptions().CPlusPlus)
return getStorageClass() != SC_Static && !getAttr<OverloadableAttr>();
- for (const DeclContext *DC = getDeclContext(); !DC->isTranslationUnit();
- DC = DC->getParent()) {
+ const DeclContext *DC = getDeclContext();
+ if (DC->isRecord())
+ return false;
+
+ for (; !DC->isTranslationUnit(); DC = DC->getParent()) {
if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC)) {
if (Linkage->getLanguage() == LinkageSpecDecl::lang_c)
return getStorageClass() != SC_Static &&
@@ -1372,9 +1383,6 @@ bool FunctionDecl::isExternC() const {
break;
}
-
- if (DC->isRecord())
- break;
}
return isMain();
@@ -2018,19 +2026,16 @@ TagDecl* TagDecl::getDefinition() const {
return 0;
}
-void TagDecl::setQualifierInfo(NestedNameSpecifier *Qualifier,
- SourceRange QualifierRange) {
- if (Qualifier) {
+void TagDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) {
+ if (QualifierLoc) {
// Make sure the extended qualifier info is allocated.
if (!hasExtInfo())
TypedefDeclOrQualifier = new (getASTContext()) ExtInfo;
// Set qualifier info.
- getExtInfo()->NNS = Qualifier;
- getExtInfo()->NNSRange = QualifierRange;
+ getExtInfo()->QualifierLoc = QualifierLoc;
}
else {
// Here Qualifier == 0, i.e., we are removing the qualifier (if any).
- assert(QualifierRange.isInvalid());
if (hasExtInfo()) {
getASTContext().Deallocate(getExtInfo());
TypedefDeclOrQualifier = (TypedefDecl*) 0;
@@ -2211,8 +2216,10 @@ NamespaceDecl *NamespaceDecl::getNextNamespace() {
}
ImplicitParamDecl *ImplicitParamDecl::Create(ASTContext &C, DeclContext *DC,
- SourceLocation L, IdentifierInfo *Id, QualType T) {
- return new (C) ImplicitParamDecl(ImplicitParam, DC, L, Id, T);
+ SourceLocation loc,
+ IdentifierInfo *name,
+ QualType type) {
+ return new (C) ImplicitParamDecl(DC, loc, name, type);
}
FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC,
diff --git a/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp b/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp
index be379d5..81df00d 100644
--- a/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp
@@ -465,6 +465,22 @@ void Decl::CheckAccessDeclContext() const {
#endif
}
+DeclContext *Decl::getNonClosureContext() {
+ DeclContext *DC = getDeclContext();
+
+ // This is basically "while (DC->isClosure()) DC = DC->getParent();"
+ // except that it's significantly more efficient to cast to a known
+ // decl type and call getDeclContext() than to call getParent().
+ do {
+ if (isa<BlockDecl>(DC)) {
+ DC = cast<BlockDecl>(DC)->getDeclContext();
+ continue;
+ }
+ } while (false);
+
+ assert(!DC->isClosure());
+ return DC;
+}
//===----------------------------------------------------------------------===//
// DeclContext Implementation
diff --git a/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp b/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp
index fba73f5..46768c1 100644
--- a/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp
@@ -1267,15 +1267,14 @@ LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C,
UsingDirectiveDecl *UsingDirectiveDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
SourceLocation NamespaceLoc,
- SourceRange QualifierRange,
- NestedNameSpecifier *Qualifier,
+ NestedNameSpecifierLoc QualifierLoc,
SourceLocation IdentLoc,
NamedDecl *Used,
DeclContext *CommonAncestor) {
if (NamespaceDecl *NS = dyn_cast_or_null<NamespaceDecl>(Used))
Used = NS->getOriginalNamespace();
- return new (C) UsingDirectiveDecl(DC, L, NamespaceLoc, QualifierRange,
- Qualifier, IdentLoc, Used, CommonAncestor);
+ return new (C) UsingDirectiveDecl(DC, L, NamespaceLoc, QualifierLoc,
+ IdentLoc, Used, CommonAncestor);
}
NamespaceDecl *UsingDirectiveDecl::getNominatedNamespace() {
@@ -1289,14 +1288,13 @@ NamespaceAliasDecl *NamespaceAliasDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation UsingLoc,
SourceLocation AliasLoc,
IdentifierInfo *Alias,
- SourceRange QualifierRange,
- NestedNameSpecifier *Qualifier,
+ NestedNameSpecifierLoc QualifierLoc,
SourceLocation IdentLoc,
NamedDecl *Namespace) {
if (NamespaceDecl *NS = dyn_cast_or_null<NamespaceDecl>(Namespace))
Namespace = NS->getOriginalNamespace();
- return new (C) NamespaceAliasDecl(DC, UsingLoc, AliasLoc, Alias, QualifierRange,
- Qualifier, IdentLoc, Namespace);
+ return new (C) NamespaceAliasDecl(DC, UsingLoc, AliasLoc, Alias,
+ QualifierLoc, IdentLoc, Namespace);
}
UsingDecl *UsingShadowDecl::getUsingDecl() const {
@@ -1337,35 +1335,31 @@ void UsingDecl::removeShadowDecl(UsingShadowDecl *S) {
S->UsingOrNextShadow = this;
}
-UsingDecl *UsingDecl::Create(ASTContext &C, DeclContext *DC,
- SourceRange NNR, SourceLocation UL,
- NestedNameSpecifier* TargetNNS,
+UsingDecl *UsingDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation UL,
+ NestedNameSpecifierLoc QualifierLoc,
const DeclarationNameInfo &NameInfo,
bool IsTypeNameArg) {
- return new (C) UsingDecl(DC, NNR, UL, TargetNNS, NameInfo, IsTypeNameArg);
+ return new (C) UsingDecl(DC, UL, QualifierLoc, NameInfo, IsTypeNameArg);
}
UnresolvedUsingValueDecl *
UnresolvedUsingValueDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation UsingLoc,
- SourceRange TargetNNR,
- NestedNameSpecifier *TargetNNS,
+ NestedNameSpecifierLoc QualifierLoc,
const DeclarationNameInfo &NameInfo) {
return new (C) UnresolvedUsingValueDecl(DC, C.DependentTy, UsingLoc,
- TargetNNR, TargetNNS, NameInfo);
+ QualifierLoc, NameInfo);
}
UnresolvedUsingTypenameDecl *
UnresolvedUsingTypenameDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation UsingLoc,
SourceLocation TypenameLoc,
- SourceRange TargetNNR,
- NestedNameSpecifier *TargetNNS,
+ NestedNameSpecifierLoc QualifierLoc,
SourceLocation TargetNameLoc,
DeclarationName TargetName) {
return new (C) UnresolvedUsingTypenameDecl(DC, UsingLoc, TypenameLoc,
- TargetNNR, TargetNNS,
- TargetNameLoc,
+ QualifierLoc, TargetNameLoc,
TargetName.getAsIdentifierInfo());
}
diff --git a/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp b/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp
index 77b4257..c6ae128 100644
--- a/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp
@@ -918,20 +918,20 @@ void DeclPrinter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *PID) {
void DeclPrinter::VisitUsingDecl(UsingDecl *D) {
Out << "using ";
- D->getTargetNestedNameDecl()->print(Out, Policy);
+ D->getQualifier()->print(Out, Policy);
Out << D;
}
void
DeclPrinter::VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) {
Out << "using typename ";
- D->getTargetNestedNameSpecifier()->print(Out, Policy);
+ D->getQualifier()->print(Out, Policy);
Out << D->getDeclName();
}
void DeclPrinter::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
Out << "using ";
- D->getTargetNestedNameSpecifier()->print(Out, Policy);
+ D->getQualifier()->print(Out, Policy);
Out << D->getDeclName();
}
diff --git a/contrib/llvm/tools/clang/lib/AST/Expr.cpp b/contrib/llvm/tools/clang/lib/AST/Expr.cpp
index 391b26a..1c1061b 100644
--- a/contrib/llvm/tools/clang/lib/AST/Expr.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/Expr.cpp
@@ -836,6 +836,19 @@ QualType CallExpr::getCallReturnType() const {
return FnType->getResultType();
}
+SourceRange CallExpr::getSourceRange() const {
+ if (isa<CXXOperatorCallExpr>(this))
+ return cast<CXXOperatorCallExpr>(this)->getSourceRange();
+
+ SourceLocation begin = getCallee()->getLocStart();
+ if (begin.isInvalid() && getNumArgs() > 0)
+ begin = getArg(0)->getLocStart();
+ SourceLocation end = getRParenLoc();
+ if (end.isInvalid() && getNumArgs() > 0)
+ end = getArg(getNumArgs() - 1)->getLocEnd();
+ return SourceRange(begin, end);
+}
+
OffsetOfExpr *OffsetOfExpr::Create(ASTContext &C, QualType type,
SourceLocation OperatorLoc,
TypeSourceInfo *tsi,
diff --git a/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp b/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp
index 28ff9fb..4f4a6b4 100644
--- a/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp
@@ -128,10 +128,10 @@ PseudoDestructorTypeStorage::PseudoDestructorTypeStorage(TypeSourceInfo *Info)
}
CXXPseudoDestructorExpr::CXXPseudoDestructorExpr(ASTContext &Context,
- Expr *Base, bool isArrow, SourceLocation OperatorLoc,
- NestedNameSpecifier *Qualifier, SourceRange QualifierRange,
- TypeSourceInfo *ScopeType, SourceLocation ColonColonLoc,
- SourceLocation TildeLoc, PseudoDestructorTypeStorage DestroyedType)
+ Expr *Base, bool isArrow, SourceLocation OperatorLoc,
+ NestedNameSpecifierLoc QualifierLoc, TypeSourceInfo *ScopeType,
+ SourceLocation ColonColonLoc, SourceLocation TildeLoc,
+ PseudoDestructorTypeStorage DestroyedType)
: Expr(CXXPseudoDestructorExprClass,
Context.getPointerType(Context.getFunctionType(Context.VoidTy, 0, 0,
FunctionProtoType::ExtProtoInfo())),
@@ -142,15 +142,16 @@ CXXPseudoDestructorExpr::CXXPseudoDestructorExpr(ASTContext &Context,
/*isValueDependent=*/Base->isValueDependent(),
// ContainsUnexpandedParameterPack
(Base->containsUnexpandedParameterPack() ||
- (Qualifier && Qualifier->containsUnexpandedParameterPack()) ||
+ (QualifierLoc &&
+ QualifierLoc.getNestedNameSpecifier()
+ ->containsUnexpandedParameterPack()) ||
(ScopeType &&
ScopeType->getType()->containsUnexpandedParameterPack()) ||
(DestroyedType.getTypeSourceInfo() &&
DestroyedType.getTypeSourceInfo()->getType()
->containsUnexpandedParameterPack()))),
Base(static_cast<Stmt *>(Base)), IsArrow(isArrow),
- OperatorLoc(OperatorLoc), Qualifier(Qualifier),
- QualifierRange(QualifierRange),
+ OperatorLoc(OperatorLoc), QualifierLoc(QualifierLoc),
ScopeType(ScopeType), ColonColonLoc(ColonColonLoc), TildeLoc(TildeLoc),
DestroyedType(DestroyedType) { }
@@ -282,15 +283,16 @@ CXXRecordDecl *OverloadExpr::getNamingClass() const {
// DependentScopeDeclRefExpr
DependentScopeDeclRefExpr::DependentScopeDeclRefExpr(QualType T,
- NestedNameSpecifier *Qualifier,
- SourceRange QualifierRange,
+ NestedNameSpecifierLoc QualifierLoc,
const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *Args)
: Expr(DependentScopeDeclRefExprClass, T, VK_LValue, OK_Ordinary,
true, true,
(NameInfo.containsUnexpandedParameterPack() ||
- (Qualifier && Qualifier->containsUnexpandedParameterPack()))),
- NameInfo(NameInfo), QualifierRange(QualifierRange), Qualifier(Qualifier),
+ (QualifierLoc &&
+ QualifierLoc.getNestedNameSpecifier()
+ ->containsUnexpandedParameterPack()))),
+ QualifierLoc(QualifierLoc), NameInfo(NameInfo),
HasExplicitTemplateArgs(Args != 0)
{
if (Args) {
@@ -306,16 +308,14 @@ DependentScopeDeclRefExpr::DependentScopeDeclRefExpr(QualType T,
DependentScopeDeclRefExpr *
DependentScopeDeclRefExpr::Create(ASTContext &C,
- NestedNameSpecifier *Qualifier,
- SourceRange QualifierRange,
+ NestedNameSpecifierLoc QualifierLoc,
const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *Args) {
std::size_t size = sizeof(DependentScopeDeclRefExpr);
if (Args)
size += ExplicitTemplateArgumentList::sizeFor(*Args);
void *Mem = C.Allocate(size);
- return new (Mem) DependentScopeDeclRefExpr(C.DependentTy,
- Qualifier, QualifierRange,
+ return new (Mem) DependentScopeDeclRefExpr(C.DependentTy, QualifierLoc,
NameInfo, Args);
}
@@ -328,13 +328,16 @@ DependentScopeDeclRefExpr::CreateEmpty(ASTContext &C,
size += ExplicitTemplateArgumentList::sizeFor(NumTemplateArgs);
void *Mem = C.Allocate(size);
DependentScopeDeclRefExpr *E
- = new (Mem) DependentScopeDeclRefExpr(QualType(), 0, SourceRange(),
+ = new (Mem) DependentScopeDeclRefExpr(QualType(), NestedNameSpecifierLoc(),
DeclarationNameInfo(), 0);
E->HasExplicitTemplateArgs = HasExplicitTemplateArgs;
return E;
}
SourceRange CXXConstructExpr::getSourceRange() const {
+ if (isa<CXXTemporaryObjectExpr>(this))
+ return cast<CXXTemporaryObjectExpr>(this)->getSourceRange();
+
if (ParenRange.isValid())
return SourceRange(Loc, ParenRange.getEnd());
@@ -397,13 +400,6 @@ CXXRecordDecl *CXXMemberCallExpr::getRecordDecl() {
return ThisArg->getType()->getAsCXXRecordDecl();
}
-SourceRange CXXMemberCallExpr::getSourceRange() const {
- SourceLocation LocStart = getCallee()->getLocStart();
- if (LocStart.isInvalid() && getNumArgs() > 0)
- LocStart = getArg(0)->getLocStart();
- return SourceRange(LocStart, getRParenLoc());
-}
-
//===----------------------------------------------------------------------===//
// Named casts
diff --git a/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp b/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp
index 656bb99..3a5eb66 100644
--- a/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp
@@ -2926,7 +2926,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
Exp->getOpcode() == BO_Rem) {
// Evaluate gives an error for undefined Div/Rem, so make sure
// we don't evaluate one.
- if (LHSResult.Val != 2 && RHSResult.Val != 2) {
+ if (LHSResult.Val == 0 && RHSResult.Val == 0) {
llvm::APSInt REval = Exp->getRHS()->EvaluateAsInt(Ctx);
if (REval == 0)
return ICEDiag(1, E->getLocStart());
diff --git a/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp b/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp
index d66c374..939ca7a 100644
--- a/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp
@@ -606,6 +606,9 @@ void CXXNameMangler::mangleUnresolvedScope(NestedNameSpecifier *Qualifier) {
case NestedNameSpecifier::Namespace:
mangleName(Qualifier->getAsNamespace());
break;
+ case NestedNameSpecifier::NamespaceAlias:
+ mangleName(Qualifier->getAsNamespaceAlias()->getNamespace());
+ break;
case NestedNameSpecifier::TypeSpec:
case NestedNameSpecifier::TypeSpecWithTemplate: {
const Type *QTy = Qualifier->getAsType();
@@ -1647,8 +1650,11 @@ void CXXNameMangler::mangleType(const DecltypeType *T) {
void CXXNameMangler::mangleType(const AutoType *T) {
QualType D = T->getDeducedType();
- assert(!D.isNull() && "can't mangle undeduced auto type");
- mangleType(D);
+ // <builtin-type> ::= Da # dependent auto
+ if (D.isNull())
+ Out << "Da";
+ else
+ mangleType(D);
}
void CXXNameMangler::mangleIntegerLiteral(QualType T,
diff --git a/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp b/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp
index 650321d..6f1ec05 100644
--- a/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp
@@ -14,8 +14,10 @@
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
#include "clang/AST/PrettyPrinter.h"
#include "clang/AST/Type.h"
+#include "clang/AST/TypeLoc.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
@@ -46,7 +48,7 @@ NestedNameSpecifier::Create(const ASTContext &Context,
NestedNameSpecifier Mockup;
Mockup.Prefix.setPointer(Prefix);
- Mockup.Prefix.setInt(Identifier);
+ Mockup.Prefix.setInt(StoredIdentifier);
Mockup.Specifier = II;
return FindOrInsert(Context, Mockup);
}
@@ -60,19 +62,34 @@ NestedNameSpecifier::Create(const ASTContext &Context,
"Broken nested name specifier");
NestedNameSpecifier Mockup;
Mockup.Prefix.setPointer(Prefix);
- Mockup.Prefix.setInt(Namespace);
+ Mockup.Prefix.setInt(StoredNamespaceOrAlias);
Mockup.Specifier = NS;
return FindOrInsert(Context, Mockup);
}
NestedNameSpecifier *
NestedNameSpecifier::Create(const ASTContext &Context,
+ NestedNameSpecifier *Prefix,
+ NamespaceAliasDecl *Alias) {
+ assert(Alias && "Namespace alias cannot be NULL");
+ assert((!Prefix ||
+ (Prefix->getAsType() == 0 && Prefix->getAsIdentifier() == 0)) &&
+ "Broken nested name specifier");
+ NestedNameSpecifier Mockup;
+ Mockup.Prefix.setPointer(Prefix);
+ Mockup.Prefix.setInt(StoredNamespaceOrAlias);
+ Mockup.Specifier = Alias;
+ return FindOrInsert(Context, Mockup);
+}
+
+NestedNameSpecifier *
+NestedNameSpecifier::Create(const ASTContext &Context,
NestedNameSpecifier *Prefix,
bool Template, const Type *T) {
assert(T && "Type cannot be NULL");
NestedNameSpecifier Mockup;
Mockup.Prefix.setPointer(Prefix);
- Mockup.Prefix.setInt(Template? TypeSpecWithTemplate : TypeSpec);
+ Mockup.Prefix.setInt(Template? StoredTypeSpecWithTemplate : StoredTypeSpec);
Mockup.Specifier = const_cast<Type*>(T);
return FindOrInsert(Context, Mockup);
}
@@ -82,7 +99,7 @@ NestedNameSpecifier::Create(const ASTContext &Context, IdentifierInfo *II) {
assert(II && "Identifier cannot be NULL");
NestedNameSpecifier Mockup;
Mockup.Prefix.setPointer(0);
- Mockup.Prefix.setInt(Identifier);
+ Mockup.Prefix.setInt(StoredIdentifier);
Mockup.Specifier = II;
return FindOrInsert(Context, Mockup);
}
@@ -94,6 +111,47 @@ NestedNameSpecifier::GlobalSpecifier(const ASTContext &Context) {
return Context.GlobalNestedNameSpecifier;
}
+NestedNameSpecifier::SpecifierKind NestedNameSpecifier::getKind() const {
+ if (Specifier == 0)
+ return Global;
+
+ switch (Prefix.getInt()) {
+ case StoredIdentifier:
+ return Identifier;
+
+ case StoredNamespaceOrAlias:
+ return isa<NamespaceDecl>(static_cast<NamedDecl *>(Specifier))? Namespace
+ : NamespaceAlias;
+
+ case StoredTypeSpec:
+ return TypeSpec;
+
+ case StoredTypeSpecWithTemplate:
+ return TypeSpecWithTemplate;
+ }
+
+ return Global;
+}
+
+/// \brief Retrieve the namespace stored in this nested name
+/// specifier.
+NamespaceDecl *NestedNameSpecifier::getAsNamespace() const {
+ if (Prefix.getInt() == StoredNamespaceOrAlias)
+ return dyn_cast<NamespaceDecl>(static_cast<NamedDecl *>(Specifier));
+
+ return 0;
+}
+
+/// \brief Retrieve the namespace alias stored in this nested name
+/// specifier.
+NamespaceAliasDecl *NestedNameSpecifier::getAsNamespaceAlias() const {
+ if (Prefix.getInt() == StoredNamespaceOrAlias)
+ return dyn_cast<NamespaceAliasDecl>(static_cast<NamedDecl *>(Specifier));
+
+ return 0;
+}
+
+
/// \brief Whether this nested name specifier refers to a dependent
/// type or not.
bool NestedNameSpecifier::isDependent() const {
@@ -103,6 +161,7 @@ bool NestedNameSpecifier::isDependent() const {
return true;
case Namespace:
+ case NamespaceAlias:
case Global:
return false;
@@ -121,6 +180,7 @@ bool NestedNameSpecifier::containsUnexpandedParameterPack() const {
return getPrefix() && getPrefix()->containsUnexpandedParameterPack();
case Namespace:
+ case NamespaceAlias:
case Global:
return false;
@@ -147,7 +207,11 @@ NestedNameSpecifier::print(llvm::raw_ostream &OS,
break;
case Namespace:
- OS << getAsNamespace()->getIdentifier()->getName();
+ OS << getAsNamespace()->getName();
+ break;
+
+ case NamespaceAlias:
+ OS << getAsNamespaceAlias()->getName();
break;
case Global:
@@ -199,3 +263,111 @@ NestedNameSpecifier::print(llvm::raw_ostream &OS,
void NestedNameSpecifier::dump(const LangOptions &LO) {
print(llvm::errs(), PrintingPolicy(LO));
}
+
+unsigned
+NestedNameSpecifierLoc::getLocalDataLength(NestedNameSpecifier *Qualifier) {
+ assert(Qualifier && "Expected a non-NULL qualifier");
+
+ // Location of the trailing '::'.
+ unsigned Length = sizeof(unsigned);
+
+ switch (Qualifier->getKind()) {
+ case NestedNameSpecifier::Global:
+ // Nothing more to add.
+ break;
+
+ case NestedNameSpecifier::Identifier:
+ case NestedNameSpecifier::Namespace:
+ case NestedNameSpecifier::NamespaceAlias:
+ // The location of the identifier or namespace name.
+ Length += sizeof(unsigned);
+ break;
+
+ case NestedNameSpecifier::TypeSpecWithTemplate:
+ case NestedNameSpecifier::TypeSpec:
+ // The "void*" that points at the TypeLoc data.
+ // Note: the 'template' keyword is part of the TypeLoc.
+ Length += sizeof(void *);
+ break;
+ }
+
+ return Length;
+}
+
+unsigned
+NestedNameSpecifierLoc::getDataLength(NestedNameSpecifier *Qualifier) {
+ unsigned Length = 0;
+ for (; Qualifier; Qualifier = Qualifier->getPrefix())
+ Length += getLocalDataLength(Qualifier);
+ return Length;
+}
+
+namespace {
+ /// \brief Load a (possibly unaligned) source location from a given address
+ /// and offset.
+ SourceLocation LoadSourceLocation(void *Data, unsigned Offset) {
+ unsigned Raw;
+ memcpy(&Raw, static_cast<char *>(Data) + Offset, sizeof(unsigned));
+ return SourceLocation::getFromRawEncoding(Raw);
+ }
+
+ /// \brief Load a (possibly unaligned) pointer from a given address and
+ /// offset.
+ void *LoadPointer(void *Data, unsigned Offset) {
+ void *Result;
+ memcpy(&Result, static_cast<char *>(Data) + Offset, sizeof(void*));
+ return Result;
+ }
+}
+
+SourceRange NestedNameSpecifierLoc::getSourceRange() const {
+ if (!Qualifier)
+ return SourceRange();
+
+ NestedNameSpecifierLoc First = *this;
+ while (NestedNameSpecifierLoc Prefix = First.getPrefix())
+ First = Prefix;
+
+ return SourceRange(First.getLocalSourceRange().getBegin(),
+ getLocalSourceRange().getEnd());
+}
+
+SourceRange NestedNameSpecifierLoc::getLocalSourceRange() const {
+ if (!Qualifier)
+ return SourceRange();
+
+ unsigned Offset = getDataLength(Qualifier->getPrefix());
+ switch (Qualifier->getKind()) {
+ case NestedNameSpecifier::Global:
+ return LoadSourceLocation(Data, Offset);
+
+ case NestedNameSpecifier::Identifier:
+ case NestedNameSpecifier::Namespace:
+ case NestedNameSpecifier::NamespaceAlias:
+ return SourceRange(LoadSourceLocation(Data, Offset),
+ LoadSourceLocation(Data, Offset + sizeof(unsigned)));
+
+ case NestedNameSpecifier::TypeSpecWithTemplate:
+ case NestedNameSpecifier::TypeSpec: {
+ // The "void*" that points at the TypeLoc data.
+ // Note: the 'template' keyword is part of the TypeLoc.
+ void *TypeData = LoadPointer(Data, Offset);
+ TypeLoc TL(Qualifier->getAsType(), TypeData);
+ return SourceRange(TL.getBeginLoc(),
+ LoadSourceLocation(Data, Offset + sizeof(void*)));
+ }
+ }
+
+ return SourceRange();
+}
+
+TypeLoc NestedNameSpecifierLoc::getTypeLoc() const {
+ assert((Qualifier->getKind() == NestedNameSpecifier::TypeSpec ||
+ Qualifier->getKind() == NestedNameSpecifier::TypeSpecWithTemplate) &&
+ "Nested-name-specifier location is not a type");
+
+ // The "void*" that points at the TypeLoc data.
+ unsigned Offset = getDataLength(Qualifier->getPrefix());
+ void *TypeData = LoadPointer(Data, Offset);
+ return TypeLoc(Qualifier->getAsType(), TypeData);
+}
diff --git a/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp b/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp
index cf14eba..4ed031f 100644
--- a/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp
@@ -698,6 +698,25 @@ protected:
DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID);
+ CharUnits getSize() const {
+ assert(Size % Context.getCharWidth() == 0);
+ return Context.toCharUnitsFromBits(Size);
+ }
+ uint64_t getSizeInBits() const { return Size; }
+
+ void setSize(CharUnits NewSize) { Size = Context.toBits(NewSize); }
+ void setSize(uint64_t NewSize) { Size = NewSize; }
+
+ CharUnits getDataSize() const {
+ assert(DataSize % Context.getCharWidth() == 0);
+ return Context.toCharUnitsFromBits(DataSize);
+ }
+ uint64_t getDataSizeInBits() const { return DataSize; }
+
+ void setDataSize(CharUnits NewSize) { DataSize = Context.toBits(NewSize); }
+ void setDataSize(uint64_t NewSize) { DataSize = NewSize; }
+
+
RecordLayoutBuilder(const RecordLayoutBuilder&); // DO NOT IMPLEMENT
void operator=(const RecordLayoutBuilder&); // DO NOT IMPLEMENT
public:
@@ -796,8 +815,8 @@ void RecordLayoutBuilder::DeterminePrimaryBase(const CXXRecordDecl *RD) {
assert(DataSize == 0 && "Vtable pointer must be at offset zero!");
// Update the size.
- Size += GetVirtualPointersSize(RD);
- DataSize = Size;
+ setSize(getSizeInBits() + GetVirtualPointersSize(RD));
+ setDataSize(getSizeInBits());
CharUnits UnpackedBaseAlign =
Context.toCharUnitsFromBits(Context.Target.getPointerAlign(0));
@@ -1090,7 +1109,7 @@ CharUnits RecordLayoutBuilder::LayoutBase(const BaseSubobjectInfo *Base) {
if (Base->Class->isEmpty() &&
EmptySubobjects->CanPlaceBaseAtOffset(Base, CharUnits::Zero())) {
uint64_t RecordSizeInBits = Context.toBits(Layout.getSize());
- Size = std::max(Size, RecordSizeInBits);
+ setSize(std::max(getSizeInBits(), RecordSizeInBits));
return CharUnits::Zero();
}
@@ -1106,7 +1125,7 @@ CharUnits RecordLayoutBuilder::LayoutBase(const BaseSubobjectInfo *Base) {
// Round up the current record size to the base's alignment boundary.
uint64_t Offset =
- llvm::RoundUpToAlignment(DataSize, Context.toBits(BaseAlign));
+ llvm::RoundUpToAlignment(getDataSizeInBits(), Context.toBits(BaseAlign));
// Try to place the base.
while (!EmptySubobjects->CanPlaceBaseAtOffset(Base,
@@ -1115,11 +1134,12 @@ CharUnits RecordLayoutBuilder::LayoutBase(const BaseSubobjectInfo *Base) {
if (!Base->Class->isEmpty()) {
// Update the data size.
- DataSize = Offset + Context.toBits(Layout.getNonVirtualSize());
+ setDataSize(Offset + Context.toBits(Layout.getNonVirtualSize()));
- Size = std::max(Size, DataSize);
+ setSize(std::max(getSizeInBits(), getDataSizeInBits()));
} else
- Size = std::max(Size, Offset + Context.toBits(Layout.getSize()));
+ setSize(std::max(getSizeInBits(),
+ Offset + Context.toBits(Layout.getSize())));
// Remember max struct/class alignment.
UpdateAlignment(BaseAlign, UnpackedBaseAlign);
@@ -1167,7 +1187,8 @@ void RecordLayoutBuilder::Layout(const CXXRecordDecl *RD) {
LayoutFields(RD);
- NonVirtualSize = Context.toCharUnitsFromBits(Size);
+ // FIXME: Size isn't always an exact multiple of the char width. Round up?
+ NonVirtualSize = Context.toCharUnitsFromBits(getSizeInBits());
NonVirtualAlignment = Alignment;
// Lay out the virtual bases and add the primary virtual base offsets.
@@ -1211,8 +1232,8 @@ void RecordLayoutBuilder::Layout(const ObjCInterfaceDecl *D) {
// We start laying out ivars not at the end of the superclass
// structure, but at the next byte following the last field.
- Size = Context.toBits(SL.getDataSize());
- DataSize = Size;
+ setSize(SL.getDataSize());
+ setDataSize(getSizeInBits());
}
InitializeLayout(D);
@@ -1270,20 +1291,20 @@ void RecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize,
UnfilledBitsInLastByte = 0;
uint64_t FieldOffset;
- uint64_t UnpaddedFieldOffset = DataSize - UnfilledBitsInLastByte;
+ uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastByte;
if (IsUnion) {
- DataSize = std::max(DataSize, FieldSize);
+ setDataSize(std::max(getDataSizeInBits(), FieldSize));
FieldOffset = 0;
} else {
// The bitfield is allocated starting at the next offset aligned appropriately
// for T', with length n bits.
- FieldOffset = llvm::RoundUpToAlignment(DataSize, TypeAlign);
+ FieldOffset = llvm::RoundUpToAlignment(getDataSizeInBits(), TypeAlign);
uint64_t NewSizeInBits = FieldOffset + FieldSize;
- DataSize = llvm::RoundUpToAlignment(NewSizeInBits, 8);
- UnfilledBitsInLastByte = DataSize - NewSizeInBits;
+ setDataSize(llvm::RoundUpToAlignment(NewSizeInBits, 8));
+ UnfilledBitsInLastByte = getDataSizeInBits() - NewSizeInBits;
}
// Place this field at the current location.
@@ -1293,7 +1314,7 @@ void RecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize,
TypeAlign, FieldPacked, D);
// Update the size.
- Size = std::max(Size, DataSize);
+ setSize(std::max(getSizeInBits(), getDataSizeInBits()));
// Remember max struct/class alignment.
UpdateAlignment(Context.toCharUnitsFromBits(TypeAlign));
@@ -1301,7 +1322,7 @@ void RecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize,
void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
bool FieldPacked = Packed || D->hasAttr<PackedAttr>();
- uint64_t UnpaddedFieldOffset = DataSize - UnfilledBitsInLastByte;
+ uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastByte;
uint64_t FieldOffset = IsUnion ? 0 : UnpaddedFieldOffset;
uint64_t FieldSize = D->getBitWidth()->EvaluateAsInt(Context).getZExtValue();
@@ -1355,16 +1376,16 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
// Update DataSize to include the last byte containing (part of) the bitfield.
if (IsUnion) {
// FIXME: I think FieldSize should be TypeSize here.
- DataSize = std::max(DataSize, FieldSize);
+ setDataSize(std::max(getDataSizeInBits(), FieldSize));
} else {
uint64_t NewSizeInBits = FieldOffset + FieldSize;
- DataSize = llvm::RoundUpToAlignment(NewSizeInBits, 8);
- UnfilledBitsInLastByte = DataSize - NewSizeInBits;
+ setDataSize(llvm::RoundUpToAlignment(NewSizeInBits, 8));
+ UnfilledBitsInLastByte = getDataSizeInBits() - NewSizeInBits;
}
// Update the size.
- Size = std::max(Size, DataSize);
+ setSize(std::max(getSizeInBits(), getDataSizeInBits()));
// Remember max struct/class alignment.
UpdateAlignment(Context.toCharUnitsFromBits(FieldAlign),
@@ -1377,14 +1398,14 @@ void RecordLayoutBuilder::LayoutField(const FieldDecl *D) {
return;
}
- uint64_t UnpaddedFieldOffset = DataSize - UnfilledBitsInLastByte;
+ uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastByte;
// Reset the unfilled bits.
UnfilledBitsInLastByte = 0;
bool FieldPacked = Packed || D->hasAttr<PackedAttr>();
CharUnits FieldOffset =
- IsUnion ? CharUnits::Zero() : Context.toCharUnitsFromBits(DataSize);
+ IsUnion ? CharUnits::Zero() : getDataSize();
CharUnits FieldSize;
CharUnits FieldAlign;
@@ -1464,12 +1485,12 @@ void RecordLayoutBuilder::LayoutField(const FieldDecl *D) {
// Reserve space for this field.
uint64_t FieldSizeInBits = Context.toBits(FieldSize);
if (IsUnion)
- Size = std::max(Size, FieldSizeInBits);
+ setSize(std::max(getSizeInBits(), FieldSizeInBits));
else
- Size = Context.toBits(FieldOffset) + FieldSizeInBits;
+ setSize(Context.toBits(FieldOffset) + FieldSizeInBits);
// Update the data size.
- DataSize = Size;
+ setDataSize(getSizeInBits());
// Remember max struct/class alignment.
UpdateAlignment(FieldAlign, UnpackedFieldAlign);
@@ -1477,29 +1498,30 @@ void RecordLayoutBuilder::LayoutField(const FieldDecl *D) {
void RecordLayoutBuilder::FinishLayout(const NamedDecl *D) {
// In C++, records cannot be of size 0.
- if (Context.getLangOptions().CPlusPlus && Size == 0) {
+ if (Context.getLangOptions().CPlusPlus && getSizeInBits() == 0) {
if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
// Compatibility with gcc requires a class (pod or non-pod)
// which is not empty but of size 0; such as having fields of
// array of zero-length, remains of Size 0
if (RD->isEmpty())
- Size = 8;
+ setSize(8);
}
else
- Size = 8;
+ setSize(8);
}
// Finally, round the size of the record up to the alignment of the
// record itself.
- uint64_t UnpaddedSize = Size - UnfilledBitsInLastByte;
+ uint64_t UnpaddedSize = getSizeInBits() - UnfilledBitsInLastByte;
uint64_t UnpackedSize =
- llvm::RoundUpToAlignment(Size, Context.toBits(UnpackedAlignment));
- Size = llvm::RoundUpToAlignment(Size, Context.toBits(Alignment));
+ llvm::RoundUpToAlignment(getSizeInBits(),
+ Context.toBits(UnpackedAlignment));
+ setSize(llvm::RoundUpToAlignment(getSizeInBits(), Context.toBits(Alignment)));
unsigned CharBitNum = Context.Target.getCharWidth();
if (const RecordDecl *RD = dyn_cast<RecordDecl>(D)) {
// Warn if padding was introduced to the struct/class/union.
- if (Size > UnpaddedSize) {
- unsigned PadSize = Size - UnpaddedSize;
+ if (getSizeInBits() > UnpaddedSize) {
+ unsigned PadSize = getSizeInBits() - UnpaddedSize;
bool InBits = true;
if (PadSize % CharBitNum == 0) {
PadSize = PadSize / CharBitNum;
@@ -1513,7 +1535,8 @@ void RecordLayoutBuilder::FinishLayout(const NamedDecl *D) {
// Warn if we packed it unnecessarily. If the alignment is 1 byte don't
// bother since there won't be alignment issues.
- if (Packed && UnpackedAlignment > CharUnits::One() && Size == UnpackedSize)
+ if (Packed && UnpackedAlignment > CharUnits::One() &&
+ getSizeInBits() == UnpackedSize)
Diag(D->getLocation(), diag::warn_unnecessary_packed)
<< Context.getTypeDeclType(RD);
}
diff --git a/contrib/llvm/tools/clang/lib/AST/Stmt.cpp b/contrib/llvm/tools/clang/lib/AST/Stmt.cpp
index 7e73f02..8a80275 100644
--- a/contrib/llvm/tools/clang/lib/AST/Stmt.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/Stmt.cpp
@@ -218,6 +218,10 @@ unsigned AsmStmt::getNumPlusOperands() const {
Expr *AsmStmt::getInputExpr(unsigned i) {
return cast<Expr>(Exprs[i + NumOutputs]);
}
+void AsmStmt::setInputExpr(unsigned i, Expr *E) {
+ Exprs[i + NumOutputs] = E;
+}
+
/// getInputConstraint - Return the specified input constraint. Unlike output
/// constraints, these can be empty.
diff --git a/contrib/llvm/tools/clang/lib/AST/StmtDumper.cpp b/contrib/llvm/tools/clang/lib/AST/StmtDumper.cpp
index 846bd4c..5c7dbb3 100644
--- a/contrib/llvm/tools/clang/lib/AST/StmtDumper.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/StmtDumper.cpp
@@ -279,8 +279,8 @@ void StmtDumper::DumpDeclarator(Decl *D) {
// print using decl (e.g. "using std::string;")
const char *tn = UD->isTypeName() ? "typename " : "";
OS << '"' << UD->getDeclKindName() << tn;
- UD->getTargetNestedNameDecl()->print(OS,
- PrintingPolicy(UD->getASTContext().getLangOptions()));
+ UD->getQualifier()->print(OS,
+ PrintingPolicy(UD->getASTContext().getLangOptions()));
OS << ";\"";
} else if (LabelDecl *LD = dyn_cast<LabelDecl>(D)) {
OS << "label " << LD->getNameAsString();
diff --git a/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp b/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp
index 5ab5f46..1764f4a 100644
--- a/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp
@@ -24,8 +24,6 @@
#include "llvm/ADT/FoldingSet.h"
#include <algorithm>
#include <cctype>
-#include <iomanip>
-#include <sstream>
using namespace clang;
@@ -42,17 +40,11 @@ static void printIntegral(const TemplateArgument &TemplArg,
if (T->isBooleanType()) {
Out << (Val->getBoolValue() ? "true" : "false");
} else if (T->isCharType()) {
- char Ch = Val->getSExtValue();
- if (std::isprint(Ch)) {
- Out << "'";
- if (Ch == '\'' || Ch == '\\')
- Out << '\\';
- Out << Ch << "'";
- } else {
- std::ostringstream Str;
- Str << std::setw(2) << std::setfill('0') << std::hex << (int)Ch;
- Out << "'\\x" << Str.str() << "'";
- }
+ const unsigned char Ch = Val->getZExtValue();
+ const std::string Str(1, Ch);
+ Out << ((Ch == '\'') ? "'\\" : "'");
+ Out.write_escaped(Str, /*UseHexEscapes=*/ true);
+ Out << "'";
} else {
Out << Val->toString(10);
}
diff --git a/contrib/llvm/tools/clang/lib/Analysis/AnalysisContext.cpp b/contrib/llvm/tools/clang/lib/Analysis/AnalysisContext.cpp
index 5233d3b..62097ef 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/AnalysisContext.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/AnalysisContext.cpp
@@ -19,8 +19,10 @@
#include "clang/AST/StmtVisitor.h"
#include "clang/Analysis/Analyses/LiveVariables.h"
#include "clang/Analysis/Analyses/PseudoConstantAnalysis.h"
+#include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h"
#include "clang/Analysis/AnalysisContext.h"
#include "clang/Analysis/CFG.h"
+#include "clang/Analysis/CFGStmtMap.h"
#include "clang/Analysis/Support/BumpVector.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/Support/ErrorHandling.h"
@@ -86,6 +88,30 @@ CFG *AnalysisContext::getUnoptimizedCFG() {
return completeCFG;
}
+CFGStmtMap *AnalysisContext::getCFGStmtMap() {
+ if (cfgStmtMap)
+ return cfgStmtMap;
+
+ if (CFG *c = getCFG()) {
+ cfgStmtMap = CFGStmtMap::Build(c, &getParentMap());
+ return cfgStmtMap;
+ }
+
+ return 0;
+}
+
+CFGReachabilityAnalysis *AnalysisContext::getCFGReachablityAnalysis() {
+ if (CFA)
+ return CFA;
+
+ if (CFG *c = getCFG()) {
+ CFA = new CFGReachabilityAnalysis(*c);
+ return CFA;
+ }
+
+ return 0;
+}
+
void AnalysisContext::dumpCFG() {
getCFG()->dump(getASTContext().getLangOptions());
}
@@ -346,10 +372,12 @@ AnalysisContext::getReferencedBlockVars(const BlockDecl *BD) {
AnalysisContext::~AnalysisContext() {
delete cfg;
delete completeCFG;
+ delete cfgStmtMap;
delete liveness;
delete relaxedLiveness;
delete PM;
delete PCA;
+ delete CFA;
delete ReferencedBlockVars;
}
diff --git a/contrib/llvm/tools/clang/lib/Analysis/CFG.cpp b/contrib/llvm/tools/clang/lib/Analysis/CFG.cpp
index a0ec5fe..cc6e9c5 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/CFG.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/CFG.cpp
@@ -17,6 +17,7 @@
#include "clang/AST/DeclCXX.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/AST/PrettyPrinter.h"
+#include "clang/AST/CharUnits.h"
#include "llvm/Support/GraphWriter.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Format.h"
@@ -413,9 +414,16 @@ private:
Expr::EvalResult Result;
if (!S->isTypeDependent() && !S->isValueDependent() &&
- S->Evaluate(Result, *Context) && Result.Val.isInt())
- return Result.Val.getInt().getBoolValue();
-
+ S->Evaluate(Result, *Context)) {
+ if (Result.Val.isInt())
+ return Result.Val.getInt().getBoolValue();
+ if (Result.Val.isLValue()) {
+ Expr *e = Result.Val.getLValueBase();
+ const CharUnits &c = Result.Val.getLValueOffset();
+ if (!e && c.isZero())
+ return false;
+ }
+ }
return TryResult();
}
};
@@ -928,11 +936,13 @@ CFGBlock *CFGBuilder::VisitStmt(Stmt *S, AddStmtChoice asc) {
/// VisitChildren - Visit the children of a Stmt.
CFGBlock *CFGBuilder::VisitChildren(Stmt* Terminator) {
- CFGBlock *B = Block;
- for (Stmt::child_range I = Terminator->children(); I; ++I) {
- if (*I) B = Visit(*I);
- }
- return B;
+ CFGBlock *lastBlock = Block;
+ for (Stmt::child_range I = Terminator->children(); I; ++I)
+ if (Stmt *child = *I)
+ if (CFGBlock *b = Visit(child))
+ lastBlock = b;
+
+ return lastBlock;
}
CFGBlock *CFGBuilder::VisitAddrLabelExpr(AddrLabelExpr *A,
@@ -1207,6 +1217,8 @@ CFGBlock *CFGBuilder::VisitConditionalOperator(AbstractConditionalOperator *C,
return 0;
Block = NULL;
}
+ else
+ LHSBlock = ConfluenceBlock;
// Create the block for the RHS expression.
Succ = ConfluenceBlock;
@@ -1219,23 +1231,23 @@ CFGBlock *CFGBuilder::VisitConditionalOperator(AbstractConditionalOperator *C,
// See if this is a known constant.
const TryResult& KnownVal = tryEvaluateBool(C->getCond());
- if (LHSBlock)
- addSuccessor(Block, KnownVal.isFalse() ? NULL : LHSBlock);
+ addSuccessor(Block, KnownVal.isFalse() ? NULL : LHSBlock);
addSuccessor(Block, KnownVal.isTrue() ? NULL : RHSBlock);
Block->setTerminator(C);
Expr *condExpr = C->getCond();
- CFGBlock *result = 0;
-
- // Run the condition expression if it's not trivially expressed in
- // terms of the opaque value (or if there is no opaque value).
- if (condExpr != opaqueValue) result = addStmt(condExpr);
-
- // Before that, run the common subexpression if there was one.
- // At least one of this or the above will be run.
- if (opaqueValue) result = addStmt(BCO->getCommon());
+ if (opaqueValue) {
+ // Run the condition expression if it's not trivially expressed in
+ // terms of the opaque value (or if there is no opaque value).
+ if (condExpr != opaqueValue)
+ addStmt(condExpr);
- return result;
+ // Before that, run the common subexpression if there was one.
+ // At least one of this or the above will be run.
+ return addStmt(BCO->getCommon());
+ }
+
+ return addStmt(condExpr);
}
CFGBlock *CFGBuilder::VisitDeclStmt(DeclStmt *DS) {
@@ -1819,6 +1831,7 @@ CFGBlock* CFGBuilder::VisitWhileStmt(WhileStmt* W) {
if (badCFG)
return 0;
LoopSuccessor = Block;
+ Block = 0;
} else
LoopSuccessor = Succ;
diff --git a/contrib/llvm/tools/clang/lib/Analysis/CFGReachabilityAnalysis.cpp b/contrib/llvm/tools/clang/lib/Analysis/CFGReachabilityAnalysis.cpp
new file mode 100644
index 0000000..7786584
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Analysis/CFGReachabilityAnalysis.cpp
@@ -0,0 +1,76 @@
+//==- CFGReachabilityAnalysis.cpp - Basic reachability analysis --*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a flow-sensitive, (mostly) path-insensitive reachability
+// analysis based on Clang's CFGs. Clients can query if a given basic block
+// is reachable within the CFG.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/SmallVector.h"
+#include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h"
+#include "clang/Analysis/CFG.h"
+
+using namespace clang;
+
+CFGReachabilityAnalysis::CFGReachabilityAnalysis(const CFG &cfg)
+ : analyzed(cfg.getNumBlockIDs(), false) {}
+
+bool CFGReachabilityAnalysis::isReachable(const CFGBlock *Src,
+ const CFGBlock *Dst) {
+
+ const unsigned DstBlockID = Dst->getBlockID();
+
+ // If we haven't analyzed the destination node, run the analysis now
+ if (!analyzed[DstBlockID]) {
+ mapReachability(Dst);
+ analyzed[DstBlockID] = true;
+ }
+
+ // Return the cached result
+ return reachable[DstBlockID][Src->getBlockID()];
+}
+
+// Maps reachability to a common node by walking the predecessors of the
+// destination node.
+void CFGReachabilityAnalysis::mapReachability(const CFGBlock *Dst) {
+ llvm::SmallVector<const CFGBlock *, 11> worklist;
+ llvm::BitVector visited(analyzed.size());
+
+ ReachableSet &DstReachability = reachable[Dst->getBlockID()];
+ DstReachability.resize(analyzed.size(), false);
+
+ // Start searching from the destination node, since we commonly will perform
+ // multiple queries relating to a destination node.
+ worklist.push_back(Dst);
+ bool firstRun = true;
+
+ while (!worklist.empty()) {
+ const CFGBlock *block = worklist.back();
+ worklist.pop_back();
+
+ if (visited[block->getBlockID()])
+ continue;
+ visited[block->getBlockID()] = true;
+
+ // Update reachability information for this node -> Dst
+ if (!firstRun) {
+ // Don't insert Dst -> Dst unless it was a predecessor of itself
+ DstReachability[block->getBlockID()] = true;
+ }
+ else
+ firstRun = false;
+
+ // Add the predecessors to the worklist.
+ for (CFGBlock::const_pred_iterator i = block->pred_begin(),
+ e = block->pred_end(); i != e; ++i) {
+ worklist.push_back(*i);
+ }
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp b/contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp
index 8725e7f..553e4c9 100644
--- a/contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp
@@ -288,14 +288,15 @@ const char *DiagnosticIDs::getDescription(unsigned DiagID) const {
/// the DiagnosticClient.
DiagnosticIDs::Level
DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, SourceLocation Loc,
- const Diagnostic &Diag) const {
+ const Diagnostic &Diag,
+ diag::Mapping *mapping) const {
// Handle custom diagnostics, which cannot be mapped.
if (DiagID >= diag::DIAG_UPPER_LIMIT)
return CustomDiagInfo->getLevel(DiagID);
unsigned DiagClass = getBuiltinDiagClass(DiagID);
assert(DiagClass != CLASS_NOTE && "Cannot get diagnostic level of a note!");
- return getDiagnosticLevel(DiagID, DiagClass, Loc, Diag);
+ return getDiagnosticLevel(DiagID, DiagClass, Loc, Diag, mapping);
}
/// \brief Based on the way the client configured the Diagnostic
@@ -307,7 +308,8 @@ DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, SourceLocation Loc,
DiagnosticIDs::Level
DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, unsigned DiagClass,
SourceLocation Loc,
- const Diagnostic &Diag) const {
+ const Diagnostic &Diag,
+ diag::Mapping *mapping) const {
// Specific non-error diagnostics may be mapped to various levels from ignored
// to error. Errors can only be mapped to fatal.
DiagnosticIDs::Level Result = DiagnosticIDs::Fatal;
@@ -323,6 +325,9 @@ DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, unsigned DiagClass,
MappingInfo = GetDefaultDiagMapping(DiagID);
Diag.setDiagnosticMappingInternal(DiagID, MappingInfo, State, false, false);
}
+
+ if (mapping)
+ *mapping = (diag::Mapping) (MappingInfo & 7);
switch (MappingInfo & 7) {
default: assert(0 && "Unknown mapping!");
diff --git a/contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp b/contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp
index 044c88d..e2783ba 100644
--- a/contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp
@@ -823,6 +823,12 @@ unsigned SourceManager::getInstantiationColumnNumber(SourceLocation Loc,
return getColumnNumber(LocInfo.first, LocInfo.second, Invalid);
}
+unsigned SourceManager::getPresumedColumnNumber(SourceLocation Loc,
+ bool *Invalid) const {
+ if (isInvalid(Loc, Invalid)) return 0;
+ return getPresumedLoc(Loc).getColumn();
+}
+
static LLVM_ATTRIBUTE_NOINLINE void
ComputeLineNumbers(Diagnostic &Diag, ContentCache *FI,
llvm::BumpPtrAllocator &Alloc,
@@ -985,17 +991,22 @@ unsigned SourceManager::getLineNumber(FileID FID, unsigned FilePos,
return LineNo;
}
+unsigned SourceManager::getSpellingLineNumber(SourceLocation Loc,
+ bool *Invalid) const {
+ if (isInvalid(Loc, Invalid)) return 0;
+ std::pair<FileID, unsigned> LocInfo = getDecomposedSpellingLoc(Loc);
+ return getLineNumber(LocInfo.first, LocInfo.second);
+}
unsigned SourceManager::getInstantiationLineNumber(SourceLocation Loc,
bool *Invalid) const {
if (isInvalid(Loc, Invalid)) return 0;
std::pair<FileID, unsigned> LocInfo = getDecomposedInstantiationLoc(Loc);
return getLineNumber(LocInfo.first, LocInfo.second);
}
-unsigned SourceManager::getSpellingLineNumber(SourceLocation Loc,
+unsigned SourceManager::getPresumedLineNumber(SourceLocation Loc,
bool *Invalid) const {
if (isInvalid(Loc, Invalid)) return 0;
- std::pair<FileID, unsigned> LocInfo = getDecomposedSpellingLoc(Loc);
- return getLineNumber(LocInfo.first, LocInfo.second);
+ return getPresumedLoc(Loc).getLine();
}
/// getFileCharacteristic - return the file characteristic of the specified
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets.cpp
index a8198e4..55321f24 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Targets.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets.cpp
@@ -152,6 +152,7 @@ public:
DarwinTargetInfo(const std::string& triple) :
OSTargetInfo<Target>(triple) {
this->TLSSupported = llvm::Triple(triple).getDarwinMajorNumber() > 10;
+ this->MCountName = "\01mcount";
}
virtual std::string isValidSectionSpecifier(llvm::StringRef SR) const {
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.cpp
index a35648d..9587de2 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.cpp
@@ -895,12 +895,9 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD,
QualType selfTy = getContext().VoidPtrTy;
IdentifierInfo *II = &CGM.getContext().Idents.get(".block_descriptor");
- // FIXME: this leaks, and we only need it very temporarily.
- ImplicitParamDecl *selfDecl =
- ImplicitParamDecl::Create(getContext(),
- const_cast<BlockDecl*>(blockDecl),
- SourceLocation(), II, selfTy);
- args.push_back(std::make_pair(selfDecl, selfTy));
+ ImplicitParamDecl selfDecl(const_cast<BlockDecl*>(blockDecl),
+ SourceLocation(), II, selfTy);
+ args.push_back(std::make_pair(&selfDecl, selfTy));
// Now add the rest of the parameters.
for (BlockDecl::param_const_iterator i = blockDecl->param_begin(),
@@ -928,12 +925,11 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD,
blockInfo.getBlockExpr()->getBody()->getLocEnd());
CurFuncDecl = outerFnDecl; // StartFunction sets this to blockDecl
- // Okay. Undo some of what StartFunction did. We really don't need
- // an alloca for the block address; in theory we could remove it,
- // but that might do unpleasant things to debug info.
- llvm::AllocaInst *blockAddrAlloca
- = cast<llvm::AllocaInst>(LocalDeclMap[selfDecl]);
- llvm::Value *blockAddr = Builder.CreateLoad(blockAddrAlloca);
+ // Okay. Undo some of what StartFunction did.
+
+ // Pull the 'self' reference out of the local decl map.
+ llvm::Value *blockAddr = LocalDeclMap[&selfDecl];
+ LocalDeclMap.erase(&selfDecl);
BlockPointer = Builder.CreateBitCast(blockAddr,
blockInfo.StructureType->getPointerTo(),
"block");
@@ -1010,7 +1006,7 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD,
continue;
}
- DI->EmitDeclareOfBlockDeclRefVariable(variable, blockAddrAlloca,
+ DI->EmitDeclareOfBlockDeclRefVariable(variable, BlockPointer,
Builder, blockInfo);
}
}
@@ -1376,10 +1372,9 @@ llvm::Constant *CodeGenModule::BuildbyrefCopyHelper(const llvm::Type *T,
BlockFieldFlags flags,
unsigned align,
const VarDecl *var) {
- // All alignments below that of pointer alignment collapse down to just
- // pointer alignment, as we always have at least that much alignment to begin
- // with.
- align /= unsigned(getTarget().getPointerAlign(0) / 8);
+ // All alignments below pointer alignment are bumped up, as we
+ // always have at least that much alignment to begin with.
+ if (align < PointerAlignInBytes) align = PointerAlignInBytes;
// As an optimization, we only generate a single function of each kind we
// might need. We need a different one for each alignment and for each
@@ -1396,10 +1391,9 @@ llvm::Constant *CodeGenModule::BuildbyrefDestroyHelper(const llvm::Type *T,
BlockFieldFlags flags,
unsigned align,
const VarDecl *var) {
- // All alignments below that of pointer alignment collpase down to just
- // pointer alignment, as we always have at least that much alignment to begin
- // with.
- align /= unsigned(getTarget().getPointerAlign(0) / 8);
+ // All alignments below pointer alignment are bumped up, as we
+ // always have at least that much alignment to begin with.
+ if (align < PointerAlignInBytes) align = PointerAlignInBytes;
// As an optimization, we only generate a single function of each kind we
// might need. We need a different one for each alignment and for each
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.h b/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.h
index bee729d..0bc8bca 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.h
@@ -177,7 +177,6 @@ public:
const BlockExpr *Block;
CharUnits BlockSize;
CharUnits BlockAlign;
- llvm::SmallVector<const Expr*, 8> BlockLayout;
const Capture &getCapture(const VarDecl *var) const {
llvm::DenseMap<const VarDecl*, Capture>::const_iterator
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp
index 8e88beb..cd28bbe 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp
@@ -17,6 +17,7 @@
#include "clang/AST/EvaluatedExprVisitor.h"
#include "clang/AST/RecordLayout.h"
#include "clang/AST/StmtCXX.h"
+#include "clang/Frontend/CodeGenOptions.h"
using namespace clang;
using namespace CodeGen;
@@ -1140,6 +1141,16 @@ CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
llvm::Value *This,
CallExpr::const_arg_iterator ArgBeg,
CallExpr::const_arg_iterator ArgEnd) {
+
+ CGDebugInfo *DI = getDebugInfo();
+ if (DI && CGM.getCodeGenOpts().LimitDebugInfo) {
+ // If debug info for this class has been emitted then this is the right time
+ // to do so.
+ const CXXRecordDecl *Parent = D->getParent();
+ DI->getOrCreateRecordType(CGM.getContext().getTypeDeclType(Parent),
+ Parent->getLocation());
+ }
+
if (D->isTrivial()) {
if (ArgBeg == ArgEnd) {
// Trivial default constructor, no codegen required.
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.cpp
index 374ede8..1d7901a 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.cpp
@@ -876,7 +876,7 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) {
///
/// As a side-effect, this method clears the insertion point.
void CodeGenFunction::EmitBranchThroughCleanup(JumpDest Dest) {
- assert(Dest.getScopeDepth().encloses(EHStack.getInnermostNormalCleanup())
+ assert(Dest.getScopeDepth().encloses(EHStack.stable_begin())
&& "stale jump destination");
if (!HaveInsertPoint())
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp
index 469b460..dfd9f56 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -156,14 +156,14 @@ CGDebugInfo::getClassName(RecordDecl *RD) {
llvm::DIFile CGDebugInfo::getOrCreateFile(SourceLocation Loc) {
if (!Loc.isValid())
// If Location is not valid then use main input file.
- return DBuilder.CreateFile(TheCU.getFilename(), TheCU.getDirectory());
+ return DBuilder.createFile(TheCU.getFilename(), TheCU.getDirectory());
SourceManager &SM = CGM.getContext().getSourceManager();
PresumedLoc PLoc = SM.getPresumedLoc(Loc);
if (PLoc.isInvalid() || llvm::StringRef(PLoc.getFilename()).empty())
// If the location is not valid then use main input file.
- return DBuilder.CreateFile(TheCU.getFilename(), TheCU.getDirectory());
+ return DBuilder.createFile(TheCU.getFilename(), TheCU.getDirectory());
// Cache the results.
const char *fname = PLoc.getFilename();
@@ -176,7 +176,7 @@ llvm::DIFile CGDebugInfo::getOrCreateFile(SourceLocation Loc) {
return llvm::DIFile(cast<llvm::MDNode>(it->second));
}
- llvm::DIFile F = DBuilder.CreateFile(PLoc.getFilename(), getCurrentDirname());
+ llvm::DIFile F = DBuilder.createFile(PLoc.getFilename(), getCurrentDirname());
DIFileCache[fname] = F;
return F;
@@ -185,7 +185,7 @@ llvm::DIFile CGDebugInfo::getOrCreateFile(SourceLocation Loc) {
/// getOrCreateMainFile - Get the file info for main compile unit.
llvm::DIFile CGDebugInfo::getOrCreateMainFile() {
- return DBuilder.CreateFile(TheCU.getFilename(), TheCU.getDirectory());
+ return DBuilder.createFile(TheCU.getFilename(), TheCU.getDirectory());
}
/// getLineNumber - Get line number for the location. If location is invalid
@@ -264,7 +264,7 @@ void CGDebugInfo::CreateCompileUnit() {
RuntimeVers = LO.ObjCNonFragileABI ? 2 : 1;
// Create new compile unit.
- DBuilder.CreateCompileUnit(
+ DBuilder.createCompileUnit(
LangTag, Filename, getCurrentDirname(),
Producer,
LO.Optimize, CGM.getCodeGenOpts().DwarfDebugFlags, RuntimeVers);
@@ -282,7 +282,7 @@ llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT) {
case BuiltinType::Void:
return llvm::DIType();
case BuiltinType::ObjCClass:
- return DBuilder.CreateStructType(TheCU, "objc_class",
+ return DBuilder.createStructType(TheCU, "objc_class",
getOrCreateMainFile(), 0, 0, 0,
llvm::DIDescriptor::FlagFwdDecl,
llvm::DIArray());
@@ -293,28 +293,28 @@ llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT) {
// } *id;
llvm::DIType OCTy =
- DBuilder.CreateStructType(TheCU, "objc_class",
+ DBuilder.createStructType(TheCU, "objc_class",
getOrCreateMainFile(), 0, 0, 0,
llvm::DIDescriptor::FlagFwdDecl,
llvm::DIArray());
unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy);
- llvm::DIType ISATy = DBuilder.CreatePointerType(OCTy, Size);
+ llvm::DIType ISATy = DBuilder.createPointerType(OCTy, Size);
llvm::SmallVector<llvm::Value *, 16> EltTys;
llvm::DIType FieldTy =
- DBuilder.CreateMemberType("isa", getOrCreateMainFile(),
+ DBuilder.createMemberType("isa", getOrCreateMainFile(),
0,Size, 0, 0, 0, ISATy);
EltTys.push_back(FieldTy);
llvm::DIArray Elements =
- DBuilder.GetOrCreateArray(EltTys.data(), EltTys.size());
+ DBuilder.getOrCreateArray(EltTys.data(), EltTys.size());
- return DBuilder.CreateStructType(TheCU, "objc_object",
+ return DBuilder.createStructType(TheCU, "objc_object",
getOrCreateMainFile(),
0, 0, 0, 0, Elements);
}
case BuiltinType::ObjCSel: {
- return DBuilder.CreateStructType(TheCU, "objc_selector",
+ return DBuilder.createStructType(TheCU, "objc_selector",
getOrCreateMainFile(), 0, 0, 0,
llvm::DIDescriptor::FlagFwdDecl,
llvm::DIArray());
@@ -350,7 +350,7 @@ llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT) {
uint64_t Size = CGM.getContext().getTypeSize(BT);
uint64_t Align = CGM.getContext().getTypeAlign(BT);
llvm::DIType DbgTy =
- DBuilder.CreateBasicType(BTName, Size, Align, Encoding);
+ DBuilder.createBasicType(BTName, Size, Align, Encoding);
return DbgTy;
}
@@ -363,7 +363,7 @@ llvm::DIType CGDebugInfo::CreateType(const ComplexType *Ty) {
uint64_t Size = CGM.getContext().getTypeSize(Ty);
uint64_t Align = CGM.getContext().getTypeAlign(Ty);
llvm::DIType DbgTy =
- DBuilder.CreateBasicType("complex", Size, Align, Encoding);
+ DBuilder.createBasicType("complex", Size, Align, Encoding);
return DbgTy;
}
@@ -399,7 +399,7 @@ llvm::DIType CGDebugInfo::CreateQualifiedType(QualType Ty, llvm::DIFile Unit) {
// No need to fill in the Name, Line, Size, Alignment, Offset in case of
// CVR derived types.
- llvm::DIType DbgTy = DBuilder.CreateQualifiedType(Tag, FromTy);
+ llvm::DIType DbgTy = DBuilder.createQualifiedType(Tag, FromTy);
return DbgTy;
}
@@ -430,19 +430,19 @@ llvm::DIType CGDebugInfo::CreatePointeeType(QualType PointeeTy,
llvm::DIFile DefUnit = getOrCreateFile(RD->getLocation());
unsigned Line = getLineNumber(RD->getLocation());
llvm::DIDescriptor FDContext =
- getContextDescriptor(dyn_cast<Decl>(RD->getDeclContext()));
+ getContextDescriptor(cast<Decl>(RD->getDeclContext()));
if (RD->isStruct())
- return DBuilder.CreateStructType(FDContext, RD->getName(), DefUnit,
+ return DBuilder.createStructType(FDContext, RD->getName(), DefUnit,
Line, 0, 0, llvm::DIType::FlagFwdDecl,
llvm::DIArray());
else if (RD->isUnion())
- return DBuilder.CreateUnionType(FDContext, RD->getName(), DefUnit,
+ return DBuilder.createUnionType(FDContext, RD->getName(), DefUnit,
Line, 0, 0, llvm::DIType::FlagFwdDecl,
llvm::DIArray());
else {
assert(RD->isClass() && "Unknown RecordType!");
- return DBuilder.CreateClassType(FDContext, RD->getName(), DefUnit,
+ return DBuilder.createClassType(FDContext, RD->getName(), DefUnit,
Line, 0, 0, 0, llvm::DIType::FlagFwdDecl,
llvm::DIType(), llvm::DIArray());
}
@@ -457,7 +457,7 @@ llvm::DIType CGDebugInfo::CreatePointerLikeType(unsigned Tag,
llvm::DIFile Unit) {
if (Tag == llvm::dwarf::DW_TAG_reference_type)
- return DBuilder.CreateReferenceType(CreatePointeeType(PointeeTy, Unit));
+ return DBuilder.createReferenceType(CreatePointeeType(PointeeTy, Unit));
// Bit size, align and offset of the type.
// Size is always the size of a pointer. We can't use getTypeSize here
@@ -467,7 +467,7 @@ llvm::DIType CGDebugInfo::CreatePointerLikeType(unsigned Tag,
uint64_t Align = CGM.getContext().getTypeAlign(Ty);
return
- DBuilder.CreatePointerType(CreatePointeeType(PointeeTy, Unit), Size, Align);
+ DBuilder.createPointerType(CreatePointeeType(PointeeTy, Unit), Size, Align);
}
llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty,
@@ -488,20 +488,20 @@ llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty,
EltTys.push_back(CreateMemberType(Unit, FType, "reserved", &FieldOffset));
EltTys.push_back(CreateMemberType(Unit, FType, "Size", &FieldOffset));
- Elements = DBuilder.GetOrCreateArray(EltTys.data(), EltTys.size());
+ Elements = DBuilder.getOrCreateArray(EltTys.data(), EltTys.size());
EltTys.clear();
unsigned Flags = llvm::DIDescriptor::FlagAppleBlock;
unsigned LineNo = getLineNumber(CurLoc);
- EltTy = DBuilder.CreateStructType(Unit, "__block_descriptor",
+ EltTy = DBuilder.createStructType(Unit, "__block_descriptor",
Unit, LineNo, FieldOffset, 0,
Flags, Elements);
// Bit size, align and offset of the type.
uint64_t Size = CGM.getContext().getTypeSize(Ty);
- DescTy = DBuilder.CreatePointerType(EltTy, Size);
+ DescTy = DBuilder.createPointerType(EltTy, Size);
FieldOffset = 0;
FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);
@@ -516,20 +516,20 @@ llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty,
FieldTy = DescTy;
FieldSize = CGM.getContext().getTypeSize(Ty);
FieldAlign = CGM.getContext().getTypeAlign(Ty);
- FieldTy = DBuilder.CreateMemberType("__descriptor", Unit,
+ FieldTy = DBuilder.createMemberType("__descriptor", Unit,
LineNo, FieldSize, FieldAlign,
FieldOffset, 0, FieldTy);
EltTys.push_back(FieldTy);
FieldOffset += FieldSize;
- Elements = DBuilder.GetOrCreateArray(EltTys.data(), EltTys.size());
+ Elements = DBuilder.getOrCreateArray(EltTys.data(), EltTys.size());
- EltTy = DBuilder.CreateStructType(Unit, "__block_literal_generic",
+ EltTy = DBuilder.createStructType(Unit, "__block_literal_generic",
Unit, LineNo, FieldOffset, 0,
Flags, Elements);
BlockLiteralGenericSet = true;
- BlockLiteralGeneric = DBuilder.CreatePointerType(EltTy, Size);
+ BlockLiteralGeneric = DBuilder.createPointerType(EltTy, Size);
return BlockLiteralGeneric;
}
@@ -543,7 +543,7 @@ llvm::DIType CGDebugInfo::CreateType(const TypedefType *Ty,
// We don't set size information, but do specify where the typedef was
// declared.
unsigned Line = getLineNumber(Ty->getDecl()->getLocation());
- llvm::DIType DbgTy = DBuilder.CreateTypedef(Src, Ty->getDecl()->getName(),
+ llvm::DIType DbgTy = DBuilder.createTypedef(Src, Ty->getDecl()->getName(),
Unit, Line);
return DbgTy;
}
@@ -558,66 +558,76 @@ llvm::DIType CGDebugInfo::CreateType(const FunctionType *Ty,
// Set up remainder of arguments if there is a prototype.
// FIXME: IF NOT, HOW IS THIS REPRESENTED? llvm-gcc doesn't represent '...'!
if (isa<FunctionNoProtoType>(Ty))
- EltTys.push_back(DBuilder.CreateUnspecifiedParameter());
+ EltTys.push_back(DBuilder.createUnspecifiedParameter());
else if (const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(Ty)) {
for (unsigned i = 0, e = FTP->getNumArgs(); i != e; ++i)
EltTys.push_back(getOrCreateType(FTP->getArgType(i), Unit));
}
llvm::DIArray EltTypeArray =
- DBuilder.GetOrCreateArray(EltTys.data(), EltTys.size());
+ DBuilder.getOrCreateArray(EltTys.data(), EltTys.size());
- llvm::DIType DbgTy = DBuilder.CreateSubroutineType(Unit, EltTypeArray);
+ llvm::DIType DbgTy = DBuilder.createSubroutineType(Unit, EltTypeArray);
return DbgTy;
}
+llvm::DIType CGDebugInfo::createFieldType(llvm::StringRef name,
+ QualType type,
+ Expr *bitWidth,
+ SourceLocation loc,
+ AccessSpecifier AS,
+ uint64_t offsetInBits,
+ llvm::DIFile tunit) {
+ llvm::DIType debugType = getOrCreateType(type, tunit);
+
+ // Get the location for the field.
+ llvm::DIFile file = getOrCreateFile(loc);
+ unsigned line = getLineNumber(loc);
+
+ uint64_t sizeInBits = 0;
+ unsigned alignInBits = 0;
+ if (!type->isIncompleteArrayType()) {
+ llvm::tie(sizeInBits, alignInBits) = CGM.getContext().getTypeInfo(type);
+
+ if (bitWidth)
+ sizeInBits = bitWidth->EvaluateAsInt(CGM.getContext()).getZExtValue();
+ }
+
+ unsigned flags = 0;
+ if (AS == clang::AS_private)
+ flags |= llvm::DIDescriptor::FlagPrivate;
+ else if (AS == clang::AS_protected)
+ flags |= llvm::DIDescriptor::FlagProtected;
+
+ return DBuilder.createMemberType(name, file, line, sizeInBits, alignInBits,
+ offsetInBits, flags, debugType);
+}
+
/// CollectRecordFields - A helper function to collect debug info for
/// record fields. This is used while creating debug info entry for a Record.
void CGDebugInfo::
-CollectRecordFields(const RecordDecl *RD, llvm::DIFile Unit,
- llvm::SmallVectorImpl<llvm::Value *> &EltTys) {
- unsigned FieldNo = 0;
- const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
- for (RecordDecl::field_iterator I = RD->field_begin(),
- E = RD->field_end();
- I != E; ++I, ++FieldNo) {
- FieldDecl *Field = *I;
- llvm::DIType FieldTy = getOrCreateType(Field->getType(), Unit);
- llvm::StringRef FieldName = Field->getName();
-
- // Ignore unnamed fields. Do not ignore unnamed records.
- if (FieldName.empty() && !isa<RecordType>(Field->getType()))
+CollectRecordFields(const RecordDecl *record, llvm::DIFile tunit,
+ llvm::SmallVectorImpl<llvm::Value *> &elements) {
+ unsigned fieldNo = 0;
+ const ASTRecordLayout &layout = CGM.getContext().getASTRecordLayout(record);
+ for (RecordDecl::field_iterator I = record->field_begin(),
+ E = record->field_end();
+ I != E; ++I, ++fieldNo) {
+ FieldDecl *field = *I;
+
+ llvm::StringRef name = field->getName();
+ QualType type = field->getType();
+
+ // Ignore unnamed fields unless they're anonymous structs/unions.
+ if (name.empty() && !type->isRecordType())
continue;
- // Get the location for the field.
- llvm::DIFile FieldDefUnit = getOrCreateFile(Field->getLocation());
- unsigned FieldLine = getLineNumber(Field->getLocation());
- QualType FType = Field->getType();
- uint64_t FieldSize = 0;
- unsigned FieldAlign = 0;
- if (!FType->isIncompleteArrayType()) {
-
- // Bit size, align and offset of the type.
- FieldSize = CGM.getContext().getTypeSize(FType);
- Expr *BitWidth = Field->getBitWidth();
- if (BitWidth)
- FieldSize = BitWidth->EvaluateAsInt(CGM.getContext()).getZExtValue();
- FieldAlign = CGM.getContext().getTypeAlign(FType);
- }
+ llvm::DIType fieldType
+ = createFieldType(name, type, field->getBitWidth(),
+ field->getLocation(), field->getAccess(),
+ layout.getFieldOffset(fieldNo), tunit);
- uint64_t FieldOffset = RL.getFieldOffset(FieldNo);
-
- unsigned Flags = 0;
- AccessSpecifier Access = I->getAccess();
- if (Access == clang::AS_private)
- Flags |= llvm::DIDescriptor::FlagPrivate;
- else if (Access == clang::AS_protected)
- Flags |= llvm::DIDescriptor::FlagProtected;
-
- FieldTy = DBuilder.CreateMemberType(FieldName, FieldDefUnit,
- FieldLine, FieldSize, FieldAlign,
- FieldOffset, Flags, FieldTy);
- EltTys.push_back(FieldTy);
+ elements.push_back(fieldType);
}
}
@@ -649,7 +659,7 @@ CGDebugInfo::getOrCreateMethodType(const CXXMethodDecl *Method,
QualType ThisPtr =
Context.getPointerType(Context.getTagDeclType(Method->getParent()));
llvm::DIType ThisPtrType =
- DBuilder.CreateArtificialType(getOrCreateType(ThisPtr, Unit));
+ DBuilder.createArtificialType(getOrCreateType(ThisPtr, Unit));
TypeCache[ThisPtr.getAsOpaquePtr()] = ThisPtrType;
Elts.push_back(ThisPtrType);
@@ -660,9 +670,9 @@ CGDebugInfo::getOrCreateMethodType(const CXXMethodDecl *Method,
Elts.push_back(Args.getElement(i));
llvm::DIArray EltTypeArray =
- DBuilder.GetOrCreateArray(Elts.data(), Elts.size());
+ DBuilder.getOrCreateArray(Elts.data(), Elts.size());
- return DBuilder.CreateSubroutineType(Unit, EltTypeArray);
+ return DBuilder.createSubroutineType(Unit, EltTypeArray);
}
/// isFunctionLocalClass - Return true if CXXRecordDecl is defined
@@ -736,7 +746,7 @@ CGDebugInfo::CreateCXXMemberFunction(const CXXMethodDecl *Method,
Flags |= llvm::DIDescriptor::FlagPrototyped;
llvm::DISubprogram SP =
- DBuilder.CreateMethod(RecordTy , MethodName, MethodLinkageName,
+ DBuilder.createMethod(RecordTy , MethodName, MethodLinkageName,
MethodDefUnit, MethodLine,
MethodTy, /*isLocalToUnit=*/false,
/* isDefinition=*/ false,
@@ -780,7 +790,7 @@ CollectCXXFriends(const CXXRecordDecl *RD, llvm::DIFile Unit,
for (CXXRecordDecl::friend_iterator BI = RD->friend_begin(),
BE = RD->friend_end(); BI != BE; ++BI) {
if (TypeSourceInfo *TInfo = (*BI)->getFriendType())
- EltTys.push_back(DBuilder.CreateFriend(RecordTy,
+ EltTys.push_back(DBuilder.createFriend(RecordTy,
getOrCreateType(TInfo->getType(),
Unit)));
}
@@ -818,7 +828,7 @@ CollectCXXBases(const CXXRecordDecl *RD, llvm::DIFile Unit,
BFlags |= llvm::DIDescriptor::FlagProtected;
llvm::DIType DTy =
- DBuilder.CreateInheritance(RecordTy,
+ DBuilder.createInheritance(RecordTy,
getOrCreateType(BI->getType(), Unit),
BaseOffset, BFlags);
EltTys.push_back(DTy);
@@ -834,12 +844,12 @@ llvm::DIType CGDebugInfo::getOrCreateVTablePtrType(llvm::DIFile Unit) {
/* Function type */
llvm::Value *STy = getOrCreateType(Context.IntTy, Unit);
- llvm::DIArray SElements = DBuilder.GetOrCreateArray(&STy, 1);
- llvm::DIType SubTy = DBuilder.CreateSubroutineType(Unit, SElements);
+ llvm::DIArray SElements = DBuilder.getOrCreateArray(&STy, 1);
+ llvm::DIType SubTy = DBuilder.createSubroutineType(Unit, SElements);
unsigned Size = Context.getTypeSize(Context.VoidPtrTy);
- llvm::DIType vtbl_ptr_type = DBuilder.CreatePointerType(SubTy, Size, 0,
+ llvm::DIType vtbl_ptr_type = DBuilder.createPointerType(SubTy, Size, 0,
"__vtbl_ptr_type");
- VTablePtrType = DBuilder.CreatePointerType(vtbl_ptr_type, Size);
+ VTablePtrType = DBuilder.createPointerType(vtbl_ptr_type, Size);
return VTablePtrType;
}
@@ -872,7 +882,7 @@ CollectVTableInfo(const CXXRecordDecl *RD, llvm::DIFile Unit,
unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy);
llvm::DIType VPTR
- = DBuilder.CreateMemberType(getVTableName(RD), Unit,
+ = DBuilder.createMemberType(getVTableName(RD), Unit,
0, Size, 0, 0, 0,
getOrCreateVTablePtrType(Unit));
EltTys.push_back(VPTR);
@@ -882,7 +892,7 @@ CollectVTableInfo(const CXXRecordDecl *RD, llvm::DIFile Unit,
llvm::DIType CGDebugInfo::getOrCreateRecordType(QualType RTy,
SourceLocation Loc) {
llvm::DIType T = getOrCreateType(RTy, getOrCreateFile(Loc));
- DBuilder.RetainType(T);
+ DBuilder.retainType(T);
return T;
}
@@ -902,13 +912,13 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) {
// may refer to the forward decl if the struct is recursive) and replace all
// uses of the forward declaration with the final definition.
llvm::DIDescriptor FDContext =
- getContextDescriptor(dyn_cast<Decl>(RD->getDeclContext()));
+ getContextDescriptor(cast<Decl>(RD->getDeclContext()));
// If this is just a forward declaration, construct an appropriately
// marked node and just return it.
if (!RD->getDefinition()) {
llvm::DIType FwdDecl =
- DBuilder.CreateStructType(FDContext, RD->getName(),
+ DBuilder.createStructType(FDContext, RD->getName(),
DefUnit, Line, 0, 0,
llvm::DIDescriptor::FlagFwdDecl,
llvm::DIArray());
@@ -916,7 +926,7 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) {
return FwdDecl;
}
- llvm::DIType FwdDecl = DBuilder.CreateTemporaryType(DefUnit);
+ llvm::DIType FwdDecl = DBuilder.createTemporaryType(DefUnit);
llvm::MDNode *MN = FwdDecl;
llvm::TrackingVH<llvm::MDNode> FwdDeclNode = MN;
@@ -952,7 +962,7 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) {
llvm::DIType VTy = getOrCreateType(V->getType(), VUnit);
// Do not use DIGlobalVariable for enums.
if (VTy.getTag() != llvm::dwarf::DW_TAG_enumeration_type) {
- DBuilder.CreateStaticVariable(FwdDecl, VName, VName, VUnit,
+ DBuilder.createStaticVariable(FwdDecl, VName, VName, VUnit,
getLineNumber(V->getLocation()),
VTy, true, CI);
}
@@ -973,13 +983,13 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) {
if (TA.getKind() == TemplateArgument::Type) {
llvm::DIType TTy = getOrCreateType(TA.getAsType(), Unit);
llvm::DITemplateTypeParameter TTP =
- DBuilder.CreateTemplateTypeParameter(TheCU, TTy.getName(), TTy);
+ DBuilder.createTemplateTypeParameter(TheCU, TTy.getName(), TTy);
TemplateParams.push_back(TTP);
} else if (TA.getKind() == TemplateArgument::Integral) {
llvm::DIType TTy = getOrCreateType(TA.getIntegralType(), Unit);
// FIXME: Get parameter name, instead of parameter type name.
llvm::DITemplateValueParameter TVP =
- DBuilder.CreateTemplateValueParameter(TheCU, TTy.getName(), TTy,
+ DBuilder.createTemplateValueParameter(TheCU, TTy.getName(), TTy,
TA.getAsIntegral()->getZExtValue());
TemplateParams.push_back(TVP);
}
@@ -994,19 +1004,19 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) {
RegionMap.erase(RI);
llvm::DIDescriptor RDContext =
- getContextDescriptor(dyn_cast<Decl>(RD->getDeclContext()));
+ getContextDescriptor(cast<Decl>(RD->getDeclContext()));
llvm::StringRef RDName = RD->getName();
uint64_t Size = CGM.getContext().getTypeSize(Ty);
uint64_t Align = CGM.getContext().getTypeAlign(Ty);
llvm::DIArray Elements =
- DBuilder.GetOrCreateArray(EltTys.data(), EltTys.size());
+ DBuilder.getOrCreateArray(EltTys.data(), EltTys.size());
llvm::MDNode *RealDecl = NULL;
if (RD->isStruct())
- RealDecl = DBuilder.CreateStructType(RDContext, RDName, DefUnit, Line,
+ RealDecl = DBuilder.createStructType(RDContext, RDName, DefUnit, Line,
Size, Align, 0, Elements);
else if (RD->isUnion())
- RealDecl = DBuilder.CreateUnionType(RDContext, RDName, DefUnit, Line,
+ RealDecl = DBuilder.createUnionType(RDContext, RDName, DefUnit, Line,
Size, Align, 0, Elements);
else {
assert(RD->isClass() && "Unknown RecordType!");
@@ -1030,8 +1040,8 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) {
else if (CXXDecl->isDynamicClass())
ContainingType = FwdDecl;
llvm::DIArray TParamsArray =
- DBuilder.GetOrCreateArray(TemplateParams.data(), TemplateParams.size());
- RealDecl = DBuilder.CreateClassType(RDContext, RDName, DefUnit, Line,
+ DBuilder.getOrCreateArray(TemplateParams.data(), TemplateParams.size());
+ RealDecl = DBuilder.createClassType(RDContext, RDName, DefUnit, Line,
Size, Align, 0, 0, llvm::DIType(),
Elements, ContainingType,
TParamsArray);
@@ -1067,7 +1077,7 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
// debug type.
if (ID->isForwardDecl()) {
llvm::DIType FwdDecl =
- DBuilder.CreateStructType(Unit, ID->getName(),
+ DBuilder.createStructType(Unit, ID->getName(),
DefUnit, Line, 0, 0, 0,
llvm::DIArray(), RuntimeLang);
return FwdDecl;
@@ -1079,7 +1089,7 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
// its members. Finally, we create a descriptor for the complete type (which
// may refer to the forward decl if the struct is recursive) and replace all
// uses of the forward declaration with the final definition.
- llvm::DIType FwdDecl = DBuilder.CreateTemporaryType(DefUnit);
+ llvm::DIType FwdDecl = DBuilder.createTemporaryType(DefUnit);
llvm::MDNode *MN = FwdDecl;
llvm::TrackingVH<llvm::MDNode> FwdDeclNode = MN;
@@ -1101,7 +1111,7 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
return llvm::DIType();
llvm::DIType InhTag =
- DBuilder.CreateInheritance(FwdDecl, SClassTy, 0, 0);
+ DBuilder.createInheritance(FwdDecl, SClassTy, 0, 0);
EltTys.push_back(InhTag);
}
@@ -1146,14 +1156,14 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
else if (Field->getAccessControl() == ObjCIvarDecl::Private)
Flags = llvm::DIDescriptor::FlagPrivate;
- FieldTy = DBuilder.CreateMemberType(FieldName, FieldDefUnit,
+ FieldTy = DBuilder.createMemberType(FieldName, FieldDefUnit,
FieldLine, FieldSize, FieldAlign,
FieldOffset, Flags, FieldTy);
EltTys.push_back(FieldTy);
}
llvm::DIArray Elements =
- DBuilder.GetOrCreateArray(EltTys.data(), EltTys.size());
+ DBuilder.getOrCreateArray(EltTys.data(), EltTys.size());
RegionStack.pop_back();
llvm::DenseMap<const Decl *, llvm::WeakVH>::iterator RI =
@@ -1166,7 +1176,7 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
uint64_t Align = CGM.getContext().getTypeAlign(Ty);
llvm::DIType RealDecl =
- DBuilder.CreateStructType(Unit, ID->getName(), DefUnit,
+ DBuilder.createStructType(Unit, ID->getName(), DefUnit,
Line, Size, Align, 0,
Elements, RuntimeLang);
@@ -1194,14 +1204,14 @@ llvm::DIType CGDebugInfo::CreateType(const VectorType *Ty,
if (NumElems > 0)
--NumElems;
- llvm::Value *Subscript = DBuilder.GetOrCreateSubrange(0, NumElems);
- llvm::DIArray SubscriptArray = DBuilder.GetOrCreateArray(&Subscript, 1);
+ llvm::Value *Subscript = DBuilder.getOrCreateSubrange(0, NumElems);
+ llvm::DIArray SubscriptArray = DBuilder.getOrCreateArray(&Subscript, 1);
uint64_t Size = CGM.getContext().getTypeSize(Ty);
uint64_t Align = CGM.getContext().getTypeAlign(Ty);
return
- DBuilder.CreateVectorType(Size, Align, ElementTy, SubscriptArray);
+ DBuilder.createVectorType(Size, Align, ElementTy, SubscriptArray);
}
llvm::DIType CGDebugInfo::CreateType(const ArrayType *Ty,
@@ -1238,16 +1248,16 @@ llvm::DIType CGDebugInfo::CreateType(const ArrayType *Ty,
if (CAT->getSize().getZExtValue())
Upper = CAT->getSize().getZExtValue() - 1;
// FIXME: Verify this is right for VLAs.
- Subscripts.push_back(DBuilder.GetOrCreateSubrange(0, Upper));
+ Subscripts.push_back(DBuilder.getOrCreateSubrange(0, Upper));
EltTy = Ty->getElementType();
}
}
llvm::DIArray SubscriptArray =
- DBuilder.GetOrCreateArray(Subscripts.data(), Subscripts.size());
+ DBuilder.getOrCreateArray(Subscripts.data(), Subscripts.size());
llvm::DIType DbgTy =
- DBuilder.CreateArrayType(Size, Align, getOrCreateType(EltTy, Unit),
+ DBuilder.createArrayType(Size, Align, getOrCreateType(EltTy, Unit),
SubscriptArray);
return DbgTy;
}
@@ -1283,21 +1293,21 @@ llvm::DIType CGDebugInfo::CreateType(const MemberPointerType *Ty,
// FIXME: This should probably be a function type instead.
ElementTypes[0] =
- DBuilder.CreateMemberType("ptr", U, 0,
+ DBuilder.createMemberType("ptr", U, 0,
Info.first, Info.second, FieldOffset, 0,
PointerDiffDITy);
FieldOffset += Info.first;
ElementTypes[1] =
- DBuilder.CreateMemberType("ptr", U, 0,
+ DBuilder.createMemberType("ptr", U, 0,
Info.first, Info.second, FieldOffset, 0,
PointerDiffDITy);
llvm::DIArray Elements =
- DBuilder.GetOrCreateArray(&ElementTypes[0],
+ DBuilder.getOrCreateArray(&ElementTypes[0],
llvm::array_lengthof(ElementTypes));
- return DBuilder.CreateStructType(U, llvm::StringRef("test"),
+ return DBuilder.createStructType(U, llvm::StringRef("test"),
U, 0, FieldOffset,
0, 0, Elements);
}
@@ -1312,13 +1322,13 @@ llvm::DIType CGDebugInfo::CreateEnumType(const EnumDecl *ED) {
Enum = ED->enumerator_begin(), EnumEnd = ED->enumerator_end();
Enum != EnumEnd; ++Enum) {
Enumerators.push_back(
- DBuilder.CreateEnumerator(Enum->getName(),
+ DBuilder.createEnumerator(Enum->getName(),
Enum->getInitVal().getZExtValue()));
}
// Return a CompositeType for the enum itself.
llvm::DIArray EltArray =
- DBuilder.GetOrCreateArray(Enumerators.data(), Enumerators.size());
+ DBuilder.getOrCreateArray(Enumerators.data(), Enumerators.size());
llvm::DIFile DefUnit = getOrCreateFile(ED->getLocation());
unsigned Line = getLineNumber(ED->getLocation());
@@ -1329,9 +1339,9 @@ llvm::DIType CGDebugInfo::CreateEnumType(const EnumDecl *ED) {
Align = CGM.getContext().getTypeAlign(ED->getTypeForDecl());
}
llvm::DIDescriptor EnumContext =
- getContextDescriptor(dyn_cast<Decl>(ED->getDeclContext()));
+ getContextDescriptor(cast<Decl>(ED->getDeclContext()));
llvm::DIType DbgTy =
- DBuilder.CreateEnumerationType(EnumContext, ED->getName(), DefUnit, Line,
+ DBuilder.createEnumerationType(EnumContext, ED->getName(), DefUnit, Line,
Size, Align, EltArray);
return DbgTy;
}
@@ -1485,7 +1495,7 @@ llvm::DIType CGDebugInfo::CreateMemberType(llvm::DIFile Unit, QualType FType,
llvm::DIType FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
uint64_t FieldSize = CGM.getContext().getTypeSize(FType);
unsigned FieldAlign = CGM.getContext().getTypeAlign(FType);
- llvm::DIType Ty = DBuilder.CreateMemberType(Name, Unit, 0,
+ llvm::DIType Ty = DBuilder.createMemberType(Name, Unit, 0,
FieldSize, FieldAlign,
*Offset, 0, FieldTy);
*Offset += FieldSize;
@@ -1548,7 +1558,7 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, QualType FnType,
if (D->isImplicit())
Flags |= llvm::DIDescriptor::FlagArtificial;
llvm::DISubprogram SP =
- DBuilder.CreateFunction(FDContext, Name, LinkageName, Unit,
+ DBuilder.createFunction(FDContext, Name, LinkageName, Unit,
LineNo, getOrCreateType(FnType, Unit),
Fn->hasInternalLinkage(), true/*definition*/,
Flags, CGM.getLangOptions().Optimize, Fn);
@@ -1640,7 +1650,7 @@ void CGDebugInfo::UpdateLineDirectiveRegion(CGBuilderTy &Builder) {
/// region - "llvm.dbg.region.start.".
void CGDebugInfo::EmitRegionStart(CGBuilderTy &Builder) {
llvm::DIDescriptor D =
- DBuilder.CreateLexicalBlock(RegionStack.empty() ?
+ DBuilder.createLexicalBlock(RegionStack.empty() ?
llvm::DIDescriptor() :
llvm::DIDescriptor(RegionStack.back()),
getOrCreateFile(CurLoc),
@@ -1725,18 +1735,18 @@ llvm::DIType CGDebugInfo::EmitTypeForVarWithBlocksAttr(const ValueDecl *VD,
FieldAlign = Align.getQuantity()*8;
*XOffset = FieldOffset;
- FieldTy = DBuilder.CreateMemberType(VD->getName(), Unit,
+ FieldTy = DBuilder.createMemberType(VD->getName(), Unit,
0, FieldSize, FieldAlign,
FieldOffset, 0, FieldTy);
EltTys.push_back(FieldTy);
FieldOffset += FieldSize;
llvm::DIArray Elements =
- DBuilder.GetOrCreateArray(EltTys.data(), EltTys.size());
+ DBuilder.getOrCreateArray(EltTys.data(), EltTys.size());
unsigned Flags = llvm::DIDescriptor::FlagBlockByrefStruct;
- return DBuilder.CreateStructType(Unit, "", Unit, 0, FieldOffset, 0, Flags,
+ return DBuilder.createStructType(Unit, "", Unit, 0, FieldOffset, 0, Flags,
Elements);
}
@@ -1762,13 +1772,13 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag,
// If Storage is an aggregate returned as 'sret' then let debugger know
// about this.
if (Arg->hasStructRetAttr())
- Ty = DBuilder.CreateReferenceType(Ty);
+ Ty = DBuilder.createReferenceType(Ty);
else if (CXXRecordDecl *Record = VD->getType()->getAsCXXRecordDecl()) {
// If an aggregate variable has non trivial destructor or non trivial copy
// constructor than it is pass indirectly. Let debug info know about this
// by using reference of the aggregate type as a argument type.
if (!Record->hasTrivialCopyConstructor() || !Record->hasTrivialDestructor())
- Ty = DBuilder.CreateReferenceType(Ty);
+ Ty = DBuilder.createReferenceType(Ty);
}
}
@@ -1799,27 +1809,27 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag,
// Create the descriptor for the variable.
llvm::DIVariable D =
- DBuilder.CreateComplexVariable(Tag,
+ DBuilder.createComplexVariable(Tag,
llvm::DIDescriptor(RegionStack.back()),
VD->getName(), Unit, Line, Ty,
addr.data(), addr.size());
// Insert an llvm.dbg.declare into the current block.
llvm::Instruction *Call =
- DBuilder.InsertDeclare(Storage, D, Builder.GetInsertBlock());
+ DBuilder.insertDeclare(Storage, D, Builder.GetInsertBlock());
Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope));
return;
}
// Create the descriptor for the variable.
llvm::DIVariable D =
- DBuilder.CreateLocalVariable(Tag, llvm::DIDescriptor(Scope),
+ DBuilder.createLocalVariable(Tag, llvm::DIDescriptor(Scope),
Name, Unit, Line, Ty,
CGM.getLangOptions().Optimize, Flags);
// Insert an llvm.dbg.declare into the current block.
llvm::Instruction *Call =
- DBuilder.InsertDeclare(Storage, D, Builder.GetInsertBlock());
+ DBuilder.insertDeclare(Storage, D, Builder.GetInsertBlock());
Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope));
return;
@@ -1827,33 +1837,34 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag,
// If VD is an anonymous union then Storage represents value for
// all union fields.
- if (const RecordType *RT = dyn_cast<RecordType>(VD->getType()))
- if (const RecordDecl *RD = dyn_cast<RecordDecl>(RT->getDecl()))
- if (RD->isUnion()) {
- for (RecordDecl::field_iterator I = RD->field_begin(),
- E = RD->field_end();
- I != E; ++I) {
- FieldDecl *Field = *I;
- llvm::DIType FieldTy = getOrCreateType(Field->getType(), Unit);
- llvm::StringRef FieldName = Field->getName();
+ if (const RecordType *RT = dyn_cast<RecordType>(VD->getType())) {
+ const RecordDecl *RD = cast<RecordDecl>(RT->getDecl());
+ if (RD->isUnion()) {
+ for (RecordDecl::field_iterator I = RD->field_begin(),
+ E = RD->field_end();
+ I != E; ++I) {
+ FieldDecl *Field = *I;
+ llvm::DIType FieldTy = getOrCreateType(Field->getType(), Unit);
+ llvm::StringRef FieldName = Field->getName();
- // Ignore unnamed fields. Do not ignore unnamed records.
- if (FieldName.empty() && !isa<RecordType>(Field->getType()))
- continue;
+ // Ignore unnamed fields. Do not ignore unnamed records.
+ if (FieldName.empty() && !isa<RecordType>(Field->getType()))
+ continue;
- // Use VarDecl's Tag, Scope and Line number.
- llvm::DIVariable D =
- DBuilder.CreateLocalVariable(Tag, llvm::DIDescriptor(Scope),
- FieldName, Unit, Line, FieldTy,
- CGM.getLangOptions().Optimize, Flags);
+ // Use VarDecl's Tag, Scope and Line number.
+ llvm::DIVariable D =
+ DBuilder.createLocalVariable(Tag, llvm::DIDescriptor(Scope),
+ FieldName, Unit, Line, FieldTy,
+ CGM.getLangOptions().Optimize, Flags);
- // Insert an llvm.dbg.declare into the current block.
- llvm::Instruction *Call =
- DBuilder.InsertDeclare(Storage, D, Builder.GetInsertBlock());
+ // Insert an llvm.dbg.declare into the current block.
+ llvm::Instruction *Call =
+ DBuilder.insertDeclare(Storage, D, Builder.GetInsertBlock());
- Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope));
- }
+ Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope));
}
+ }
+ }
}
/// EmitDeclare - Emit local variable declaration debug info.
@@ -1887,7 +1898,6 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag,
llvm::SmallVector<llvm::Value *, 9> addr;
const llvm::Type *Int64Ty = llvm::Type::getInt64Ty(CGM.getLLVMContext());
- addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpDeref));
addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpPlus));
addr.push_back(llvm::ConstantInt::get(Int64Ty, offset.getQuantity()));
if (isByRef) {
@@ -1905,12 +1915,12 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag,
// Create the descriptor for the variable.
llvm::DIVariable D =
- DBuilder.CreateComplexVariable(Tag, llvm::DIDescriptor(RegionStack.back()),
+ DBuilder.createComplexVariable(Tag, llvm::DIDescriptor(RegionStack.back()),
VD->getName(), Unit, Line, Ty,
addr.data(), addr.size());
// Insert an llvm.dbg.declare into the current block.
llvm::Instruction *Call =
- DBuilder.InsertDeclare(Storage, D, Builder.GetInsertBlock());
+ DBuilder.insertDeclare(Storage, D, Builder.GetInsertBlock());
llvm::MDNode *Scope = RegionStack.back();
Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope));
@@ -1936,7 +1946,146 @@ void CGDebugInfo::EmitDeclareOfArgVariable(const VarDecl *VD, llvm::Value *AI,
EmitDeclare(VD, llvm::dwarf::DW_TAG_arg_variable, AI, Builder);
}
+namespace {
+ struct BlockLayoutChunk {
+ uint64_t OffsetInBits;
+ const BlockDecl::Capture *Capture;
+ };
+ bool operator<(const BlockLayoutChunk &l, const BlockLayoutChunk &r) {
+ return l.OffsetInBits < r.OffsetInBits;
+ }
+}
+
+void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,
+ llvm::Value *addr,
+ CGBuilderTy &Builder) {
+ ASTContext &C = CGM.getContext();
+ const BlockDecl *blockDecl = block.getBlockDecl();
+
+ // Collect some general information about the block's location.
+ SourceLocation loc = blockDecl->getCaretLocation();
+ llvm::DIFile tunit = getOrCreateFile(loc);
+ unsigned line = getLineNumber(loc);
+ unsigned column = getColumnNumber(loc);
+
+ // Build the debug-info type for the block literal.
+ llvm::DIDescriptor enclosingContext =
+ getContextDescriptor(cast<Decl>(blockDecl->getDeclContext()));
+
+ const llvm::StructLayout *blockLayout =
+ CGM.getTargetData().getStructLayout(block.StructureType);
+
+ llvm::SmallVector<llvm::Value*, 16> fields;
+ fields.push_back(createFieldType("__isa", C.VoidPtrTy, 0, loc, AS_public,
+ blockLayout->getElementOffsetInBits(0),
+ tunit));
+ fields.push_back(createFieldType("__flags", C.IntTy, 0, loc, AS_public,
+ blockLayout->getElementOffsetInBits(1),
+ tunit));
+ fields.push_back(createFieldType("__reserved", C.IntTy, 0, loc, AS_public,
+ blockLayout->getElementOffsetInBits(2),
+ tunit));
+ fields.push_back(createFieldType("__FuncPtr", C.VoidPtrTy, 0, loc, AS_public,
+ blockLayout->getElementOffsetInBits(3),
+ tunit));
+ fields.push_back(createFieldType("__descriptor",
+ C.getPointerType(block.NeedsCopyDispose ?
+ C.getBlockDescriptorExtendedType() :
+ C.getBlockDescriptorType()),
+ 0, loc, AS_public,
+ blockLayout->getElementOffsetInBits(4),
+ tunit));
+
+ // We want to sort the captures by offset, not because DWARF
+ // requires this, but because we're paranoid about debuggers.
+ llvm::SmallVector<BlockLayoutChunk, 8> chunks;
+
+ // 'this' capture.
+ if (blockDecl->capturesCXXThis()) {
+ BlockLayoutChunk chunk;
+ chunk.OffsetInBits =
+ blockLayout->getElementOffsetInBits(block.CXXThisIndex);
+ chunk.Capture = 0;
+ chunks.push_back(chunk);
+ }
+
+ // Variable captures.
+ for (BlockDecl::capture_const_iterator
+ i = blockDecl->capture_begin(), e = blockDecl->capture_end();
+ i != e; ++i) {
+ const BlockDecl::Capture &capture = *i;
+ const VarDecl *variable = capture.getVariable();
+ const CGBlockInfo::Capture &captureInfo = block.getCapture(variable);
+ // Ignore constant captures.
+ if (captureInfo.isConstant())
+ continue;
+
+ BlockLayoutChunk chunk;
+ chunk.OffsetInBits =
+ blockLayout->getElementOffsetInBits(captureInfo.getIndex());
+ chunk.Capture = &capture;
+ chunks.push_back(chunk);
+ }
+
+ // Sort by offset.
+ llvm::array_pod_sort(chunks.begin(), chunks.end());
+
+ for (llvm::SmallVectorImpl<BlockLayoutChunk>::iterator
+ i = chunks.begin(), e = chunks.end(); i != e; ++i) {
+ uint64_t offsetInBits = i->OffsetInBits;
+ const BlockDecl::Capture *capture = i->Capture;
+
+ // If we have a null capture, this must be the C++ 'this' capture.
+ if (!capture) {
+ const CXXMethodDecl *method =
+ cast<CXXMethodDecl>(blockDecl->getNonClosureContext());
+ QualType type = method->getThisType(C);
+
+ fields.push_back(createFieldType("this", type, 0, loc, AS_public,
+ offsetInBits, tunit));
+ continue;
+ }
+
+ const VarDecl *variable = capture->getVariable();
+ QualType type = (capture->isByRef() ? C.VoidPtrTy : variable->getType());
+ llvm::StringRef name = variable->getName();
+ fields.push_back(createFieldType(name, type, 0, loc, AS_public,
+ offsetInBits, tunit));
+ }
+
+ llvm::SmallString<36> typeName;
+ llvm::raw_svector_ostream(typeName)
+ << "__block_literal_" << CGM.getUniqueBlockCount();
+
+ llvm::DIArray fieldsArray =
+ DBuilder.getOrCreateArray(fields.data(), fields.size());
+
+ llvm::DIType type =
+ DBuilder.createStructType(tunit, typeName.str(), tunit, line,
+ CGM.getContext().toBits(block.BlockSize),
+ CGM.getContext().toBits(block.BlockAlign),
+ 0, fieldsArray);
+ type = DBuilder.createPointerType(type, CGM.PointerWidthInBits);
+
+ // Get overall information about the block.
+ unsigned flags = llvm::DIDescriptor::FlagArtificial;
+ llvm::MDNode *scope = RegionStack.back();
+ llvm::StringRef name = ".block_descriptor";
+
+ // Create the descriptor for the parameter.
+ llvm::DIVariable debugVar =
+ DBuilder.createLocalVariable(llvm::dwarf::DW_TAG_arg_variable,
+ llvm::DIDescriptor(scope),
+ name, tunit, line, type,
+ CGM.getLangOptions().Optimize, flags);
+
+ // Insert an llvm.dbg.value into the current block.
+ llvm::Instruction *declare =
+ DBuilder.insertDbgValueIntrinsic(addr, 0, debugVar,
+ Builder.GetInsertBlock());
+ declare->setDebugLoc(llvm::DebugLoc::get(line, column, scope));
+}
/// EmitGlobalVariable - Emit information about a global variable.
void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
@@ -1967,7 +2116,7 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
LinkageName = llvm::StringRef();
llvm::DIDescriptor DContext =
getContextDescriptor(dyn_cast<Decl>(D->getDeclContext()));
- DBuilder.CreateStaticVariable(DContext, DeclName, LinkageName,
+ DBuilder.createStaticVariable(DContext, DeclName, LinkageName,
Unit, LineNo, getOrCreateType(T, Unit),
Var->hasInternalLinkage(), Var);
}
@@ -1994,7 +2143,7 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
ArrayType::Normal, 0);
}
- DBuilder.CreateGlobalVariable(Name, Unit, LineNo,
+ DBuilder.createGlobalVariable(Name, Unit, LineNo,
getOrCreateType(T, Unit),
Var->hasInternalLinkage(), Var);
}
@@ -2013,7 +2162,7 @@ void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD,
// Do not use DIGlobalVariable for enums.
if (Ty.getTag() == llvm::dwarf::DW_TAG_enumeration_type)
return;
- DBuilder.CreateStaticVariable(Unit, Name, Name, Unit,
+ DBuilder.createStaticVariable(Unit, Name, Name, Unit,
getLineNumber(VD->getLocation()),
Ty, true, Init);
}
@@ -2032,7 +2181,7 @@ CGDebugInfo::getOrCreateNameSpace(const NamespaceDecl *NSDecl) {
llvm::DIDescriptor Context =
getContextDescriptor(dyn_cast<Decl>(NSDecl->getDeclContext()));
llvm::DINameSpace NS =
- DBuilder.CreateNameSpace(Context, NSDecl->getName(), FileD, LineNo);
+ DBuilder.createNameSpace(Context, NSDecl->getName(), FileD, LineNo);
NameSpaceCache[NSDecl] = llvm::WeakVH(NS);
return NS;
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.h b/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.h
index 6a9ab9c..a390788 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.h
@@ -123,7 +123,10 @@ class CGDebugInfo {
llvm::SmallVectorImpl<llvm::Value *> &EltTys,
llvm::DIType RecordTy);
-
+ llvm::DIType createFieldType(llvm::StringRef name, QualType type,
+ Expr *bitWidth, SourceLocation loc,
+ AccessSpecifier AS, uint64_t offsetInBits,
+ llvm::DIFile tunit);
void CollectRecordFields(const RecordDecl *Decl, llvm::DIFile F,
llvm::SmallVectorImpl<llvm::Value *> &E);
@@ -180,6 +183,13 @@ public:
void EmitDeclareOfArgVariable(const VarDecl *Decl, llvm::Value *AI,
CGBuilderTy &Builder);
+ /// EmitDeclareOfBlockLiteralArgVariable - Emit call to
+ /// llvm.dbg.declare for the block-literal argument to a block
+ /// invocation function.
+ void EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,
+ llvm::Value *addr,
+ CGBuilderTy &Builder);
+
/// EmitGlobalVariable - Emit information about a global variable.
void EmitGlobalVariable(llvm::GlobalVariable *GV, const VarDecl *Decl);
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGDecl.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGDecl.cpp
index a87dfae..f4db01d 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGDecl.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGDecl.cpp
@@ -474,14 +474,19 @@ namespace {
struct CallCleanupFunction : EHScopeStack::Cleanup {
llvm::Constant *CleanupFn;
const CGFunctionInfo &FnInfo;
- llvm::Value *Addr;
const VarDecl &Var;
CallCleanupFunction(llvm::Constant *CleanupFn, const CGFunctionInfo *Info,
- llvm::Value *Addr, const VarDecl *Var)
- : CleanupFn(CleanupFn), FnInfo(*Info), Addr(Addr), Var(*Var) {}
+ const VarDecl *Var)
+ : CleanupFn(CleanupFn), FnInfo(*Info), Var(*Var) {}
void Emit(CodeGenFunction &CGF, bool IsForEH) {
+ DeclRefExpr DRE(const_cast<VarDecl*>(&Var), Var.getType(), VK_LValue,
+ SourceLocation());
+ // Compute the address of the local variable, in case it's a byref
+ // or something.
+ llvm::Value *Addr = CGF.EmitDeclRefLValue(&DRE).getAddress();
+
// In some cases, the type of the function argument will be different from
// the type of the pointer. An example of this is
// void f(void* arg);
@@ -543,7 +548,7 @@ static bool canEmitInitWithFewStoresAfterMemset(llvm::Constant *Init,
/// canEmitInitWithFewStoresAfterMemset returned true for, emit the scalar
/// stores that would be required.
static void emitStoresForInitAfterMemset(llvm::Constant *Init, llvm::Value *Loc,
- CGBuilderTy &Builder) {
+ bool isVolatile, CGBuilderTy &Builder) {
// Zero doesn't require any stores.
if (isa<llvm::ConstantAggregateZero>(Init) ||
isa<llvm::ConstantPointerNull>(Init) ||
@@ -554,7 +559,7 @@ static void emitStoresForInitAfterMemset(llvm::Constant *Init, llvm::Value *Loc,
isa<llvm::ConstantVector>(Init) || isa<llvm::BlockAddress>(Init) ||
isa<llvm::ConstantExpr>(Init)) {
if (!Init->isNullValue())
- Builder.CreateStore(Init, Loc);
+ Builder.CreateStore(Init, Loc, isVolatile);
return;
}
@@ -567,7 +572,7 @@ static void emitStoresForInitAfterMemset(llvm::Constant *Init, llvm::Value *Loc,
// Otherwise, get a pointer to the element and emit it.
emitStoresForInitAfterMemset(Elt, Builder.CreateConstGEP2_32(Loc, 0, i),
- Builder);
+ isVolatile, Builder);
}
}
@@ -597,37 +602,55 @@ static bool shouldUseMemSetPlusStoresToInitialize(llvm::Constant *Init,
/// EmitAutoVarDecl - Emit code and set up an entry in LocalDeclMap for a
/// variable declaration with auto, register, or no storage class specifier.
/// These turn into simple stack objects, or GlobalValues depending on target.
-void CodeGenFunction::EmitAutoVarDecl(const VarDecl &D,
- SpecialInitFn *SpecialInit) {
+void CodeGenFunction::EmitAutoVarDecl(const VarDecl &D) {
+ AutoVarEmission emission = EmitAutoVarAlloca(D);
+ EmitAutoVarInit(emission);
+ EmitAutoVarCleanups(emission);
+}
+
+/// EmitAutoVarAlloca - Emit the alloca and debug information for a
+/// local variable. Does not emit initalization or destruction.
+CodeGenFunction::AutoVarEmission
+CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
QualType Ty = D.getType();
- unsigned Alignment = getContext().getDeclAlign(&D).getQuantity();
+
+ AutoVarEmission emission(D);
+
bool isByRef = D.hasAttr<BlocksAttr>();
- bool needsDispose = false;
- CharUnits Align = CharUnits::Zero();
- bool IsSimpleConstantInitializer = false;
+ emission.IsByRef = isByRef;
+
+ CharUnits alignment = getContext().getDeclAlign(&D);
+ emission.Alignment = alignment;
- bool NRVO = false;
- llvm::Value *NRVOFlag = 0;
llvm::Value *DeclPtr;
if (Ty->isConstantSizeType()) {
if (!Target.useGlobalsForAutomaticVariables()) {
- NRVO = getContext().getLangOptions().ElideConstructors &&
- D.isNRVOVariable();
- // If this value is an array or struct, is POD, and if the initializer is
- // a staticly determinable constant, try to optimize it (unless the NRVO
- // is already optimizing this).
- if (!NRVO && D.getInit() && !isByRef &&
- (Ty->isArrayType() || Ty->isRecordType()) &&
- Ty->isPODType() &&
+ bool NRVO = getContext().getLangOptions().ElideConstructors &&
+ D.isNRVOVariable();
+
+ // If this value is a POD array or struct with a statically
+ // determinable constant initializer, there are optimizations we
+ // can do.
+ // TODO: we can potentially constant-evaluate non-POD structs and
+ // arrays as long as the initialization is trivial (e.g. if they
+ // have a non-trivial destructor, but not a non-trivial constructor).
+ if (D.getInit() &&
+ (Ty->isArrayType() || Ty->isRecordType()) && Ty->isPODType() &&
D.getInit()->isConstantInitializer(getContext(), false)) {
- // If this variable is marked 'const', emit the value as a global.
- if (CGM.getCodeGenOpts().MergeAllConstants &&
- Ty.isConstant(getContext())) {
- EmitStaticVarDecl(D, llvm::GlobalValue::InternalLinkage);
- return;
+
+ // If the variable's a const type, and it's neither an NRVO
+ // candidate nor a __block variable, emit it as a global instead.
+ if (CGM.getCodeGenOpts().MergeAllConstants && Ty.isConstQualified() &&
+ !NRVO && !isByRef) {
+ EmitStaticVarDecl(D, llvm::GlobalValue::PrivateLinkage);
+
+ emission.Address = 0; // signal this condition to later callbacks
+ assert(emission.wasEmittedAsGlobal());
+ return emission;
}
-
- IsSimpleConstantInitializer = true;
+
+ // Otherwise, tell the initialization code that we're in this case.
+ emission.IsConstantAggregate = true;
}
// A normal fixed sized variable becomes an alloca in the entry block,
@@ -646,12 +669,13 @@ void CodeGenFunction::EmitAutoVarDecl(const VarDecl &D,
// to this variable. Set it to zero to indicate that NRVO was not
// applied.
llvm::Value *Zero = Builder.getFalse();
- NRVOFlag = CreateTempAlloca(Zero->getType(), "nrvo");
+ llvm::Value *NRVOFlag = CreateTempAlloca(Zero->getType(), "nrvo");
EnsureInsertPoint();
Builder.CreateStore(Zero, NRVOFlag);
// Record the NRVO flag for this variable.
NRVOFlags[&D] = NRVOFlag;
+ emission.NRVOFlag = NRVOFlag;
}
}
} else {
@@ -661,11 +685,11 @@ void CodeGenFunction::EmitAutoVarDecl(const VarDecl &D,
llvm::AllocaInst *Alloc = CreateTempAlloca(LTy);
Alloc->setName(D.getNameAsString());
- Align = getContext().getDeclAlign(&D);
+ CharUnits allocaAlignment = alignment;
if (isByRef)
- Align = std::max(Align,
+ allocaAlignment = std::max(allocaAlignment,
getContext().toCharUnitsFromBits(Target.getPointerAlign(0)));
- Alloc->setAlignment(Align.getQuantity());
+ Alloc->setAlignment(allocaAlignment.getQuantity());
DeclPtr = Alloc;
}
} else {
@@ -707,7 +731,7 @@ void CodeGenFunction::EmitAutoVarDecl(const VarDecl &D,
// Allocate memory for the array.
llvm::AllocaInst *VLA =
Builder.CreateAlloca(llvm::Type::getInt8Ty(getLLVMContext()), VLASize, "vla");
- VLA->setAlignment(getContext().getDeclAlign(&D).getQuantity());
+ VLA->setAlignment(alignment.getQuantity());
DeclPtr = Builder.CreateBitCast(VLA, LElemPtrTy, "tmp");
}
@@ -715,6 +739,7 @@ void CodeGenFunction::EmitAutoVarDecl(const VarDecl &D,
llvm::Value *&DMEntry = LocalDeclMap[&D];
assert(DMEntry == 0 && "Decl already exists in localdeclmap!");
DMEntry = DeclPtr;
+ emission.Address = DeclPtr;
// Emit debug info for local var declaration.
if (CGDebugInfo *DI = getDebugInfo()) {
@@ -727,53 +752,92 @@ void CodeGenFunction::EmitAutoVarDecl(const VarDecl &D,
DI->EmitDeclareOfAutoVariable(&D, DeclPtr, Builder);
}
+ return emission;
+}
+
+/// Determines whether the given __block variable is potentially
+/// captured by the given expression.
+static bool isCapturedBy(const VarDecl &var, const Expr *e) {
+ // Skip the most common kinds of expressions that make
+ // hierarchy-walking expensive.
+ e = e->IgnoreParenCasts();
+
+ if (const BlockExpr *be = dyn_cast<BlockExpr>(e)) {
+ const BlockDecl *block = be->getBlockDecl();
+ for (BlockDecl::capture_const_iterator i = block->capture_begin(),
+ e = block->capture_end(); i != e; ++i) {
+ if (i->getVariable() == &var)
+ return true;
+ }
+
+ // No need to walk into the subexpressions.
+ return false;
+ }
+
+ for (Stmt::const_child_range children = e->children(); children; ++children)
+ if (isCapturedBy(var, cast<Expr>(*children)))
+ return true;
+
+ return false;
+}
+
+void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
+ assert(emission.Variable && "emission was not valid!");
+
+ // If this was emitted as a global constant, we're done.
+ if (emission.wasEmittedAsGlobal()) return;
+
+ const VarDecl &D = *emission.Variable;
+ QualType type = D.getType();
+
// If this local has an initializer, emit it now.
const Expr *Init = D.getInit();
// If we are at an unreachable point, we don't need to emit the initializer
// unless it contains a label.
if (!HaveInsertPoint()) {
- if (!ContainsLabel(Init))
- Init = 0;
- else
- EnsureInsertPoint();
+ if (!Init || !ContainsLabel(Init)) return;
+ EnsureInsertPoint();
}
- if (isByRef) {
- EnsureInsertPoint();
+ CharUnits alignment = emission.Alignment;
+
+ if (emission.IsByRef) {
llvm::Value *V;
BlockFieldFlags fieldFlags;
bool fieldNeedsCopyDispose = false;
- needsDispose = true;
-
- if (Ty->isBlockPointerType()) {
+ if (type->isBlockPointerType()) {
fieldFlags |= BLOCK_FIELD_IS_BLOCK;
fieldNeedsCopyDispose = true;
- } else if (getContext().isObjCNSObjectType(Ty) ||
- Ty->isObjCObjectPointerType()) {
+ } else if (getContext().isObjCNSObjectType(type) ||
+ type->isObjCObjectPointerType()) {
fieldFlags |= BLOCK_FIELD_IS_OBJECT;
fieldNeedsCopyDispose = true;
} else if (getLangOptions().CPlusPlus) {
if (getContext().getBlockVarCopyInits(&D))
fieldNeedsCopyDispose = true;
- else if (const CXXRecordDecl *record = D.getType()->getAsCXXRecordDecl())
+ else if (const CXXRecordDecl *record = type->getAsCXXRecordDecl())
fieldNeedsCopyDispose = !record->hasTrivialDestructor();
}
+ llvm::Value *addr = emission.Address;
+
// FIXME: Someone double check this.
- if (Ty.isObjCGCWeak())
+ if (type.isObjCGCWeak())
fieldFlags |= BLOCK_FIELD_IS_WEAK;
+ // Initialize the 'isa', which is just 0 or 1.
int isa = 0;
if (fieldFlags & BLOCK_FIELD_IS_WEAK)
isa = 1;
V = Builder.CreateIntToPtr(Builder.getInt32(isa), Int8PtrTy, "isa");
- Builder.CreateStore(V, Builder.CreateStructGEP(DeclPtr, 0, "byref.isa"));
+ Builder.CreateStore(V, Builder.CreateStructGEP(addr, 0, "byref.isa"));
- Builder.CreateStore(DeclPtr, Builder.CreateStructGEP(DeclPtr, 1,
- "byref.forwarding"));
+ // Store the address of the variable into its own forwarding pointer.
+ Builder.CreateStore(addr,
+ Builder.CreateStructGEP(addr, 1, "byref.forwarding"));
// Blocks ABI:
// c) the flags field is set to either 0 if no helper functions are
@@ -781,150 +845,157 @@ void CodeGenFunction::EmitAutoVarDecl(const VarDecl &D,
BlockFlags flags;
if (fieldNeedsCopyDispose) flags |= BLOCK_HAS_COPY_DISPOSE;
Builder.CreateStore(llvm::ConstantInt::get(IntTy, flags.getBitMask()),
- Builder.CreateStructGEP(DeclPtr, 2, "byref.flags"));
+ Builder.CreateStructGEP(addr, 2, "byref.flags"));
const llvm::Type *V1;
- V1 = cast<llvm::PointerType>(DeclPtr->getType())->getElementType();
+ V1 = cast<llvm::PointerType>(addr->getType())->getElementType();
V = llvm::ConstantInt::get(IntTy, CGM.GetTargetTypeStoreSize(V1).getQuantity());
- Builder.CreateStore(V, Builder.CreateStructGEP(DeclPtr, 3, "byref.size"));
+ Builder.CreateStore(V, Builder.CreateStructGEP(addr, 3, "byref.size"));
if (fieldNeedsCopyDispose) {
- llvm::Value *copy_helper = Builder.CreateStructGEP(DeclPtr, 4);
- Builder.CreateStore(CGM.BuildbyrefCopyHelper(DeclPtr->getType(),
- fieldFlags,
- Align.getQuantity(), &D),
+ llvm::Value *copy_helper = Builder.CreateStructGEP(addr, 4);
+ Builder.CreateStore(CGM.BuildbyrefCopyHelper(addr->getType(), fieldFlags,
+ alignment.getQuantity(), &D),
copy_helper);
- llvm::Value *destroy_helper = Builder.CreateStructGEP(DeclPtr, 5);
- Builder.CreateStore(CGM.BuildbyrefDestroyHelper(DeclPtr->getType(),
+ llvm::Value *destroy_helper = Builder.CreateStructGEP(addr, 5);
+ Builder.CreateStore(CGM.BuildbyrefDestroyHelper(addr->getType(),
fieldFlags,
- Align.getQuantity(), &D),
+ alignment.getQuantity(),
+ &D),
destroy_helper);
}
}
- if (SpecialInit) {
- SpecialInit(*this, D, DeclPtr);
- } else if (Init) {
- llvm::Value *Loc = DeclPtr;
-
- bool isVolatile = getContext().getCanonicalType(Ty).isVolatileQualified();
+ if (!Init) return;
+
+ // Check whether this is a byref variable that's potentially
+ // captured and moved by its own initializer. If so, we'll need to
+ // emit the initializer first, then copy into the variable.
+ bool capturedByInit = emission.IsByRef && isCapturedBy(D, Init);
+
+ llvm::Value *Loc =
+ capturedByInit ? emission.Address : emission.getObjectAddress(*this);
+
+ bool isVolatile = type.isVolatileQualified();
- // If the initializer was a simple constant initializer, we can optimize it
- // in various ways.
- if (IsSimpleConstantInitializer) {
- llvm::Constant *Init = CGM.EmitConstantExpr(D.getInit(), Ty,this);
- assert(Init != 0 && "Wasn't a simple constant init?");
-
- llvm::Value *SizeVal =
- llvm::ConstantInt::get(IntPtrTy,
- getContext().getTypeSizeInChars(Ty).getQuantity());
-
- const llvm::Type *BP = Int8PtrTy;
- if (Loc->getType() != BP)
- Loc = Builder.CreateBitCast(Loc, BP, "tmp");
+ // If this is a simple aggregate initialization, we can optimize it
+ // in various ways.
+ if (emission.IsConstantAggregate) {
+ assert(!capturedByInit && "constant init contains a capturing block?");
+
+ llvm::Constant *Init = CGM.EmitConstantExpr(D.getInit(), type, this);
+ assert(Init != 0 && "Wasn't a simple constant init?");
- // If the initializer is all or mostly zeros, codegen with memset then do
- // a few stores afterward.
- if (shouldUseMemSetPlusStoresToInitialize(Init,
+ llvm::Value *SizeVal =
+ llvm::ConstantInt::get(IntPtrTy,
+ getContext().getTypeSizeInChars(type).getQuantity());
+
+ const llvm::Type *BP = Int8PtrTy;
+ if (Loc->getType() != BP)
+ Loc = Builder.CreateBitCast(Loc, BP, "tmp");
+
+ // If the initializer is all or mostly zeros, codegen with memset then do
+ // a few stores afterward.
+ if (shouldUseMemSetPlusStoresToInitialize(Init,
CGM.getTargetData().getTypeAllocSize(Init->getType()))) {
- Builder.CreateMemSet(Loc, Builder.getInt8(0), SizeVal,
- Align.getQuantity(), false);
- if (!Init->isNullValue()) {
- Loc = Builder.CreateBitCast(Loc, Init->getType()->getPointerTo());
- emitStoresForInitAfterMemset(Init, Loc, Builder);
- }
-
- } else {
- // Otherwise, create a temporary global with the initializer then
- // memcpy from the global to the alloca.
- std::string Name = GetStaticDeclName(*this, D, ".");
- llvm::GlobalVariable *GV =
+ Builder.CreateMemSet(Loc, llvm::ConstantInt::get(Int8Ty, 0), SizeVal,
+ alignment.getQuantity(), isVolatile);
+ if (!Init->isNullValue()) {
+ Loc = Builder.CreateBitCast(Loc, Init->getType()->getPointerTo());
+ emitStoresForInitAfterMemset(Init, Loc, isVolatile, Builder);
+ }
+ } else {
+ // Otherwise, create a temporary global with the initializer then
+ // memcpy from the global to the alloca.
+ std::string Name = GetStaticDeclName(*this, D, ".");
+ llvm::GlobalVariable *GV =
new llvm::GlobalVariable(CGM.getModule(), Init->getType(), true,
llvm::GlobalValue::InternalLinkage,
Init, Name, 0, false, 0);
- GV->setAlignment(Align.getQuantity());
+ GV->setAlignment(alignment.getQuantity());
- llvm::Value *SrcPtr = GV;
- if (SrcPtr->getType() != BP)
- SrcPtr = Builder.CreateBitCast(SrcPtr, BP, "tmp");
+ llvm::Value *SrcPtr = GV;
+ if (SrcPtr->getType() != BP)
+ SrcPtr = Builder.CreateBitCast(SrcPtr, BP, "tmp");
- Builder.CreateMemCpy(Loc, SrcPtr, SizeVal, Align.getQuantity(), false);
- }
- } else if (Ty->isReferenceType()) {
- RValue RV = EmitReferenceBindingToExpr(Init, &D);
- if (isByRef)
- Loc = Builder.CreateStructGEP(DeclPtr, getByRefValueLLVMField(&D),
- D.getNameAsString());
- EmitStoreOfScalar(RV.getScalarVal(), Loc, false, Alignment, Ty);
- } else if (!hasAggregateLLVMType(Init->getType())) {
- llvm::Value *V = EmitScalarExpr(Init);
- if (isByRef) {
- // When RHS has side-effect, must go through "forwarding' field
- // to get to the address of the __block variable descriptor.
- if (Init->HasSideEffects(getContext()))
- Loc = BuildBlockByrefAddress(DeclPtr, &D);
- else
- Loc = Builder.CreateStructGEP(DeclPtr, getByRefValueLLVMField(&D),
- D.getNameAsString());
- }
- EmitStoreOfScalar(V, Loc, isVolatile, Alignment, Ty);
- } else if (Init->getType()->isAnyComplexType()) {
- if (isByRef)
- Loc = Builder.CreateStructGEP(DeclPtr, getByRefValueLLVMField(&D),
- D.getNameAsString());
- EmitComplexExprIntoAddr(Init, Loc, isVolatile);
- } else {
- if (isByRef)
- Loc = Builder.CreateStructGEP(DeclPtr, getByRefValueLLVMField(&D),
- D.getNameAsString());
- EmitAggExpr(Init, AggValueSlot::forAddr(Loc, isVolatile, true, false));
+ Builder.CreateMemCpy(Loc, SrcPtr, SizeVal, alignment.getQuantity(),
+ isVolatile);
}
+ } else if (type->isReferenceType()) {
+ RValue RV = EmitReferenceBindingToExpr(Init, &D);
+ if (capturedByInit) Loc = BuildBlockByrefAddress(Loc, &D);
+ EmitStoreOfScalar(RV.getScalarVal(), Loc, false, alignment.getQuantity(),
+ type);
+ } else if (!hasAggregateLLVMType(type)) {
+ llvm::Value *V = EmitScalarExpr(Init);
+ if (capturedByInit) Loc = BuildBlockByrefAddress(Loc, &D);
+ EmitStoreOfScalar(V, Loc, isVolatile, alignment.getQuantity(), type);
+ } else if (type->isAnyComplexType()) {
+ ComplexPairTy complex = EmitComplexExpr(Init);
+ if (capturedByInit) Loc = BuildBlockByrefAddress(Loc, &D);
+ StoreComplexToAddr(complex, Loc, isVolatile);
+ } else {
+ // TODO: how can we delay here if D is captured by its initializer?
+ EmitAggExpr(Init, AggValueSlot::forAddr(Loc, isVolatile, true, false));
}
+}
- // Handle CXX destruction of variables.
- QualType DtorTy(Ty);
- while (const ArrayType *Array = getContext().getAsArrayType(DtorTy))
- DtorTy = getContext().getBaseElementType(Array);
- if (const RecordType *RT = DtorTy->getAs<RecordType>())
- if (CXXRecordDecl *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
+void CodeGenFunction::EmitAutoVarCleanups(const AutoVarEmission &emission) {
+ assert(emission.Variable && "emission was not valid!");
+
+ // If this was emitted as a global constant, we're done.
+ if (emission.wasEmittedAsGlobal()) return;
+
+ const VarDecl &D = *emission.Variable;
+
+ // Handle C++ destruction of variables.
+ if (getLangOptions().CPlusPlus) {
+ QualType type = D.getType();
+ QualType baseType = getContext().getBaseElementType(type);
+ if (const RecordType *RT = baseType->getAs<RecordType>()) {
+ CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(RT->getDecl());
if (!ClassDecl->hasTrivialDestructor()) {
// Note: We suppress the destructor call when the corresponding NRVO
// flag has been set.
- llvm::Value *Loc = DeclPtr;
- if (isByRef)
- Loc = Builder.CreateStructGEP(DeclPtr, getByRefValueLLVMField(&D),
- D.getNameAsString());
+
+ // Note that for __block variables, we want to destroy the
+ // original stack object, not the possible forwarded object.
+ llvm::Value *Loc = emission.getObjectAddress(*this);
const CXXDestructorDecl *D = ClassDecl->getDestructor();
assert(D && "EmitLocalBlockVarDecl - destructor is nul");
- if (const ConstantArrayType *Array =
- getContext().getAsConstantArrayType(Ty)) {
+ if (type != baseType) {
+ const ConstantArrayType *Array =
+ getContext().getAsConstantArrayType(type);
+ assert(Array && "types changed without array?");
EHStack.pushCleanup<CallArrayDtor>(NormalAndEHCleanup,
D, Array, Loc);
} else {
EHStack.pushCleanup<CallVarDtor>(NormalAndEHCleanup,
- D, NRVOFlag, Loc);
+ D, emission.NRVOFlag, Loc);
}
}
+ }
}
- // Handle the cleanup attribute
+ // Handle the cleanup attribute.
if (const CleanupAttr *CA = D.getAttr<CleanupAttr>()) {
const FunctionDecl *FD = CA->getFunctionDecl();
- llvm::Constant* F = CGM.GetAddrOfFunction(FD);
+ llvm::Constant *F = CGM.GetAddrOfFunction(FD);
assert(F && "Could not find function!");
const CGFunctionInfo &Info = CGM.getTypes().getFunctionInfo(FD);
- EHStack.pushCleanup<CallCleanupFunction>(NormalAndEHCleanup,
- F, &Info, DeclPtr, &D);
+ EHStack.pushCleanup<CallCleanupFunction>(NormalAndEHCleanup, F, &Info, &D);
}
- // If this is a block variable, clean it up.
- if (needsDispose && CGM.getLangOptions().getGCMode() != LangOptions::GCOnly)
- EHStack.pushCleanup<CallBlockRelease>(NormalAndEHCleanup, DeclPtr);
+ // If this is a block variable, call _Block_object_destroy
+ // (on the unforwarded address).
+ if (emission.IsByRef &&
+ CGM.getLangOptions().getGCMode() != LangOptions::GCOnly)
+ EHStack.pushCleanup<CallBlockRelease>(NormalAndEHCleanup, emission.Address);
}
/// Emit an alloca (or GlobalValue depending on target)
@@ -933,6 +1004,24 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, llvm::Value *Arg) {
// FIXME: Why isn't ImplicitParamDecl a ParmVarDecl?
assert((isa<ParmVarDecl>(D) || isa<ImplicitParamDecl>(D)) &&
"Invalid argument to EmitParmDecl");
+
+ Arg->setName(D.getName());
+
+ // Use better IR generation for certain implicit parameters.
+ if (isa<ImplicitParamDecl>(D)) {
+ // The only implicit argument a block has is its literal.
+ if (BlockInfo) {
+ LocalDeclMap[&D] = Arg;
+
+ if (CGDebugInfo *DI = getDebugInfo()) {
+ DI->setLocation(D.getLocation());
+ DI->EmitDeclareOfBlockLiteralArgVariable(*BlockInfo, Arg, Builder);
+ }
+
+ return;
+ }
+ }
+
QualType Ty = D.getType();
llvm::Value *DeclPtr;
@@ -949,7 +1038,6 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, llvm::Value *Arg) {
getContext().getDeclAlign(&D).getQuantity(), Ty,
CGM.getTBAAInfo(Ty));
}
- Arg->setName(D.getName());
llvm::Value *&DMEntry = LocalDeclMap[&D];
assert(DMEntry == 0 && "Decl already exists in localdeclmap!");
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGException.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGException.cpp
index 6181965..4bce081 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGException.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGException.cpp
@@ -1086,14 +1086,14 @@ static void BeginCatch(CodeGenFunction &CGF, const CXXCatchStmt *S) {
// 3. Enter __cxa_end_catch cleanup
// 4. Enter dtor cleanup
//
- // We do this by initializing the exception variable with a
- // "special initializer", InitCatchParam. Delegation sequence:
+ // We do this by using a slightly abnormal initialization process.
+ // Delegation sequence:
// - ExitCXXTryStmt opens a RunCleanupsScope
- // - EmitLocalBlockVarDecl creates the variable and debug info
+ // - EmitAutoVarAlloca creates the variable and debug info
// - InitCatchParam initializes the variable from the exception
- // - CallBeginCatch calls __cxa_begin_catch
- // - CallBeginCatch enters the __cxa_end_catch cleanup
- // - EmitLocalBlockVarDecl enters the variable destructor cleanup
+ // - CallBeginCatch calls __cxa_begin_catch
+ // - CallBeginCatch enters the __cxa_end_catch cleanup
+ // - EmitAutoVarCleanups enters the variable destructor cleanup
// - EmitCXXTryStmt emits the code for the catch body
// - EmitCXXTryStmt close the RunCleanupsScope
@@ -1105,7 +1105,9 @@ static void BeginCatch(CodeGenFunction &CGF, const CXXCatchStmt *S) {
}
// Emit the local.
- CGF.EmitAutoVarDecl(*CatchParam, &InitCatchParam);
+ CodeGenFunction::AutoVarEmission var = CGF.EmitAutoVarAlloca(*CatchParam);
+ InitCatchParam(CGF, *CatchParam, var.getObjectAddress(CGF));
+ CGF.EmitAutoVarCleanups(var);
}
namespace {
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp
index 1b7e7a0..2abaadf 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp
@@ -260,6 +260,10 @@ EmitExprForReferenceBinding(CodeGenFunction &CGF, const Expr *E,
}
}
+ if (const OpaqueValueExpr *opaque = dyn_cast<OpaqueValueExpr>(E))
+ if (opaque->getType()->isRecordType())
+ return CGF.EmitOpaqueValueLValue(opaque).getAddress();
+
// Nothing changed.
break;
}
@@ -1606,39 +1610,67 @@ LValue CodeGenFunction::EmitLValueForAnonRecordField(llvm::Value *BaseValue,
}
}
-LValue CodeGenFunction::EmitLValueForField(llvm::Value *BaseValue,
- const FieldDecl *Field,
- unsigned CVRQualifiers) {
- if (Field->isBitField())
- return EmitLValueForBitfield(BaseValue, Field, CVRQualifiers);
+LValue CodeGenFunction::EmitLValueForField(llvm::Value *baseAddr,
+ const FieldDecl *field,
+ unsigned cvr) {
+ if (field->isBitField())
+ return EmitLValueForBitfield(baseAddr, field, cvr);
- const CGRecordLayout &RL =
- CGM.getTypes().getCGRecordLayout(Field->getParent());
- unsigned idx = RL.getLLVMFieldNo(Field);
- llvm::Value *V = Builder.CreateStructGEP(BaseValue, idx, "tmp");
+ const RecordDecl *rec = field->getParent();
+ QualType type = field->getType();
+
+ bool mayAlias = rec->hasAttr<MayAliasAttr>();
- // Match union field type.
- if (Field->getParent()->isUnion()) {
- const llvm::Type *FieldTy =
- CGM.getTypes().ConvertTypeForMem(Field->getType());
- const llvm::PointerType *BaseTy =
- cast<llvm::PointerType>(BaseValue->getType());
- unsigned AS = BaseTy->getAddressSpace();
- V = Builder.CreateBitCast(V,
- llvm::PointerType::get(FieldTy, AS),
- "tmp");
+ llvm::Value *addr;
+ if (rec->isUnion()) {
+ // For unions, we just cast to the appropriate type.
+ assert(!type->isReferenceType() && "union has reference member");
+
+ const llvm::Type *llvmType = CGM.getTypes().ConvertTypeForMem(type);
+ unsigned AS =
+ cast<llvm::PointerType>(baseAddr->getType())->getAddressSpace();
+ addr = Builder.CreateBitCast(baseAddr, llvmType->getPointerTo(AS),
+ field->getName());
+ } else {
+ // For structs, we GEP to the field that the record layout suggests.
+ unsigned idx = CGM.getTypes().getCGRecordLayout(rec).getLLVMFieldNo(field);
+ addr = Builder.CreateStructGEP(baseAddr, idx, field->getName());
+
+ // If this is a reference field, load the reference right now.
+ if (const ReferenceType *refType = type->getAs<ReferenceType>()) {
+ llvm::LoadInst *load = Builder.CreateLoad(addr, "ref");
+ if (cvr & Qualifiers::Volatile) load->setVolatile(true);
+
+ if (CGM.shouldUseTBAA()) {
+ llvm::MDNode *tbaa;
+ if (mayAlias)
+ tbaa = CGM.getTBAAInfo(getContext().CharTy);
+ else
+ tbaa = CGM.getTBAAInfo(type);
+ CGM.DecorateInstruction(load, tbaa);
+ }
+
+ addr = load;
+ mayAlias = false;
+ type = refType->getPointeeType();
+ cvr = 0; // qualifiers don't recursively apply to referencee
+ }
}
- if (Field->getType()->isReferenceType())
- V = Builder.CreateLoad(V, "tmp");
- unsigned Alignment = getContext().getDeclAlign(Field).getQuantity();
- LValue LV = MakeAddrLValue(V, Field->getType(), Alignment);
- LV.getQuals().addCVRQualifiers(CVRQualifiers);
+ unsigned alignment = getContext().getDeclAlign(field).getQuantity();
+ LValue LV = MakeAddrLValue(addr, type, alignment);
+ LV.getQuals().addCVRQualifiers(cvr);
// __weak attribute on a field is ignored.
if (LV.getQuals().getObjCGCAttr() == Qualifiers::Weak)
LV.getQuals().removeObjCGCAttr();
-
+
+ // Fields of may_alias structs act like 'char' for TBAA purposes.
+ // FIXME: this should get propagated down through anonymous structs
+ // and unions.
+ if (mayAlias && LV.getTBAAInfo())
+ LV.setTBAAInfo(CGM.getTBAAInfo(getContext().CharTy));
+
return LV;
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGObjC.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGObjC.cpp
index 08c458b..5d34907 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGObjC.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGObjC.cpp
@@ -663,6 +663,11 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
return;
}
+ // The local variable comes into scope immediately.
+ AutoVarEmission variable = AutoVarEmission::invalid();
+ if (const DeclStmt *SD = dyn_cast<DeclStmt>(S.getElement()))
+ variable = EmitAutoVarAlloca(*cast<VarDecl>(SD->getSingleDecl()));
+
CGDebugInfo *DI = getDebugInfo();
if (DI) {
DI->setLocation(S.getSourceRange().getBegin());
@@ -799,22 +804,23 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
// Initialize the element variable.
RunCleanupsScope elementVariableScope(*this);
- bool elementIsDecl;
+ bool elementIsVariable;
LValue elementLValue;
QualType elementType;
if (const DeclStmt *SD = dyn_cast<DeclStmt>(S.getElement())) {
- EmitStmt(SD);
- const VarDecl* D = cast<VarDecl>(SD->getSingleDecl());
+ // Initialize the variable, in case it's a __block variable or something.
+ EmitAutoVarInit(variable);
+ const VarDecl* D = cast<VarDecl>(SD->getSingleDecl());
DeclRefExpr tempDRE(const_cast<VarDecl*>(D), D->getType(),
VK_LValue, SourceLocation());
elementLValue = EmitLValue(&tempDRE);
elementType = D->getType();
- elementIsDecl = true;
+ elementIsVariable = true;
} else {
elementLValue = LValue(); // suppress warning
elementType = cast<Expr>(S.getElement())->getType();
- elementIsDecl = false;
+ elementIsVariable = false;
}
const llvm::Type *convertedElementType = ConvertType(elementType);
@@ -837,11 +843,16 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
// Make sure we have an l-value. Yes, this gets evaluated every
// time through the loop.
- if (!elementIsDecl)
+ if (!elementIsVariable)
elementLValue = EmitLValue(cast<Expr>(S.getElement()));
EmitStoreThroughLValue(RValue::get(CurrentItem), elementLValue, elementType);
+ // If we do have an element variable, this assignment is the end of
+ // its initialization.
+ if (elementIsVariable)
+ EmitAutoVarCleanups(variable);
+
// Perform the loop body, setting up break and continue labels.
BreakContinueStack.push_back(BreakContinue(LoopEnd, AfterBody));
{
@@ -891,7 +902,7 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
// No more elements.
EmitBlock(EmptyBB);
- if (!elementIsDecl) {
+ if (!elementIsVariable) {
// If the element was not a declaration, set it to be null.
llvm::Value *null = llvm::Constant::getNullValue(convertedElementType);
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGObjCGNU.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCGNU.cpp
index d481e77..5f19dc6 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGObjCGNU.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCGNU.cpp
@@ -949,7 +949,12 @@ llvm::Constant *CGObjCGNU::GenerateClassStructure(
Elements.push_back(MakeConstantString(Name, ".class_name"));
Elements.push_back(Zero);
Elements.push_back(llvm::ConstantInt::get(LongTy, info));
- Elements.push_back(InstanceSize);
+ if (isMeta) {
+ llvm::TargetData td(&TheModule);
+ Elements.push_back(llvm::ConstantInt::get(LongTy,
+ td.getTypeSizeInBits(ClassTy)/8));
+ } else
+ Elements.push_back(InstanceSize);
Elements.push_back(IVars);
Elements.push_back(Methods);
Elements.push_back(NULLPtr);
@@ -1831,9 +1836,9 @@ llvm::Function *CGObjCGNU::GetPropertyGetFunction() {
std::vector<const llvm::Type*> Params;
Params.push_back(IdTy);
Params.push_back(SelectorTy);
- Params.push_back(IntTy);
+ Params.push_back(SizeTy);
Params.push_back(BoolTy);
- // void objc_getProperty (id, SEL, int, bool)
+ // void objc_getProperty (id, SEL, ptrdiff_t, bool)
const llvm::FunctionType *FTy =
llvm::FunctionType::get(IdTy, Params, false);
return cast<llvm::Function>(CGM.CreateRuntimeFunction(FTy,
@@ -1844,11 +1849,11 @@ llvm::Function *CGObjCGNU::GetPropertySetFunction() {
std::vector<const llvm::Type*> Params;
Params.push_back(IdTy);
Params.push_back(SelectorTy);
- Params.push_back(IntTy);
+ Params.push_back(SizeTy);
Params.push_back(IdTy);
Params.push_back(BoolTy);
Params.push_back(BoolTy);
- // void objc_setProperty (id, SEL, int, id, bool, bool)
+ // void objc_setProperty (id, SEL, ptrdiff_t, id, bool, bool)
const llvm::FunctionType *FTy =
llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Params, false);
return cast<llvm::Function>(CGM.CreateRuntimeFunction(FTy,
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGObjCMac.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCMac.cpp
index 7c679b9..8dbd85f 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGObjCMac.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCMac.cpp
@@ -46,6 +46,15 @@ using namespace CodeGen;
// don't belong in CGObjCRuntime either so we will live with it for
// now.
+static void EmitNullReturnInitialization(CodeGenFunction &CGF,
+ ReturnValueSlot &returnSlot,
+ QualType resultType) {
+ // Force the return slot to exist.
+ if (!returnSlot.getValue())
+ returnSlot = ReturnValueSlot(CGF.CreateMemTemp(resultType), false);
+ CGF.EmitNullInitialization(returnSlot.getValue(), resultType);
+}
+
static uint64_t LookupFieldBitOffset(CodeGen::CodeGenModule &CGM,
const ObjCInterfaceDecl *OID,
const ObjCImplementationDecl *ID,
@@ -1639,6 +1648,7 @@ CGObjCCommonMac::EmitLegacyMessageSend(CodeGen::CodeGenFunction &CGF,
llvm::Constant *Fn = NULL;
if (CGM.ReturnTypeUsesSRet(FnInfo)) {
+ EmitNullReturnInitialization(CGF, Return, ResultType);
Fn = (ObjCABI == 2) ? ObjCTypes.getSendStretFn2(IsSuper)
: ObjCTypes.getSendStretFn(IsSuper);
} else if (CGM.ReturnTypeUsesFPRet(ResultType)) {
@@ -5629,6 +5639,7 @@ CodeGen::RValue CGObjCNonFragileABIMac::EmitMessageSend(
llvm::Constant *Fn = 0;
std::string Name("\01l_");
if (CGM.ReturnTypeUsesSRet(FnInfo)) {
+ EmitNullReturnInitialization(CGF, Return, ResultType);
if (IsSuper) {
Fn = ObjCTypes.getMessageSendSuper2StretFixupFn();
Name += "objc_msgSendSuper2_stret_fixup";
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
index 4b19aef..ceae66f 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
@@ -207,8 +207,9 @@ CGBitFieldInfo CGBitFieldInfo::MakeInfo(CodeGenTypes &Types,
uint64_t ContainingTypeSizeInBits,
unsigned ContainingTypeAlign) {
const llvm::Type *Ty = Types.ConvertTypeForMemRecursive(FD->getType());
- uint64_t TypeSizeInBytes = Types.getTargetData().getTypeAllocSize(Ty);
- uint64_t TypeSizeInBits = TypeSizeInBytes * 8;
+ CharUnits TypeSizeInBytes =
+ CharUnits::fromQuantity(Types.getTargetData().getTypeAllocSize(Ty));
+ uint64_t TypeSizeInBits = Types.getContext().toBits(TypeSizeInBytes);
bool IsSigned = FD->getType()->isSignedIntegerType();
@@ -249,7 +250,7 @@ CGBitFieldInfo CGBitFieldInfo::MakeInfo(CodeGenTypes &Types,
uint64_t AccessStart = FieldOffset - (FieldOffset % AccessWidth);
// Adjust initial access size to fit within record.
- while (AccessWidth > 8 &&
+ while (AccessWidth > Types.getTarget().getCharWidth() &&
AccessStart + AccessWidth > ContainingTypeSizeInBits) {
AccessWidth >>= 1;
AccessStart = FieldOffset - (FieldOffset % AccessWidth);
@@ -262,7 +263,8 @@ CGBitFieldInfo CGBitFieldInfo::MakeInfo(CodeGenTypes &Types,
if (AccessStart + AccessWidth > ContainingTypeSizeInBits) {
// If so, reduce access size to the next smaller power-of-two and retry.
AccessWidth >>= 1;
- assert(AccessWidth >= 8 && "Cannot access under byte size!");
+ assert(AccessWidth >= Types.getTarget().getCharWidth()
+ && "Cannot access under byte size!");
continue;
}
@@ -329,7 +331,7 @@ void CGRecordLayoutBuilder::LayoutBitField(const FieldDecl *D,
if (fieldSize == 0)
return;
- uint64_t nextFieldOffsetInBits = NextFieldOffset.getQuantity() * 8;
+ uint64_t nextFieldOffsetInBits = Types.getContext().toBits(NextFieldOffset);
unsigned numBytesToAppend;
if (fieldOffset < nextFieldOffsetInBits) {
@@ -378,8 +380,10 @@ bool CGRecordLayoutBuilder::LayoutField(const FieldDecl *D,
CheckZeroInitializable(D->getType());
- assert(fieldOffset % 8 == 0 && "FieldOffset is not on a byte boundary!");
- CharUnits fieldOffsetInBytes = CharUnits::fromQuantity(fieldOffset / 8);
+ assert(fieldOffset % Types.getTarget().getCharWidth() == 0
+ && "field offset is not on a byte boundary!");
+ CharUnits fieldOffsetInBytes
+ = Types.getContext().toCharUnitsFromBits(fieldOffset);
const llvm::Type *Ty = Types.ConvertTypeForMemRecursive(D->getType());
CharUnits typeAlignment = getTypeAlignment(Ty);
@@ -396,7 +400,7 @@ bool CGRecordLayoutBuilder::LayoutField(const FieldDecl *D,
const RecordDecl *RD = cast<RecordDecl>(RT->getDecl());
if (const MaxFieldAlignmentAttr *MFAA =
RD->getAttr<MaxFieldAlignmentAttr>()) {
- if (MFAA->getAlignment() != typeAlignment.getQuantity() * 8)
+ if (MFAA->getAlignment() != Types.getContext().toBits(typeAlignment))
return false;
}
}
@@ -728,7 +732,8 @@ bool CGRecordLayoutBuilder::LayoutFields(const RecordDecl *D) {
void CGRecordLayoutBuilder::AppendTailPadding(uint64_t RecordSize) {
assert(RecordSize % 8 == 0 && "Invalid record size!");
- CharUnits RecordSizeInBytes = CharUnits::fromQuantity(RecordSize / 8);
+ CharUnits RecordSizeInBytes =
+ Types.getContext().toCharUnitsFromBits(RecordSize);
assert(NextFieldOffset <= RecordSizeInBytes && "Size mismatch!");
CharUnits AlignedNextFieldOffset =
@@ -920,7 +925,8 @@ CGRecordLayout *CodeGenTypes::ComputeRecordLayout(const RecordDecl *D) {
// Verify that every component access is within the structure.
uint64_t FieldOffset = SL->getElementOffsetInBits(AI.FieldIndex);
- uint64_t AccessBitOffset = FieldOffset + AI.FieldByteOffset * 8;
+ uint64_t AccessBitOffset = FieldOffset +
+ getContext().toBits(CharUnits::fromQuantity(AI.FieldByteOffset));
assert(AccessBitOffset + AI.AccessWidth <= TypeSizeInBits &&
"Invalid bit-field access (out of range)!");
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.h b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.h
index 67ef414..be646fb 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.h
@@ -1555,7 +1555,55 @@ public:
/// EmitAutoVarDecl - Emit an auto variable declaration.
///
/// This function can be called with a null (unreachable) insert point.
- void EmitAutoVarDecl(const VarDecl &D, SpecialInitFn *SpecialInit = 0);
+ void EmitAutoVarDecl(const VarDecl &D);
+
+ class AutoVarEmission {
+ friend class CodeGenFunction;
+
+ const VarDecl *Variable;
+
+ /// The alignment of the variable.
+ CharUnits Alignment;
+
+ /// The address of the alloca. Null if the variable was emitted
+ /// as a global constant.
+ llvm::Value *Address;
+
+ llvm::Value *NRVOFlag;
+
+ /// True if the variable is a __block variable.
+ bool IsByRef;
+
+ /// True if the variable is of aggregate type and has a constant
+ /// initializer.
+ bool IsConstantAggregate;
+
+ struct Invalid {};
+ AutoVarEmission(Invalid) : Variable(0) {}
+
+ AutoVarEmission(const VarDecl &variable)
+ : Variable(&variable), Address(0), NRVOFlag(0),
+ IsByRef(false), IsConstantAggregate(false) {}
+
+ bool wasEmittedAsGlobal() const { return Address == 0; }
+
+ public:
+ static AutoVarEmission invalid() { return AutoVarEmission(Invalid()); }
+
+ /// Returns the address of the object within this declaration.
+ /// Note that this does not chase the forwarding pointer for
+ /// __block decls.
+ llvm::Value *getObjectAddress(CodeGenFunction &CGF) const {
+ if (!IsByRef) return Address;
+
+ return CGF.Builder.CreateStructGEP(Address,
+ CGF.getByRefValueLLVMField(Variable),
+ Variable->getNameAsString());
+ }
+ };
+ AutoVarEmission EmitAutoVarAlloca(const VarDecl &var);
+ void EmitAutoVarInit(const AutoVarEmission &emission);
+ void EmitAutoVarCleanups(const AutoVarEmission &emission);
void EmitStaticVarDecl(const VarDecl &D,
llvm::GlobalValue::LinkageTypes Linkage);
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp
index 9e5d7cf..a8453c3 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp
@@ -97,6 +97,8 @@ CodeGenModule::CodeGenModule(ASTContext &C, const CodeGenOptions &CGO,
Int32Ty = llvm::Type::getInt32Ty(LLVMContext);
Int64Ty = llvm::Type::getInt64Ty(LLVMContext);
PointerWidthInBits = C.Target.getPointerWidth(0);
+ PointerAlignInBytes =
+ C.toCharUnitsFromBits(C.Target.getPointerAlign(0)).getQuantity();
IntTy = llvm::IntegerType::get(LLVMContext, C.Target.getIntWidth());
IntPtrTy = llvm::IntegerType::get(LLVMContext, PointerWidthInBits);
Int8PtrTy = Int8Ty->getPointerTo(0);
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.h b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.h
index b6bd37c..73e6ece 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.h
@@ -120,8 +120,11 @@ namespace CodeGen {
const llvm::PointerType *Int8PtrPtrTy;
};
- /// The width of an address-zero pointer.
+ /// The width of a pointer into the generic address space.
unsigned char PointerWidthInBits;
+
+ /// The alignment of a pointer into the generic address space.
+ unsigned char PointerAlignInBytes;
};
/// CodeGenModule - This class organizes the cross-function state that is used
@@ -292,6 +295,8 @@ public:
const TargetCodeGenInfo &getTargetCodeGenInfo();
bool isTargetDarwin() const;
+ bool shouldUseTBAA() const { return TBAA != 0; }
+
llvm::MDNode *getTBAAInfo(QualType QTy);
static void DecorateInstruction(llvm::Instruction *Inst,
@@ -386,8 +391,8 @@ public:
unsigned Align,
const VarDecl *variable);
- /// getGlobalUniqueCount - Fetches the global unique block count.
- int getGlobalUniqueCount() { return ++Block.GlobalUniqueCount; }
+ /// getUniqueBlockCount - Fetches the global unique block count.
+ int getUniqueBlockCount() { return ++Block.GlobalUniqueCount; }
/// getBlockDescriptorType - Fetches the type of a generic block
/// descriptor.
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.cpp b/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.cpp
index d74b3f3..2ffc840 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.cpp
@@ -2105,8 +2105,15 @@ ABIArgInfo WinX86_64ABIInfo::classify(QualType Ty) const {
RT->getDecl()->hasFlexibleArrayMember())
return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
- // FIXME: mingw64-gcc emits 128-bit struct as i128
- if (Size <= 128 &&
+ // FIXME: mingw-w64-gcc emits 128-bit struct as i128
+ if (Size == 128 &&
+ getContext().Target.getTriple().getOS() == llvm::Triple::MinGW32)
+ return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(),
+ Size));
+
+ // MS x64 ABI requirement: "Any argument that doesn't fit in 8 bytes, or is
+ // not 1, 2, 4, or 8 bytes, must be passed by reference."
+ if (Size <= 64 &&
(Size & (Size - 1)) == 0)
return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(),
Size));
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp
index e4051a1..e305683 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp
@@ -198,7 +198,8 @@ void ToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &Args,
switch (Type) {
case ToolChain::CST_Libcxx:
- CmdArgs.push_back("-cxx-system-include");
+ CmdArgs.push_back("-nostdinc++");
+ CmdArgs.push_back("-cxx-isystem");
CmdArgs.push_back("/usr/include/c++/v1");
break;
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp
index d94de20..422c572 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp
@@ -46,7 +46,7 @@ Darwin::Darwin(const HostInfo &Host, const llvm::Triple& Triple)
// Compute the initial Darwin version based on the host.
bool HadExtra;
std::string OSName = Triple.getOSName();
- if (!Driver::GetReleaseVersion(&OSName[6],
+ if (!Driver::GetReleaseVersion(&OSName.c_str()[6],
DarwinVersion[0], DarwinVersion[1],
DarwinVersion[2], HadExtra))
getDriver().Diag(clang::diag::err_drv_invalid_darwin_version) << OSName;
@@ -1271,6 +1271,7 @@ Tool &AuroraUX::SelectTool(const Compilation &C, const JobAction &JA) const {
/// Linux toolchain (very bare-bones at the moment).
enum LinuxDistro {
+ ArchLinux,
DebianLenny,
DebianSqueeze,
Exherbo,
@@ -1367,6 +1368,9 @@ static LinuxDistro DetectLinuxDistro(llvm::Triple::ArchType Arch) {
if (!llvm::sys::fs::exists("/etc/exherbo-release", Exists) && Exists)
return Exherbo;
+ if (!llvm::sys::fs::exists("/etc/arch-release", Exists) && Exists)
+ return ArchLinux;
+
return UnknownDistro;
}
@@ -1436,8 +1440,9 @@ Linux::Linux(const HostInfo &Host, const llvm::Triple &Triple)
GccTriple = "i586-suse-linux";
}
- const char* GccVersions[] = {"4.5.1", "4.5", "4.4.5", "4.4.4", "4.4.3", "4.4",
- "4.3.4", "4.3.3", "4.3.2"};
+ const char* GccVersions[] = {"4.5.2", "4.5.1", "4.5", "4.4.5", "4.4.4",
+ "4.4.3", "4.4", "4.3.4", "4.3.3", "4.3.2",
+ "4.3"};
std::string Base = "";
for (unsigned i = 0; i < sizeof(GccVersions)/sizeof(char*); ++i) {
std::string Suffix = GccTriple + "/" + GccVersions[i];
@@ -1498,6 +1503,9 @@ Linux::Linux(const HostInfo &Host, const llvm::Triple &Triple)
Distro == UbuntuKarmic)
ExtraOpts.push_back("--build-id");
+ if (Distro == ArchLinux)
+ Lib = "lib";
+
Paths.push_back(Base + Suffix);
if (HasMultilib(Arch, Distro)) {
if (IsOpenSuse(Distro) && Is32Bits)
diff --git a/contrib/llvm/tools/clang/lib/Driver/Tools.cpp b/contrib/llvm/tools/clang/lib/Driver/Tools.cpp
index 0697d54..a2c95fc 100644
--- a/contrib/llvm/tools/clang/lib/Driver/Tools.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/Tools.cpp
@@ -1552,10 +1552,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-fobjc-default-synthesize-properties");
}
- // -fobjc-exceptions is default.
- if (!Args.hasFlag(options::OPT_fobjc_exceptions,
- options::OPT_fno_objc_exceptions))
- CmdArgs.push_back("-fno-objc-exceptions");
+ // -fno-objc-exceptions is default.
+ if (IsRewriter || Args.hasFlag(options::OPT_fobjc_exceptions,
+ options::OPT_fno_objc_exceptions))
+ CmdArgs.push_back("-fobjc-exceptions");
}
if (!Args.hasFlag(options::OPT_fassume_sane_operator_new,
@@ -3091,7 +3091,7 @@ void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-lgcc");
if (Args.hasArg(options::OPT_pthread))
- CmdArgs.push_back("-pthread");
+ CmdArgs.push_back("-lpthread");
if (!Args.hasArg(options::OPT_shared))
CmdArgs.push_back("-lc");
CmdArgs.push_back("-lgcc");
diff --git a/contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp b/contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp
index 4a5a51d..a7942e6 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp
@@ -389,7 +389,8 @@ public:
virtual bool ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers,
llvm::StringRef OriginalFileName,
- std::string &SuggestedPredefines) {
+ std::string &SuggestedPredefines,
+ FileManager &FileMgr) {
Predefines = Buffers[0].Data;
for (unsigned I = 1, N = Buffers.size(); I != N; ++I) {
Predefines += Buffers[I].Data;
diff --git a/contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp b/contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp
index beb5ad2..4b44c48 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp
@@ -78,6 +78,8 @@ static void AnalyzerOptsToArgs(const AnalyzerOptions &Opts,
std::vector<std::string> &Res) {
for (unsigned i = 0, e = Opts.AnalysisList.size(); i != e; ++i)
Res.push_back(getAnalysisName(Opts.AnalysisList[i]));
+ if (Opts.ShowCheckerHelp)
+ Res.push_back("-analyzer-checker-help");
if (Opts.AnalysisStoreOpt != BasicStoreModel) {
Res.push_back("-analyzer-store");
Res.push_back(getAnalysisStoreName(Opts.AnalysisStoreOpt));
@@ -114,8 +116,6 @@ static void AnalyzerOptsToArgs(const AnalyzerOptions &Opts,
Res.push_back("-analyzer-viz-egraph-ubigraph");
if (Opts.EnableExperimentalChecks)
Res.push_back("-analyzer-experimental-checks");
- if (Opts.EnableExperimentalInternalChecks)
- Res.push_back("-analyzer-experimental-internal-checks");
if (Opts.BufferOverflows)
Res.push_back("-analyzer-check-buffer-overflows");
@@ -473,11 +473,6 @@ static void HeaderSearchOptsToArgs(const HeaderSearchOptions &Opts,
Res.push_back(Opts.Sysroot);
}
- for (unsigned i = 0, e = Opts.CXXSystemIncludes.size(); i != e; ++i) {
- Res.push_back("-cxx-system-include");
- Res.push_back(Opts.CXXSystemIncludes[i]);
- }
-
/// User specified include entries.
for (unsigned i = 0, e = Opts.UserEntries.size(); i != e; ++i) {
const HeaderSearchOptions::Entry &E = Opts.UserEntries[i];
@@ -490,6 +485,8 @@ static void HeaderSearchOptsToArgs(const HeaderSearchOptions &Opts,
Res.push_back("-iquote");
} else if (E.Group == frontend::System) {
Res.push_back("-isystem");
+ } else if (E.Group == frontend::CXXSystem) {
+ Res.push_back("-cxx-isystem");
} else {
assert(E.Group == frontend::Angled && "Invalid group!");
Res.push_back(E.IsFramework ? "-F" : "-I");
@@ -588,10 +585,12 @@ static void LangOptsToArgs(const LangOptions &Opts,
Res.push_back("-faltivec");
if (Opts.Exceptions)
Res.push_back("-fexceptions");
+ if (Opts.ObjCExceptions)
+ Res.push_back("-fobjc-exceptions");
+ if (Opts.CXXExceptions)
+ Res.push_back("-fcxx-exceptions");
if (Opts.SjLjExceptions)
Res.push_back("-fsjlj-exceptions");
- if (!Opts.ObjCExceptions)
- Res.push_back("-fno-objc-exceptions");
if (!Opts.RTTI)
Res.push_back("-fno-rtti");
if (Opts.MSBitfields)
@@ -864,6 +863,7 @@ static void ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
Opts.AnalysisDiagOpt = Value;
}
+ Opts.ShowCheckerHelp = Args.hasArg(OPT_analyzer_checker_help);
Opts.VisualizeEGDot = Args.hasArg(OPT_analyzer_viz_egraph_graphviz);
Opts.VisualizeEGUbi = Args.hasArg(OPT_analyzer_viz_egraph_ubigraph);
Opts.AnalyzeAll = Args.hasArg(OPT_analyzer_opt_analyze_headers);
@@ -878,8 +878,6 @@ static void ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
Opts.CFGAddImplicitDtors = Args.hasArg(OPT_analysis_CFGAddImplicitDtors);
Opts.CFGAddInitializers = Args.hasArg(OPT_analysis_CFGAddInitializers);
Opts.EnableExperimentalChecks = Args.hasArg(OPT_analyzer_experimental_checks);
- Opts.EnableExperimentalInternalChecks =
- Args.hasArg(OPT_analyzer_experimental_internal_checks);
Opts.TrimGraph = Args.hasArg(OPT_trim_egraph);
Opts.MaxNodes = Args.getLastArgIntValue(OPT_analyzer_max_nodes, 150000,Diags);
Opts.MaxLoop = Args.getLastArgIntValue(OPT_analyzer_max_loop, 4, Diags);
@@ -894,8 +892,13 @@ static void ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
const Arg *A = *it;
A->claim();
bool enable = (A->getOption().getID() == OPT_analyzer_checker);
- Opts.CheckersControlList.push_back(std::make_pair(A->getValue(Args),
- enable));
+ // We can have a list of comma separated checker names, e.g:
+ // '-analyzer-checker=cocoa,unix'
+ llvm::StringRef checkerList = A->getValue(Args);
+ llvm::SmallVector<llvm::StringRef, 4> checkers;
+ checkerList.split(checkers, ",");
+ for (unsigned i = 0, e = checkers.size(); i != e; ++i)
+ Opts.CheckersControlList.push_back(std::make_pair(checkers[i], enable));
}
}
@@ -1238,7 +1241,6 @@ std::string CompilerInvocation::GetResourcesPath(const char *Argv0,
static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args) {
using namespace cc1options;
- Opts.CXXSystemIncludes = Args.getAllArgValues(OPT_cxx_system_include);
Opts.Sysroot = Args.getLastArgValue(OPT_isysroot, "/");
Opts.Verbose = Args.hasArg(OPT_v);
Opts.UseBuiltinIncludes = !Args.hasArg(OPT_nobuiltininc);
@@ -1274,10 +1276,12 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args) {
for (arg_iterator it = Args.filtered_begin(OPT_iquote),
ie = Args.filtered_end(); it != ie; ++it)
Opts.AddPath((*it)->getValue(Args), frontend::Quoted, true, false, true);
- for (arg_iterator it = Args.filtered_begin(OPT_isystem, OPT_iwithsysroot),
- ie = Args.filtered_end(); it != ie; ++it)
- Opts.AddPath((*it)->getValue(Args), frontend::System, true, false,
- (*it)->getOption().matches(OPT_iwithsysroot));
+ for (arg_iterator it = Args.filtered_begin(OPT_cxx_isystem, OPT_isystem,
+ OPT_iwithsysroot), ie = Args.filtered_end(); it != ie; ++it)
+ Opts.AddPath((*it)->getValue(Args),
+ ((*it)->getOption().matches(OPT_cxx_isystem) ?
+ frontend::CXXSystem : frontend::System),
+ true, false, (*it)->getOption().matches(OPT_iwithsysroot));
// FIXME: Need options for the various environment variables!
}
@@ -1459,7 +1463,10 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
if (Args.hasArg(OPT_fno_threadsafe_statics))
Opts.ThreadsafeStatics = 0;
Opts.Exceptions = Args.hasArg(OPT_fexceptions);
- Opts.ObjCExceptions = !Args.hasArg(OPT_fno_objc_exceptions);
+ Opts.ObjCExceptions = Args.hasArg(OPT_fobjc_exceptions);
+ Opts.CXXExceptions = Args.hasArg(OPT_fcxx_exceptions);
+ Opts.SjLjExceptions = Args.hasArg(OPT_fsjlj_exceptions);
+
Opts.RTTI = !Args.hasArg(OPT_fno_rtti);
Opts.Blocks = Args.hasArg(OPT_fblocks);
Opts.CharIsSigned = !Args.hasArg(OPT_fno_signed_char);
@@ -1489,8 +1496,6 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Opts.CatchUndefined = Args.hasArg(OPT_fcatch_undefined_behavior);
Opts.EmitAllDecls = Args.hasArg(OPT_femit_all_decls);
Opts.PICLevel = Args.getLastArgIntValue(OPT_pic_level, 0, Diags);
- Opts.SjLjExceptions = Args.hasArg(OPT_fsjlj_exceptions);
- Opts.ObjCExceptions = !Args.hasArg(OPT_fno_objc_exceptions);
Opts.Static = Args.hasArg(OPT_static_define);
Opts.DumpRecordLayouts = Args.hasArg(OPT_fdump_record_layouts);
Opts.DumpVTableLayouts = Args.hasArg(OPT_fdump_vtable_layouts);
@@ -1661,8 +1666,11 @@ void CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
InputKind DashX = ParseFrontendArgs(Res.getFrontendOpts(), *Args, Diags);
ParseCodeGenArgs(Res.getCodeGenOpts(), *Args, DashX, Diags);
ParseHeaderSearchArgs(Res.getHeaderSearchOpts(), *Args);
- if (DashX != IK_AST && DashX != IK_LLVM_IR)
+ if (DashX != IK_AST && DashX != IK_LLVM_IR) {
ParseLangArgs(Res.getLangOpts(), *Args, DashX, Diags);
+ if (Res.getFrontendOpts().ProgramAction == frontend::RewriteObjC)
+ Res.getLangOpts().ObjCExceptions = 1;
+ }
// FIXME: ParsePreprocessorArgs uses the FileManager to read the contents of
// PCH file and find the original header name. Remove the need to do that in
// ParsePreprocessorArgs and remove the FileManager
diff --git a/contrib/llvm/tools/clang/lib/Frontend/DocumentXML.cpp b/contrib/llvm/tools/clang/lib/Frontend/DocumentXML.cpp
index b24ece5..a09db0b 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/DocumentXML.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/DocumentXML.cpp
@@ -14,6 +14,7 @@
#include "clang/Frontend/DocumentXML.h"
#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
#include "clang/AST/ASTContext.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/ADT/StringExtras.h"
@@ -218,6 +219,10 @@ void DocumentXML::addPtrAttribute(const char* pAttributeName,
addPtrAttribute(pAttributeName, pNNS->getAsNamespace());
break;
}
+ case NestedNameSpecifier::NamespaceAlias: {
+ addPtrAttribute(pAttributeName, pNNS->getAsNamespaceAlias());
+ break;
+ }
case NestedNameSpecifier::TypeSpec: {
addPtrAttribute(pAttributeName, pNNS->getAsType());
break;
diff --git a/contrib/llvm/tools/clang/lib/Frontend/InitHeaderSearch.cpp b/contrib/llvm/tools/clang/lib/Frontend/InitHeaderSearch.cpp
index 69199e2..566b96c 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/InitHeaderSearch.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/InitHeaderSearch.cpp
@@ -46,7 +46,9 @@ namespace {
/// a HeaderSearch object. InitHeaderSearch stores several search path lists
/// internally, which can be sent to a HeaderSearch object in one swoop.
class InitHeaderSearch {
- std::vector<DirectoryLookup> IncludeGroup[4];
+ std::vector<std::pair<IncludeDirGroup, DirectoryLookup> > IncludePath;
+ typedef std::vector<std::pair<IncludeDirGroup,
+ DirectoryLookup> >::const_iterator path_iterator;
HeaderSearch& Headers;
bool Verbose;
std::string IncludeSysroot;
@@ -98,7 +100,7 @@ public:
/// Realize - Merges all search path lists into one list and send it to
/// HeaderSearch.
- void Realize();
+ void Realize(const LangOptions &Lang);
};
}
@@ -135,8 +137,8 @@ void InitHeaderSearch::AddPath(const llvm::Twine &Path,
// If the directory exists, add it.
if (const DirectoryEntry *DE = FM.getDirectory(MappedPathStr)) {
- IncludeGroup[Group].push_back(DirectoryLookup(DE, Type, isUserSupplied,
- isFramework));
+ IncludePath.push_back(std::make_pair(Group, DirectoryLookup(DE, Type,
+ isUserSupplied, isFramework)));
return;
}
@@ -146,7 +148,8 @@ void InitHeaderSearch::AddPath(const llvm::Twine &Path,
if (const FileEntry *FE = FM.getFile(MappedPathStr)) {
if (const HeaderMap *HM = Headers.CreateHeaderMap(FE)) {
// It is a headermap, add it to the search path.
- IncludeGroup[Group].push_back(DirectoryLookup(HM, Type,isUserSupplied));
+ IncludePath.push_back(std::make_pair(Group, DirectoryLookup(HM, Type,
+ isUserSupplied)));
return;
}
}
@@ -183,29 +186,29 @@ void InitHeaderSearch::AddGnuCPlusPlusIncludePaths(llvm::StringRef Base,
llvm::StringRef Dir64,
const llvm::Triple &triple) {
// Add the base dir
- AddPath(Base, System, true, false, false);
+ AddPath(Base, CXXSystem, true, false, false);
// Add the multilib dirs
llvm::Triple::ArchType arch = triple.getArch();
bool is64bit = arch == llvm::Triple::ppc64 || arch == llvm::Triple::x86_64;
if (is64bit)
- AddPath(Base + "/" + ArchDir + "/" + Dir64, System, true, false, false);
+ AddPath(Base + "/" + ArchDir + "/" + Dir64, CXXSystem, true, false, false);
else
- AddPath(Base + "/" + ArchDir + "/" + Dir32, System, true, false, false);
+ AddPath(Base + "/" + ArchDir + "/" + Dir32, CXXSystem, true, false, false);
// Add the backward dir
- AddPath(Base + "/backward", System, true, false, false);
+ AddPath(Base + "/backward", CXXSystem, true, false, false);
}
void InitHeaderSearch::AddMinGWCPlusPlusIncludePaths(llvm::StringRef Base,
llvm::StringRef Arch,
llvm::StringRef Version) {
AddPath(Base + "/" + Arch + "/" + Version + "/include/c++",
- System, true, false, false);
+ CXXSystem, true, false, false);
AddPath(Base + "/" + Arch + "/" + Version + "/include/c++/" + Arch,
- System, true, false, false);
+ CXXSystem, true, false, false);
AddPath(Base + "/" + Arch + "/" + Version + "/include/c++/backward",
- System, true, false, false);
+ CXXSystem, true, false, false);
}
// FIXME: This probably should goto to some platform utils place.
@@ -576,13 +579,17 @@ AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple) {
break;
case llvm::Triple::MinGW32:
// mingw-w64-20110207
- AddPath("c:/MinGW/include/c++/4.5.3", System, true, false, false);
- AddPath("c:/MinGW/include/c++/4.5.3/x86_64-w64-mingw32", System, true, false, false);
- AddPath("c:/MinGW/include/c++/4.5.3/backward", System, true, false, false);
+ AddPath("c:/MinGW/include/c++/4.5.3", CXXSystem, true, false, false);
+ AddPath("c:/MinGW/include/c++/4.5.3/x86_64-w64-mingw32", CXXSystem, true,
+ false, false);
+ AddPath("c:/MinGW/include/c++/4.5.3/backward", CXXSystem, true, false,
+ false);
// mingw-w64-20101129
- AddPath("c:/MinGW/include/c++/4.5.2", System, true, false, false);
- AddPath("c:/MinGW/include/c++/4.5.2/x86_64-w64-mingw32", System, true, false, false);
- AddPath("c:/MinGW/include/c++/4.5.2/backward", System, true, false, false);
+ AddPath("c:/MinGW/include/c++/4.5.2", CXXSystem, true, false, false);
+ AddPath("c:/MinGW/include/c++/4.5.2/x86_64-w64-mingw32", CXXSystem, true,
+ false, false);
+ AddPath("c:/MinGW/include/c++/4.5.2/backward", CXXSystem, true, false,
+ false);
// Try gcc 4.5.0
AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.5.0");
// Try gcc 4.4.0
@@ -622,7 +629,7 @@ AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple) {
}
break;
case llvm::Triple::DragonFly:
- AddPath("/usr/include/c++/4.1", System, true, false, false);
+ AddPath("/usr/include/c++/4.1", CXXSystem, true, false, false);
break;
case llvm::Triple::Linux:
//===------------------------------------------------------------------===//
@@ -821,13 +828,8 @@ AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple) {
void InitHeaderSearch::AddDefaultSystemIncludePaths(const LangOptions &Lang,
const llvm::Triple &triple,
const HeaderSearchOptions &HSOpts) {
- if (Lang.CPlusPlus && HSOpts.UseStandardCXXIncludes) {
- if (!HSOpts.CXXSystemIncludes.empty()) {
- for (unsigned i = 0, e = HSOpts.CXXSystemIncludes.size(); i != e; ++i)
- AddPath(HSOpts.CXXSystemIncludes[i], System, true, false, false);
- } else
- AddDefaultCPlusPlusIncludePaths(triple);
- }
+ if (Lang.CPlusPlus && HSOpts.UseStandardCXXIncludes)
+ AddDefaultCPlusPlusIncludePaths(triple);
AddDefaultCIncludePaths(triple, HSOpts);
@@ -841,11 +843,11 @@ void InitHeaderSearch::AddDefaultSystemIncludePaths(const LangOptions &Lang,
/// RemoveDuplicates - If there are duplicate directory entries in the specified
/// search list, remove the later (dead) ones.
static void RemoveDuplicates(std::vector<DirectoryLookup> &SearchList,
- bool Verbose) {
+ unsigned First, bool Verbose) {
llvm::SmallPtrSet<const DirectoryEntry *, 8> SeenDirs;
llvm::SmallPtrSet<const DirectoryEntry *, 8> SeenFrameworkDirs;
llvm::SmallPtrSet<const HeaderMap *, 8> SeenHeaderMaps;
- for (unsigned i = 0; i != SearchList.size(); ++i) {
+ for (unsigned i = First; i != SearchList.size(); ++i) {
unsigned DirToRemove = i;
const DirectoryLookup &CurEntry = SearchList[i];
@@ -920,32 +922,49 @@ static void RemoveDuplicates(std::vector<DirectoryLookup> &SearchList,
}
-void InitHeaderSearch::Realize() {
+void InitHeaderSearch::Realize(const LangOptions &Lang) {
// Concatenate ANGLE+SYSTEM+AFTER chains together into SearchList.
std::vector<DirectoryLookup> SearchList;
- SearchList = IncludeGroup[Angled];
- SearchList.insert(SearchList.end(), IncludeGroup[System].begin(),
- IncludeGroup[System].end());
- SearchList.insert(SearchList.end(), IncludeGroup[After].begin(),
- IncludeGroup[After].end());
- RemoveDuplicates(SearchList, Verbose);
- RemoveDuplicates(IncludeGroup[Quoted], Verbose);
+ SearchList.reserve(IncludePath.size());
+
+ /* Quoted arguments go first. */
+ for (path_iterator it = IncludePath.begin(), ie = IncludePath.end();
+ it != ie; ++it) {
+ if (it->first == Quoted)
+ SearchList.push_back(it->second);
+ }
+ /* Deduplicate and remember index */
+ RemoveDuplicates(SearchList, 0, Verbose);
+ unsigned quoted = SearchList.size();
+
+ for (path_iterator it = IncludePath.begin(), ie = IncludePath.end();
+ it != ie; ++it) {
+ if (it->first == Angled)
+ SearchList.push_back(it->second);
+ }
- // Prepend QUOTED list on the search list.
- SearchList.insert(SearchList.begin(), IncludeGroup[Quoted].begin(),
- IncludeGroup[Quoted].end());
+ for (path_iterator it = IncludePath.begin(), ie = IncludePath.end();
+ it != ie; ++it) {
+ if (it->first == System || (Lang.CPlusPlus && it->first == CXXSystem))
+ SearchList.push_back(it->second);
+ }
+
+ for (path_iterator it = IncludePath.begin(), ie = IncludePath.end();
+ it != ie; ++it) {
+ if (it->first == After)
+ SearchList.push_back(it->second);
+ }
+ RemoveDuplicates(SearchList, quoted, Verbose);
bool DontSearchCurDir = false; // TODO: set to true if -I- is set?
- Headers.SetSearchPaths(SearchList, IncludeGroup[Quoted].size(),
- DontSearchCurDir);
+ Headers.SetSearchPaths(SearchList, quoted, DontSearchCurDir);
// If verbose, print the list of directories that will be searched.
if (Verbose) {
llvm::errs() << "#include \"...\" search starts here:\n";
- unsigned QuotedIdx = IncludeGroup[Quoted].size();
for (unsigned i = 0, e = SearchList.size(); i != e; ++i) {
- if (i == QuotedIdx)
+ if (i == quoted)
llvm::errs() << "#include <...> search starts here:\n";
const char *Name = SearchList[i].getName();
const char *Suffix;
@@ -990,5 +1009,5 @@ void clang::ApplyHeaderSearchOptions(HeaderSearch &HS,
if (HSOpts.UseStandardIncludes)
Init.AddDefaultSystemIncludePaths(Lang, Triple, HSOpts);
- Init.Realize();
+ Init.Realize(Lang);
}
diff --git a/contrib/llvm/tools/clang/lib/Frontend/InitPreprocessor.cpp b/contrib/llvm/tools/clang/lib/Frontend/InitPreprocessor.cpp
index d0111a5..91b5280 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/InitPreprocessor.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/InitPreprocessor.cpp
@@ -48,12 +48,13 @@ static void DefineBuiltinMacro(MacroBuilder &Builder, llvm::StringRef Macro,
}
}
-std::string clang::NormalizeDashIncludePath(llvm::StringRef File) {
+std::string clang::NormalizeDashIncludePath(llvm::StringRef File,
+ FileManager &FileMgr) {
// Implicit include paths should be resolved relative to the current
// working directory first, and then use the regular header search
// mechanism. The proper way to handle this is to have the
// predefines buffer located at the current working directory, but
- // it has not file entry. For now, workaround this by using an
+ // it has no file entry. For now, workaround this by using an
// absolute path if we find the file here, and otherwise letting
// header search handle it.
llvm::SmallString<128> Path(File);
@@ -61,21 +62,25 @@ std::string clang::NormalizeDashIncludePath(llvm::StringRef File) {
bool exists;
if (llvm::sys::fs::exists(Path.str(), exists) || !exists)
Path = File;
+ else if (exists)
+ FileMgr.getFile(File);
return Lexer::Stringify(Path.str());
}
/// AddImplicitInclude - Add an implicit #include of the specified file to the
/// predefines buffer.
-static void AddImplicitInclude(MacroBuilder &Builder, llvm::StringRef File) {
+static void AddImplicitInclude(MacroBuilder &Builder, llvm::StringRef File,
+ FileManager &FileMgr) {
Builder.append("#include \"" +
- llvm::Twine(NormalizeDashIncludePath(File)) + "\"");
+ llvm::Twine(NormalizeDashIncludePath(File, FileMgr)) + "\"");
}
static void AddImplicitIncludeMacros(MacroBuilder &Builder,
- llvm::StringRef File) {
+ llvm::StringRef File,
+ FileManager &FileMgr) {
Builder.append("#__include_macros \"" +
- llvm::Twine(NormalizeDashIncludePath(File)) + "\"");
+ llvm::Twine(NormalizeDashIncludePath(File, FileMgr)) + "\"");
// Marker token to stop the __include_macros fetch loop.
Builder.append("##"); // ##?
}
@@ -94,7 +99,7 @@ static void AddImplicitIncludePTH(MacroBuilder &Builder, Preprocessor &PP,
return;
}
- AddImplicitInclude(Builder, OriginalFile);
+ AddImplicitInclude(Builder, OriginalFile, PP.getFileManager());
}
/// PickFP - This is used to pick a value based on the FP semantics of the
@@ -169,15 +174,10 @@ static void DefineFloatMacros(MacroBuilder &Builder, llvm::StringRef Prefix,
/// signedness of 'isSigned' and with a value suffix of 'ValSuffix' (e.g. LL).
static void DefineTypeSize(llvm::StringRef MacroName, unsigned TypeWidth,
llvm::StringRef ValSuffix, bool isSigned,
- MacroBuilder& Builder) {
- long long MaxVal;
- if (isSigned) {
- assert(TypeWidth != 1);
- MaxVal = ~0ULL >> (65-TypeWidth);
- } else
- MaxVal = ~0ULL >> (64-TypeWidth);
-
- Builder.defineMacro(MacroName, llvm::Twine(MaxVal) + ValSuffix);
+ MacroBuilder &Builder) {
+ llvm::APInt MaxVal = isSigned ? llvm::APInt::getSignedMaxValue(TypeWidth)
+ : llvm::APInt::getMaxValue(TypeWidth);
+ Builder.defineMacro(MacroName, MaxVal.toString(10, isSigned) + ValSuffix);
}
/// DefineTypeSize - An overloaded helper that uses TargetInfo to determine
@@ -590,7 +590,8 @@ void clang::InitializePreprocessor(Preprocessor &PP,
// If -imacros are specified, include them now. These are processed before
// any -include directives.
for (unsigned i = 0, e = InitOpts.MacroIncludes.size(); i != e; ++i)
- AddImplicitIncludeMacros(Builder, InitOpts.MacroIncludes[i]);
+ AddImplicitIncludeMacros(Builder, InitOpts.MacroIncludes[i],
+ PP.getFileManager());
// Process -include directives.
for (unsigned i = 0, e = InitOpts.Includes.size(); i != e; ++i) {
@@ -598,7 +599,7 @@ void clang::InitializePreprocessor(Preprocessor &PP,
if (Path == InitOpts.ImplicitPTHInclude)
AddImplicitIncludePTH(Builder, PP, Path);
else
- AddImplicitInclude(Builder, Path);
+ AddImplicitInclude(Builder, Path, PP.getFileManager());
}
// Exit the command line and go back to <built-in> (2 is LC_LEAVE).
diff --git a/contrib/llvm/tools/clang/lib/Frontend/TextDiagnosticPrinter.cpp b/contrib/llvm/tools/clang/lib/Frontend/TextDiagnosticPrinter.cpp
index 04c6a68..0849153 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/TextDiagnosticPrinter.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/TextDiagnosticPrinter.cpp
@@ -905,9 +905,21 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level,
std::string OptionName;
if (DiagOpts->ShowOptionNames) {
+ // Was this a warning mapped to an error using -Werror or pragma?
+ if (Level == Diagnostic::Error &&
+ DiagnosticIDs::isBuiltinWarningOrExtension(Info.getID())) {
+ diag::Mapping mapping = diag::MAP_IGNORE;
+ Info.getDiags()->getDiagnosticLevel(Info.getID(), Info.getLocation(),
+ &mapping);
+ if (mapping == diag::MAP_WARNING)
+ OptionName += "-Werror";
+ }
+
if (const char *
Opt = DiagnosticIDs::getWarningOptionForDiag(Info.getID())) {
- OptionName = "-W";
+ if (!OptionName.empty())
+ OptionName += ',';
+ OptionName += "-W";
OptionName += Opt;
} else if (Info.getID() == diag::fatal_too_many_errors) {
OptionName = "-ferror-limit=";
diff --git a/contrib/llvm/tools/clang/lib/Frontend/VerifyDiagnosticsClient.cpp b/contrib/llvm/tools/clang/lib/Frontend/VerifyDiagnosticsClient.cpp
index 51b351f..fff417e 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/VerifyDiagnosticsClient.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/VerifyDiagnosticsClient.cpp
@@ -369,7 +369,7 @@ static unsigned PrintProblem(Diagnostic &Diags, SourceManager *SourceMgr,
if (I->first.isInvalid() || !SourceMgr)
OS << "\n (frontend)";
else
- OS << "\n Line " << SourceMgr->getInstantiationLineNumber(I->first);
+ OS << "\n Line " << SourceMgr->getPresumedLineNumber(I->first);
OS << ": " << I->second;
}
@@ -391,7 +391,7 @@ static unsigned PrintProblem(Diagnostic &Diags, SourceManager *SourceMgr,
if (D.Location.isInvalid() || !SourceMgr)
OS << "\n (frontend)";
else
- OS << "\n Line " << SourceMgr->getInstantiationLineNumber(D.Location);
+ OS << "\n Line " << SourceMgr->getPresumedLineNumber(D.Location);
OS << ": " << D.Text;
}
@@ -413,12 +413,12 @@ static unsigned CheckLists(Diagnostic &Diags, SourceManager &SourceMgr,
for (DirectiveList::iterator I = Left.begin(), E = Left.end(); I != E; ++I) {
Directive& D = **I;
- unsigned LineNo1 = SourceMgr.getInstantiationLineNumber(D.Location);
+ unsigned LineNo1 = SourceMgr.getPresumedLineNumber(D.Location);
for (unsigned i = 0; i < D.Count; ++i) {
DiagList::iterator II, IE;
for (II = Right.begin(), IE = Right.end(); II != IE; ++II) {
- unsigned LineNo2 = SourceMgr.getInstantiationLineNumber(II->first);
+ unsigned LineNo2 = SourceMgr.getPresumedLineNumber(II->first);
if (LineNo1 != LineNo2)
continue;
diff --git a/contrib/llvm/tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/contrib/llvm/tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
index 4bb85e7..65fad6d 100644
--- a/contrib/llvm/tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
+++ b/contrib/llvm/tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
@@ -108,6 +108,12 @@ bool clang::ExecuteCompilerInvocation(CompilerInstance *Clang) {
return 0;
}
+ // Honor -analyzer-checker-help.
+ if (Clang->getAnalyzerOpts().ShowCheckerHelp) {
+ ento::printCheckerHelp(llvm::outs());
+ return 0;
+ }
+
// Honor -version.
//
// FIXME: Use a better -version message?
diff --git a/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp b/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp
index 0f0d25b..3e871ae 100644
--- a/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp
@@ -86,6 +86,7 @@ void Preprocessor::DiscardUntilEndOfDirective() {
Token Tmp;
do {
LexUnexpandedToken(Tmp);
+ assert(Tmp.isNot(tok::eof) && "EOF seen while discarding directive tokens");
} while (Tmp.isNot(tok::eom));
}
@@ -167,10 +168,12 @@ void Preprocessor::CheckEndOfDirective(const char *DirType, bool EnableMacros) {
if (Tmp.isNot(tok::eom)) {
// Add a fixit in GNU/C99/C++ mode. Don't offer a fixit for strict-C89,
- // because it is more trouble than it is worth to insert /**/ and check that
- // there is no /**/ in the range also.
+ // or if this is a macro-style preprocessing directive, because it is more
+ // trouble than it is worth to insert /**/ and check that there is no /**/
+ // in the range also.
FixItHint Hint;
- if (Features.GNUMode || Features.C99 || Features.CPlusPlus)
+ if ((Features.GNUMode || Features.C99 || Features.CPlusPlus) &&
+ !CurTokenLexer)
Hint = FixItHint::CreateInsertion(Tmp.getLocation(),"//");
Diag(Tmp, diag::ext_pp_extra_tokens_at_eol) << DirType << Hint;
DiscardUntilEndOfDirective();
diff --git a/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp b/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp
index f0475bc..80d3bb1 100644
--- a/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp
@@ -110,7 +110,8 @@ void Preprocessor::HandlePragmaDirective(unsigned Introducer) {
PragmaHandlers->HandlePragma(*this, PragmaIntroducerKind(Introducer), Tok);
// If the pragma handler didn't read the rest of the line, consume it now.
- if (CurPPLexer && CurPPLexer->ParsingPreprocessorDirective)
+ if ((CurTokenLexer && CurTokenLexer->isParsingPreprocessorDirective())
+ || (CurPPLexer && CurPPLexer->ParsingPreprocessorDirective))
DiscardUntilEndOfDirective();
}
@@ -174,7 +175,22 @@ void Preprocessor::Handle_Pragma(Token &Tok) {
}
}
- Handle_Pragma(PIK__Pragma, StrVal, PragmaLoc, RParenLoc);
+ // Plop the string (including the newline and trailing null) into a buffer
+ // where we can lex it.
+ Token TmpTok;
+ TmpTok.startToken();
+ CreateString(&StrVal[0], StrVal.size(), TmpTok);
+ SourceLocation TokLoc = TmpTok.getLocation();
+
+ // Make and enter a lexer object so that we lex and expand the tokens just
+ // like any others.
+ Lexer *TL = Lexer::Create_PragmaLexer(TokLoc, PragmaLoc, RParenLoc,
+ StrVal.size(), *this);
+
+ EnterSourceFileWithLexer(TL, 0);
+
+ // With everything set up, lex this as a #pragma directive.
+ HandlePragmaDirective(PIK__Pragma);
// Finally, return whatever came after the pragma directive.
return Lex(Tok);
@@ -193,16 +209,16 @@ void Preprocessor::HandleMicrosoft__pragma(Token &Tok) {
return;
}
- // Get the tokens enclosed within the __pragma().
+ // Get the tokens enclosed within the __pragma(), as well as the final ')'.
llvm::SmallVector<Token, 32> PragmaToks;
int NumParens = 0;
Lex(Tok);
while (Tok.isNot(tok::eof)) {
+ PragmaToks.push_back(Tok);
if (Tok.is(tok::l_paren))
NumParens++;
else if (Tok.is(tok::r_paren) && NumParens-- == 0)
break;
- PragmaToks.push_back(Tok);
Lex(Tok);
}
@@ -211,45 +227,23 @@ void Preprocessor::HandleMicrosoft__pragma(Token &Tok) {
return;
}
- // Build the pragma string.
- std::string StrVal = " ";
- for (llvm::SmallVector<Token, 32>::iterator I =
- PragmaToks.begin(), E = PragmaToks.end(); I != E; ++I) {
- StrVal += getSpelling(*I);
- }
-
- SourceLocation RParenLoc = Tok.getLocation();
-
- Handle_Pragma(PIK___pragma, StrVal, PragmaLoc, RParenLoc);
+ PragmaToks.front().setFlag(Token::LeadingSpace);
- // Finally, return whatever came after the pragma directive.
- return Lex(Tok);
-}
+ // Replace the ')' with an EOM to mark the end of the pragma.
+ PragmaToks.back().setKind(tok::eom);
-void Preprocessor::Handle_Pragma(unsigned Introducer,
- const std::string &StrVal,
- SourceLocation PragmaLoc,
- SourceLocation RParenLoc) {
+ Token *TokArray = new Token[PragmaToks.size()];
+ std::copy(PragmaToks.begin(), PragmaToks.end(), TokArray);
- // Plop the string (including the newline and trailing null) into a buffer
- // where we can lex it.
- Token TmpTok;
- TmpTok.startToken();
- CreateString(&StrVal[0], StrVal.size(), TmpTok);
- SourceLocation TokLoc = TmpTok.getLocation();
-
- // Make and enter a lexer object so that we lex and expand the tokens just
- // like any others.
- Lexer *TL = Lexer::Create_PragmaLexer(TokLoc, PragmaLoc, RParenLoc,
- StrVal.size(), *this);
-
- EnterSourceFileWithLexer(TL, 0);
+ // Push the tokens onto the stack.
+ EnterTokenStream(TokArray, PragmaToks.size(), true, true);
// With everything set up, lex this as a #pragma directive.
- HandlePragmaDirective(Introducer);
-}
-
+ HandlePragmaDirective(PIK___pragma);
+ // Finally, return whatever came after the pragma directive.
+ return Lex(Tok);
+}
/// HandlePragmaOnce - Handle #pragma once. OnceTok is the 'once'.
///
diff --git a/contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp b/contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp
index ea39b47..caa44bf 100644
--- a/contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp
@@ -543,6 +543,11 @@ unsigned TokenLexer::isNextTokenLParen() const {
return Tokens[CurToken].is(tok::l_paren);
}
+/// isParsingPreprocessorDirective - Return true if we are in the middle of a
+/// preprocessor directive.
+bool TokenLexer::isParsingPreprocessorDirective() const {
+ return Tokens[NumTokens-1].is(tok::eom) && !isAtEnd();
+}
/// HandleMicrosoftCommentPaste - In microsoft compatibility mode, /##/ pastes
/// together to form a comment that comments out everything in the current
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp
index 5a7fc7e..077edd7 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp
@@ -667,6 +667,8 @@ Decl *Parser::ParseDeclarationAfterDeclarator(Declarator &D,
Actions.ActOnUninitializedDecl(ThisDecl, TypeContainsAuto);
}
+ Actions.FinalizeDeclaration(ThisDecl);
+
return ThisDecl;
}
@@ -954,8 +956,9 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
goto DoneWithDeclSpec;
CXXScopeSpec SS;
- SS.setScopeRep((NestedNameSpecifier*) Tok.getAnnotationValue());
- SS.setRange(Tok.getAnnotationRange());
+ Actions.RestoreNestedNameSpecifierAnnotation(Tok.getAnnotationValue(),
+ Tok.getAnnotationRange(),
+ SS);
// We are looking for a qualified typename.
Token Next = NextToken();
@@ -1244,9 +1247,18 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
DiagID, getLang());
break;
case tok::kw_auto:
- if (getLang().CPlusPlus0x)
- isInvalid = DS.SetTypeSpecType(DeclSpec::TST_auto, Loc, PrevSpec,
- DiagID);
+ if (getLang().CPlusPlus0x || getLang().ObjC2) {
+ if (isKnownToBeTypeSpecifier(GetLookAheadToken(1))) {
+ isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_auto, Loc, PrevSpec,
+ DiagID, getLang());
+ if (!isInvalid)
+ Diag(Tok, diag::auto_storage_class)
+ << FixItHint::CreateRemoval(DS.getStorageClassSpecLoc());
+ }
+ else
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_auto, Loc, PrevSpec,
+ DiagID);
+ }
else
isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_auto, Loc, PrevSpec,
DiagID, getLang());
@@ -1459,6 +1471,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
else
Diag(Tok, DiagID) << PrevSpec;
}
+
DS.SetRangeEnd(Tok.getLocation());
ConsumeToken();
}
@@ -1973,6 +1986,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
}
}
+ bool AllowFixedUnderlyingType = getLang().CPlusPlus0x || getLang().Microsoft;
bool IsScopedEnum = false;
bool IsScopedUsingClassTag = false;
@@ -1984,7 +1998,8 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
}
// Must have either 'enum name' or 'enum {...}'.
- if (Tok.isNot(tok::identifier) && Tok.isNot(tok::l_brace)) {
+ if (Tok.isNot(tok::identifier) && Tok.isNot(tok::l_brace) &&
+ (AllowFixedUnderlyingType && Tok.isNot(tok::colon))) {
Diag(Tok, diag::err_expected_ident_lbrace);
// Skip the rest of this declarator, up until the comma or semicolon.
@@ -2011,7 +2026,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
TypeResult BaseType;
// Parse the fixed underlying type.
- if (getLang().CPlusPlus0x && Tok.is(tok::colon)) {
+ if (AllowFixedUnderlyingType && Tok.is(tok::colon)) {
bool PossibleBitfield = false;
if (getCurScope()->getFlags() & Scope::ClassScope) {
// If we're in class scope, this can either be an enum declaration with
@@ -2043,7 +2058,9 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
// Consume the ':'.
ConsumeToken();
- if (isCXXDeclarationSpecifier() != TPResult::True()) {
+ if ((getLang().CPlusPlus &&
+ isCXXDeclarationSpecifier() != TPResult::True()) ||
+ (!getLang().CPlusPlus && !isDeclarationSpecifier(true))) {
// We'll parse this as a bitfield later.
PossibleBitfield = true;
TPA.Revert();
@@ -2060,6 +2077,10 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
if (!PossibleBitfield) {
SourceRange Range;
BaseType = ParseTypeName(&Range);
+
+ if (!getLang().CPlusPlus0x)
+ Diag(StartLoc, diag::ext_ms_enum_fixed_underlying_type)
+ << Range;
}
}
@@ -2090,6 +2111,14 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
return;
}
+ if (!Name && TUK != Sema::TUK_Definition) {
+ Diag(Tok, diag::err_enumerator_unnamed_no_def);
+
+ // Skip the rest of this declarator, up until the comma or semicolon.
+ SkipUntil(tok::comma, true);
+ return;
+ }
+
bool Owned = false;
bool IsDependent = false;
SourceLocation TSTLoc = NameLoc.isValid()? NameLoc : StartLoc;
@@ -2734,6 +2763,9 @@ void Parser::ParseDeclaratorInternal(Declarator &D,
if (Kind == tok::star)
// Remember that we parsed a pointer type, and remember the type-quals.
D.AddTypeInfo(DeclaratorChunk::getPointer(DS.getTypeQualifiers(), Loc,
+ DS.getConstSpecLoc(),
+ DS.getVolatileSpecLoc(),
+ DS.getRestrictSpecLoc(),
DS.takeAttributes()),
SourceLocation());
else
@@ -3730,4 +3762,3 @@ bool Parser::TryAltiVecTokenOutOfLine(DeclSpec &DS, SourceLocation Loc,
}
return false;
}
-
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp
index e73578f..d8db711 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp
@@ -65,8 +65,9 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
"Call sites of this function should be guarded by checking for C++");
if (Tok.is(tok::annot_cxxscope)) {
- SS.setScopeRep(static_cast<NestedNameSpecifier*>(Tok.getAnnotationValue()));
- SS.setRange(Tok.getAnnotationRange());
+ Actions.RestoreNestedNameSpecifierAnnotation(Tok.getAnnotationValue(),
+ Tok.getAnnotationRange(),
+ SS);
ConsumeToken();
return false;
}
@@ -80,10 +81,9 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
return false;
// '::' - Global scope qualifier.
- SourceLocation CCLoc = ConsumeToken();
- SS.setBeginLoc(CCLoc);
- SS.setScopeRep(Actions.ActOnCXXGlobalScopeSpecifier(getCurScope(), CCLoc));
- SS.setEndLoc(CCLoc);
+ if (Actions.ActOnCXXGlobalScopeSpecifier(getCurScope(), ConsumeToken(), SS))
+ return true;
+
HasScopeSpecifier = true;
}
@@ -208,20 +208,20 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
assert(Tok.is(tok::coloncolon) && "NextToken() not working properly!");
SourceLocation CCLoc = ConsumeToken();
- if (!HasScopeSpecifier) {
- SS.setBeginLoc(TypeToken.getLocation());
+ if (!HasScopeSpecifier)
HasScopeSpecifier = true;
- }
if (ParsedType T = getTypeAnnotation(TypeToken)) {
- CXXScopeTy *Scope =
- Actions.ActOnCXXNestedNameSpecifier(getCurScope(), SS, T,
- TypeToken.getAnnotationRange(),
- CCLoc);
- SS.setScopeRep(Scope);
- } else
- SS.setScopeRep(0);
- SS.setEndLoc(CCLoc);
+ if (Actions.ActOnCXXNestedNameSpecifier(getCurScope(), T, CCLoc, SS))
+ SS.SetInvalid(SourceRange(SS.getBeginLoc(), CCLoc));
+
+ continue;
+ } else {
+ SourceLocation Start = SS.getBeginLoc().isValid()? SS.getBeginLoc()
+ : CCLoc;
+ SS.SetInvalid(SourceRange(Start, CCLoc));
+ }
+
continue;
}
@@ -245,7 +245,9 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
// If we get foo:bar, this is almost certainly a typo for foo::bar. Recover
// and emit a fixit hint for it.
if (Next.is(tok::colon) && !ColonIsSacred) {
- if (Actions.IsInvalidUnlessNestedName(getCurScope(), SS, II, ObjectType,
+ if (Actions.IsInvalidUnlessNestedName(getCurScope(), SS, II,
+ Tok.getLocation(),
+ Next.getLocation(), ObjectType,
EnteringContext) &&
// If the token after the colon isn't an identifier, it's still an
// error, but they probably meant something else strange so don't
@@ -274,16 +276,11 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
"NextToken() not working properly!");
SourceLocation CCLoc = ConsumeToken();
- if (!HasScopeSpecifier) {
- SS.setBeginLoc(IdLoc);
- HasScopeSpecifier = true;
- }
-
- if (!SS.isInvalid())
- SS.setScopeRep(
- Actions.ActOnCXXNestedNameSpecifier(getCurScope(), SS, IdLoc, CCLoc, II,
- ObjectType, EnteringContext));
- SS.setEndLoc(CCLoc);
+ HasScopeSpecifier = true;
+ if (Actions.ActOnCXXNestedNameSpecifier(getCurScope(), II, IdLoc, CCLoc,
+ ObjectType, EnteringContext, SS))
+ SS.SetInvalid(SourceRange(IdLoc, CCLoc));
+
continue;
}
@@ -836,6 +833,8 @@ bool Parser::ParseCXXCondition(ExprResult &ExprOut,
// FIXME: Build a reference to this declaration? Convert it to bool?
// (This is currently handled by Sema).
+
+ Actions.FinalizeDeclaration(DeclOut);
return false;
}
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp
index 8387c88..59ced8b 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp
@@ -829,7 +829,7 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
TemplateId->RAngleLoc = RAngleLoc;
ParsedTemplateArgument *Args = TemplateId->getTemplateArgs();
for (unsigned Arg = 0, ArgEnd = TemplateArgs.size(); Arg != ArgEnd; ++Arg)
- Args[Arg] = TemplateArgs[Arg];
+ Args[Arg] = ParsedTemplateArgument(TemplateArgs[Arg]);
Tok.setAnnotationValue(TemplateId);
if (TemplateKWLoc.isValid())
Tok.setLocation(TemplateKWLoc);
diff --git a/contrib/llvm/tools/clang/lib/Parse/Parser.cpp b/contrib/llvm/tools/clang/lib/Parse/Parser.cpp
index a50763a..07e592c 100644
--- a/contrib/llvm/tools/clang/lib/Parse/Parser.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/Parser.cpp
@@ -296,6 +296,10 @@ bool Parser::SkipUntil(const tok::TokenKind *Toks, unsigned NumToks,
case tok::wide_string_literal:
ConsumeStringToken();
break;
+
+ case tok::at:
+ return false;
+
case tok::semi:
if (StopAtSemi)
return false;
@@ -1159,7 +1163,7 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) {
else
PP.EnterToken(Tok);
Tok.setKind(tok::annot_cxxscope);
- Tok.setAnnotationValue(SS.getScopeRep());
+ Tok.setAnnotationValue(Actions.SaveNestedNameSpecifierAnnotation(SS));
Tok.setAnnotationRange(SS.getRange());
// In case the tokens were cached, have Preprocessor replace them
@@ -1196,7 +1200,7 @@ bool Parser::TryAnnotateCXXScopeToken(bool EnteringContext) {
else
PP.EnterToken(Tok);
Tok.setKind(tok::annot_cxxscope);
- Tok.setAnnotationValue(SS.getScopeRep());
+ Tok.setAnnotationValue(Actions.SaveNestedNameSpecifierAnnotation(SS));
Tok.setAnnotationRange(SS.getRange());
// In case the tokens were cached, have Preprocessor replace them with the
diff --git a/contrib/llvm/tools/clang/lib/Rewrite/RewriteObjC.cpp b/contrib/llvm/tools/clang/lib/Rewrite/RewriteObjC.cpp
index 875a0c7..0263f65 100644
--- a/contrib/llvm/tools/clang/lib/Rewrite/RewriteObjC.cpp
+++ b/contrib/llvm/tools/clang/lib/Rewrite/RewriteObjC.cpp
@@ -298,6 +298,7 @@ namespace {
Stmt *RewriteObjCThrowStmt(ObjCAtThrowStmt *S);
Stmt *RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S,
SourceLocation OrigEnd);
+ bool IsDeclStmtInForeachHeader(DeclStmt *DS);
CallExpr *SynthesizeCallToFunctionDecl(FunctionDecl *FD,
Expr **args, unsigned nargs,
SourceLocation StartLoc=SourceLocation(),
@@ -1348,13 +1349,13 @@ Stmt *RewriteObjC::RewritePropertyOrImplicitGetter(Expr *PropOrGetterRefExpr) {
MsgExpr = ObjCMessageExpr::Create(*Context,
Ty.getNonReferenceType(),
Expr::getValueKindForType(Ty),
- /*FIXME?*/SourceLocation(),
+ PropOrGetterRefExpr->getLocStart(),
SuperLocation,
/*IsInstanceSuper=*/true,
SuperTy,
Sel, SelectorLoc, OMD,
0, 0,
- /*FIXME:*/SourceLocation());
+ PropOrGetterRefExpr->getLocEnd());
else {
assert (Receiver && "RewritePropertyOrImplicitGetter - Receiver is null");
if (Expr *Exp = dyn_cast<Expr>(Receiver))
@@ -1364,14 +1365,15 @@ Stmt *RewriteObjC::RewritePropertyOrImplicitGetter(Expr *PropOrGetterRefExpr) {
MsgExpr = ObjCMessageExpr::Create(*Context,
Ty.getNonReferenceType(),
Expr::getValueKindForType(Ty),
- /*FIXME:*/SourceLocation(),
+ PropOrGetterRefExpr->getLocStart(),
cast<Expr>(Receiver),
Sel, SelectorLoc, OMD,
0, 0,
- /*FIXME:*/SourceLocation());
+ PropOrGetterRefExpr->getLocEnd());
}
- Stmt *ReplacingStmt = SynthMessageExpr(MsgExpr);
+ Stmt *ReplacingStmt = SynthMessageExpr(MsgExpr, MsgExpr->getLocStart(),
+ MsgExpr->getLocEnd());
if (!PropParentMap)
PropParentMap = new ParentMap(CurrentBody);
@@ -2986,9 +2988,9 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
// Make all implicit casts explicit...ICE comes in handy:-)
if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(userExpr)) {
// Reuse the ICE type, it is exactly what the doctor ordered.
- QualType type = ICE->getType()->isObjCQualifiedIdType()
- ? Context->getObjCIdType()
- : ICE->getType();
+ QualType type = ICE->getType();
+ if (needToScanForQualifiers(type))
+ type = Context->getObjCIdType();
// Make sure we convert "type (^)(...)" to "type (*)(...)".
(void)convertBlockPointerToFunctionPointer(type);
userExpr = NoTypeInfoCStyleCastExpr(Context, type, CK_BitCast,
@@ -5459,6 +5461,13 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp,
return NewRep;
}
+bool RewriteObjC::IsDeclStmtInForeachHeader(DeclStmt *DS) {
+ if (const ObjCForCollectionStmt * CS =
+ dyn_cast<ObjCForCollectionStmt>(Stmts.back()))
+ return CS->getElement() == DS;
+ return false;
+}
+
//===----------------------------------------------------------------------===//
// Function Body / Expression rewriting
//===----------------------------------------------------------------------===//
@@ -5681,7 +5690,7 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
// for (id <FooProtocol> index in someArray) ;
// This is because RewriteObjCForCollectionStmt() does textual rewriting
// and it depends on the original text locations/positions.
- if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back()))
+ if (Stmts.empty() || !IsDeclStmtInForeachHeader(DS))
RewriteObjCQualifiedInterfaceTypes(*DS->decl_begin());
// Blocks rewrite rules.
diff --git a/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp b/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp
index 63f561d..6a42224 100644
--- a/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -15,6 +15,7 @@
#include "clang/Sema/AnalysisBasedWarnings.h"
#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/ScopeInfo.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/AST/DeclObjC.h"
@@ -26,6 +27,8 @@
#include "clang/Analysis/AnalysisContext.h"
#include "clang/Analysis/CFG.h"
#include "clang/Analysis/Analyses/ReachableCode.h"
+#include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h"
+#include "clang/Analysis/CFGStmtMap.h"
#include "clang/Analysis/Analyses/UninitializedValuesV2.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/Support/Casting.h"
@@ -289,7 +292,7 @@ struct CheckFallThroughDiagnostics {
/// of a noreturn function. We assume that functions and blocks not marked
/// noreturn will return.
static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body,
- QualType BlockTy,
+ const BlockExpr *blkExpr,
const CheckFallThroughDiagnostics& CD,
AnalysisContext &AC) {
@@ -306,6 +309,7 @@ static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body,
HasNoReturn = MD->hasAttr<NoReturnAttr>();
}
else if (isa<BlockDecl>(D)) {
+ QualType BlockTy = blkExpr->getType();
if (const FunctionType *FT =
BlockTy->getPointeeType()->getAs<FunctionType>()) {
if (FT->getResultType()->isVoidType())
@@ -477,11 +481,20 @@ clang::sema::AnalysisBasedWarnings::AnalysisBasedWarnings(Sema &s) : S(s) {
Diagnostic::Ignored);
}
+static void flushDiagnostics(Sema &S, sema::FunctionScopeInfo *fscope) {
+ for (llvm::SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator
+ i = fscope->PossiblyUnreachableDiags.begin(),
+ e = fscope->PossiblyUnreachableDiags.end();
+ i != e; ++i) {
+ const sema::PossiblyUnreachableDiag &D = *i;
+ S.Diag(D.Loc, D.PD);
+ }
+}
+
void clang::sema::
AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
- const Decl *D, QualType BlockTy) {
-
- assert(BlockTy.isNull() || isa<BlockDecl>(D));
+ sema::FunctionScopeInfo *fscope,
+ const Decl *D, const BlockExpr *blkExpr) {
// We avoid doing analysis-based warnings when there are errors for
// two reasons:
@@ -491,9 +504,6 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
// time.
Diagnostic &Diags = S.getDiagnostics();
- if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred())
- return;
-
// Do not do any analysis for declarations in system headers if we are
// going to just ignore them.
if (Diags.getSuppressSystemWarnings() &&
@@ -504,6 +514,12 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
if (cast<DeclContext>(D)->isDependentContext())
return;
+ if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred()) {
+ // Flush out any possibly unreachable diagnostics.
+ flushDiagnostics(S, fscope);
+ return;
+ }
+
const Stmt *Body = D->getBody();
assert(Body);
@@ -512,12 +528,40 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
AnalysisContext AC(D, 0, /*useUnoptimizedCFG=*/false, /*addehedges=*/false,
/*addImplicitDtors=*/true, /*addInitializers=*/true);
+ // Emit delayed diagnostics.
+ if (!fscope->PossiblyUnreachableDiags.empty()) {
+ bool analyzed = false;
+ if (CFGReachabilityAnalysis *cra = AC.getCFGReachablityAnalysis())
+ if (CFGStmtMap *csm = AC.getCFGStmtMap()) {
+ analyzed = true;
+ for (llvm::SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator
+ i = fscope->PossiblyUnreachableDiags.begin(),
+ e = fscope->PossiblyUnreachableDiags.end();
+ i != e; ++i) {
+ const sema::PossiblyUnreachableDiag &D = *i;
+ if (const CFGBlock *blk = csm->getBlock(D.stmt)) {
+ // Can this block be reached from the entrance?
+ if (cra->isReachable(&AC.getCFG()->getEntry(), blk))
+ S.Diag(D.Loc, D.PD);
+ }
+ else {
+ // Emit the warning anyway if we cannot map to a basic block.
+ S.Diag(D.Loc, D.PD);
+ }
+ }
+ }
+
+ if (!analyzed)
+ flushDiagnostics(S, fscope);
+ }
+
+
// Warning: check missing 'return'
if (P.enableCheckFallThrough) {
const CheckFallThroughDiagnostics &CD =
(isa<BlockDecl>(D) ? CheckFallThroughDiagnostics::MakeForBlock()
: CheckFallThroughDiagnostics::MakeForFunction(D));
- CheckFallThroughForBody(S, D, Body, BlockTy, CD, AC);
+ CheckFallThroughForBody(S, D, Body, blkExpr, CD, AC);
}
// Warning: check for unreachable code
@@ -550,21 +594,3 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
}
}
}
-
-void clang::sema::
-AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
- const BlockExpr *E) {
- return IssueWarnings(P, E->getBlockDecl(), E->getType());
-}
-
-void clang::sema::
-AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
- const ObjCMethodDecl *D) {
- return IssueWarnings(P, D, QualType());
-}
-
-void clang::sema::
-AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
- const FunctionDecl *D) {
- return IssueWarnings(P, D, QualType());
-}
diff --git a/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp
index bc289ec..037594a 100644
--- a/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp
@@ -14,6 +14,9 @@
#include "clang/Parse/ParseDiagnostic.h" // FIXME: remove this back-dependency!
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/ParsedTemplate.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/TypeLoc.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Basic/LangOptions.h"
#include "llvm/ADT/STLExtras.h"
@@ -44,6 +47,239 @@ void UnqualifiedId::setConstructorTemplateId(TemplateIdAnnotation *TemplateId) {
EndLocation = TemplateId->RAngleLoc;
}
+CXXScopeSpec::CXXScopeSpec(const CXXScopeSpec &Other)
+ : Range(Other.Range), ScopeRep(Other.ScopeRep), Buffer(0),
+ BufferSize(Other.BufferSize), BufferCapacity(Other.BufferSize)
+{
+ if (BufferSize) {
+ Buffer = static_cast<char *>(malloc(BufferSize));
+ memcpy(Buffer, Other.Buffer, BufferSize);
+ }
+}
+
+CXXScopeSpec &CXXScopeSpec::operator=(const CXXScopeSpec &Other) {
+ Range = Other.Range;
+ ScopeRep = Other.ScopeRep;
+ if (Buffer && Other.Buffer && BufferCapacity >= Other.BufferSize) {
+ // Re-use our storage.
+ BufferSize = Other.BufferSize;
+ memcpy(Buffer, Other.Buffer, BufferSize);
+ return *this;
+ }
+
+ if (BufferCapacity)
+ free(Buffer);
+ if (Other.Buffer) {
+ BufferSize = Other.BufferSize;
+ BufferCapacity = BufferSize;
+ Buffer = static_cast<char *>(malloc(BufferSize));
+ memcpy(Buffer, Other.Buffer, BufferSize);
+ } else {
+ Buffer = 0;
+ BufferSize = 0;
+ BufferCapacity = 0;
+ }
+ return *this;
+}
+
+CXXScopeSpec::~CXXScopeSpec() {
+ if (BufferCapacity)
+ free(Buffer);
+}
+
+namespace {
+ void Append(char *Start, char *End, char *&Buffer, unsigned &BufferSize,
+ unsigned &BufferCapacity) {
+ if (BufferSize + (End - Start) > BufferCapacity) {
+ // Reallocate the buffer.
+ unsigned NewCapacity
+ = std::max((unsigned)(BufferCapacity? BufferCapacity * 2
+ : sizeof(void*) * 2),
+ (unsigned)(BufferSize + (End - Start)));
+ char *NewBuffer = static_cast<char *>(malloc(NewCapacity));
+ memcpy(NewBuffer, Buffer, BufferSize);
+
+ if (BufferCapacity)
+ free(Buffer);
+ Buffer = NewBuffer;
+ BufferCapacity = NewCapacity;
+ }
+
+ memcpy(Buffer + BufferSize, Start, End - Start);
+ BufferSize += End-Start;
+ }
+
+ /// \brief Save a source location to the given buffer.
+ void SaveSourceLocation(SourceLocation Loc, char *&Buffer,
+ unsigned &BufferSize, unsigned &BufferCapacity) {
+ unsigned Raw = Loc.getRawEncoding();
+ Append(reinterpret_cast<char *>(&Raw),
+ reinterpret_cast<char *>(&Raw) + sizeof(unsigned),
+ Buffer, BufferSize, BufferCapacity);
+ }
+
+ /// \brief Save a pointer to the given buffer.
+ void SavePointer(void *Ptr, char *&Buffer, unsigned &BufferSize,
+ unsigned &BufferCapacity) {
+ Append(reinterpret_cast<char *>(&Ptr),
+ reinterpret_cast<char *>(&Ptr) + sizeof(void *),
+ Buffer, BufferSize, BufferCapacity);
+ }
+}
+void CXXScopeSpec::Extend(ASTContext &Context, SourceLocation TemplateKWLoc,
+ TypeLoc TL, SourceLocation ColonColonLoc) {
+ ScopeRep = NestedNameSpecifier::Create(Context, ScopeRep,
+ TemplateKWLoc.isValid(),
+ TL.getTypePtr());
+ if (Range.getBegin().isInvalid())
+ Range.setBegin(TL.getBeginLoc());
+ Range.setEnd(ColonColonLoc);
+
+ // Push source-location info into the buffer.
+ SavePointer(TL.getOpaqueData(), Buffer, BufferSize, BufferCapacity);
+ SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
+
+ assert(Range == NestedNameSpecifierLoc(ScopeRep, Buffer).getSourceRange() &&
+ "NestedNameSpecifierLoc range computation incorrect");
+}
+
+void CXXScopeSpec::Extend(ASTContext &Context, IdentifierInfo *Identifier,
+ SourceLocation IdentifierLoc,
+ SourceLocation ColonColonLoc) {
+ ScopeRep = NestedNameSpecifier::Create(Context, ScopeRep, Identifier);
+ if (Range.getBegin().isInvalid())
+ Range.setBegin(IdentifierLoc);
+ Range.setEnd(ColonColonLoc);
+
+ // Push source-location info into the buffer.
+ SaveSourceLocation(IdentifierLoc, Buffer, BufferSize, BufferCapacity);
+ SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
+
+ assert(Range == NestedNameSpecifierLoc(ScopeRep, Buffer).getSourceRange() &&
+ "NestedNameSpecifierLoc range computation incorrect");
+}
+
+void CXXScopeSpec::Extend(ASTContext &Context, NamespaceDecl *Namespace,
+ SourceLocation NamespaceLoc,
+ SourceLocation ColonColonLoc) {
+ ScopeRep = NestedNameSpecifier::Create(Context, ScopeRep, Namespace);
+ if (Range.getBegin().isInvalid())
+ Range.setBegin(NamespaceLoc);
+ Range.setEnd(ColonColonLoc);
+
+ // Push source-location info into the buffer.
+ SaveSourceLocation(NamespaceLoc, Buffer, BufferSize, BufferCapacity);
+ SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
+
+ assert(Range == NestedNameSpecifierLoc(ScopeRep, Buffer).getSourceRange() &&
+ "NestedNameSpecifierLoc range computation incorrect");
+}
+
+void CXXScopeSpec::Extend(ASTContext &Context, NamespaceAliasDecl *Alias,
+ SourceLocation AliasLoc,
+ SourceLocation ColonColonLoc) {
+ ScopeRep = NestedNameSpecifier::Create(Context, ScopeRep, Alias);
+ if (Range.getBegin().isInvalid())
+ Range.setBegin(AliasLoc);
+ Range.setEnd(ColonColonLoc);
+
+ // Push source-location info into the buffer.
+ SaveSourceLocation(AliasLoc, Buffer, BufferSize, BufferCapacity);
+ SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
+
+ assert(Range == NestedNameSpecifierLoc(ScopeRep, Buffer).getSourceRange() &&
+ "NestedNameSpecifierLoc range computation incorrect");
+}
+
+void CXXScopeSpec::MakeGlobal(ASTContext &Context,
+ SourceLocation ColonColonLoc) {
+ assert(!ScopeRep && "Already have a nested-name-specifier!?");
+ ScopeRep = NestedNameSpecifier::GlobalSpecifier(Context);
+ Range = SourceRange(ColonColonLoc);
+
+ // Push source-location info into the buffer.
+ SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
+
+ assert(Range == NestedNameSpecifierLoc(ScopeRep, Buffer).getSourceRange() &&
+ "NestedNameSpecifierLoc range computation incorrect");
+}
+
+void CXXScopeSpec::MakeTrivial(ASTContext &Context,
+ NestedNameSpecifier *Qualifier, SourceRange R) {
+ ScopeRep = Qualifier;
+ Range = R;
+
+ // Construct bogus (but well-formed) source information for the
+ // nested-name-specifier.
+ BufferSize = 0;
+ llvm::SmallVector<NestedNameSpecifier *, 4> Stack;
+ for (NestedNameSpecifier *NNS = Qualifier; NNS; NNS = NNS->getPrefix())
+ Stack.push_back(NNS);
+ while (!Stack.empty()) {
+ NestedNameSpecifier *NNS = Stack.back();
+ Stack.pop_back();
+ switch (NNS->getKind()) {
+ case NestedNameSpecifier::Identifier:
+ case NestedNameSpecifier::Namespace:
+ case NestedNameSpecifier::NamespaceAlias:
+ SaveSourceLocation(R.getBegin(), Buffer, BufferSize, BufferCapacity);
+ break;
+
+ case NestedNameSpecifier::TypeSpec:
+ case NestedNameSpecifier::TypeSpecWithTemplate: {
+ TypeSourceInfo *TSInfo
+ = Context.getTrivialTypeSourceInfo(QualType(NNS->getAsType(), 0),
+ R.getBegin());
+ SavePointer(TSInfo->getTypeLoc().getOpaqueData(), Buffer, BufferSize,
+ BufferCapacity);
+ break;
+ }
+
+ case NestedNameSpecifier::Global:
+ break;
+ }
+
+ // Save the location of the '::'.
+ SaveSourceLocation(Stack.empty()? R.getEnd() : R.getBegin(),
+ Buffer, BufferSize, BufferCapacity);
+ }
+}
+
+void CXXScopeSpec::Adopt(NestedNameSpecifierLoc Other) {
+ if (!Other) {
+ Range = SourceRange();
+ ScopeRep = 0;
+ return;
+ }
+
+ if (BufferCapacity)
+ free(Buffer);
+
+ // Rather than copying the data (which is wasteful), "adopt" the
+ // pointer (which points into the ASTContext) but set the capacity to zero to
+ // indicate that we don't own it.
+ Range = Other.getSourceRange();
+ ScopeRep = Other.getNestedNameSpecifier();
+ Buffer = static_cast<char *>(Other.getOpaqueData());
+ BufferSize = Other.getDataLength();
+ BufferCapacity = 0;
+}
+
+NestedNameSpecifierLoc
+CXXScopeSpec::getWithLocInContext(ASTContext &Context) const {
+ if (isEmpty() || isInvalid())
+ return NestedNameSpecifierLoc();
+
+ // If we adopted our data pointer from elsewhere in the AST context, there's
+ // no need to copy the memory.
+ if (BufferCapacity == 0)
+ return NestedNameSpecifierLoc(ScopeRep, Buffer);
+
+ void *Mem = Context.Allocate(BufferSize, llvm::alignOf<void *>());
+ memcpy(Mem, Buffer, BufferSize);
+ return NestedNameSpecifierLoc(ScopeRep, Mem);
+}
+
/// DeclaratorChunk::getFunction - Return a DeclaratorChunk for a function.
/// "TheDeclarator" is the declarator that this will be added to.
DeclaratorChunk DeclaratorChunk::getFunction(const ParsedAttributes &attrs,
diff --git a/contrib/llvm/tools/clang/lib/Sema/Sema.cpp b/contrib/llvm/tools/clang/lib/Sema/Sema.cpp
index 23a3c24..0c39e13 100644
--- a/contrib/llvm/tools/clang/lib/Sema/Sema.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/Sema.cpp
@@ -48,6 +48,7 @@ void FunctionScopeInfo::Clear() {
SwitchStack.clear();
Returns.clear();
ErrorTrap.reset();
+ PossiblyUnreachableDiags.clear();
}
BlockScopeInfo::~BlockScopeInfo() { }
@@ -466,6 +467,12 @@ void Sema::ActOnEndOfTranslationUnit() {
checkUndefinedInternals(*this);
}
+ // Check we've noticed that we're no longer parsing the initializer for every
+ // variable. If we miss cases, then at best we have a performance issue and
+ // at worst a rejects-valid bug.
+ assert(ParsingInitForAutoVars.empty() &&
+ "Didn't unmark var as having its initializer parsed");
+
TUScope = 0;
}
@@ -625,11 +632,27 @@ void Sema::PushBlockScope(Scope *BlockScope, BlockDecl *Block) {
BlockScope, Block));
}
-void Sema::PopFunctionOrBlockScope() {
- FunctionScopeInfo *Scope = FunctionScopes.pop_back_val();
+void Sema::PopFunctionOrBlockScope(const AnalysisBasedWarnings::Policy *WP,
+ const Decl *D, const BlockExpr *blkExpr) {
+ FunctionScopeInfo *Scope = FunctionScopes.pop_back_val();
assert(!FunctionScopes.empty() && "mismatched push/pop!");
- if (FunctionScopes.back() != Scope)
+
+ // Issue any analysis-based warnings.
+ if (WP && D)
+ AnalysisWarnings.IssueWarnings(*WP, Scope, D, blkExpr);
+ else {
+ for (llvm::SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator
+ i = Scope->PossiblyUnreachableDiags.begin(),
+ e = Scope->PossiblyUnreachableDiags.end();
+ i != e; ++i) {
+ const sema::PossiblyUnreachableDiag &D = *i;
+ Diag(D.Loc, D.PD);
+ }
+ }
+
+ if (FunctionScopes.back() != Scope) {
delete Scope;
+ }
}
/// \brief Determine whether any errors occurred within this function/method/
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp
index aa0efcd..7ad4b45 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp
@@ -19,6 +19,7 @@
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Sema/DeclSpec.h"
+#include "TypeLocBuilder.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
@@ -138,6 +139,9 @@ DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS,
case NestedNameSpecifier::Namespace:
return NNS->getAsNamespace();
+ case NestedNameSpecifier::NamespaceAlias:
+ return NNS->getAsNamespaceAlias()->getNamespace();
+
case NestedNameSpecifier::TypeSpec:
case NestedNameSpecifier::TypeSpecWithTemplate: {
const TagType *Tag = NNS->getAsType()->getAs<TagType>();
@@ -219,7 +223,7 @@ bool Sema::RequireCompleteDeclContext(CXXScopeSpec &SS,
Context.getTypeDeclType(Tag),
PDiag(diag::err_incomplete_nested_name_spec)
<< SS.getRange())) {
- SS.setScopeRep(0); // Mark the ScopeSpec invalid.
+ SS.SetInvalid(SS.getRange());
return true;
}
}
@@ -227,11 +231,10 @@ bool Sema::RequireCompleteDeclContext(CXXScopeSpec &SS,
return false;
}
-/// ActOnCXXGlobalScopeSpecifier - Return the object that represents the
-/// global scope ('::').
-Sema::CXXScopeTy *Sema::ActOnCXXGlobalScopeSpecifier(Scope *S,
- SourceLocation CCLoc) {
- return NestedNameSpecifier::GlobalSpecifier(Context);
+bool Sema::ActOnCXXGlobalScopeSpecifier(Scope *S, SourceLocation CCLoc,
+ CXXScopeSpec &SS) {
+ SS.MakeGlobal(Context, CCLoc);
+ return false;
}
/// \brief Determines whether the given declaration is an valid acceptable
@@ -352,22 +355,21 @@ bool Sema::isNonTypeNestedNameSpecifier(Scope *S, CXXScopeSpec &SS,
///
/// If ErrorRecoveryLookup is true, then this call is used to improve error
/// recovery. This means that it should not emit diagnostics, it should
-/// just return null on failure. It also means it should only return a valid
+/// just return true on failure. It also means it should only return a valid
/// scope if it *knows* that the result is correct. It should not return in a
-/// dependent context, for example.
-Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S,
- CXXScopeSpec &SS,
- SourceLocation IdLoc,
- SourceLocation CCLoc,
- IdentifierInfo &II,
- QualType ObjectType,
- NamedDecl *ScopeLookupResult,
- bool EnteringContext,
- bool ErrorRecoveryLookup) {
- NestedNameSpecifier *Prefix
- = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
-
- LookupResult Found(*this, &II, IdLoc, LookupNestedNameSpecifierName);
+/// dependent context, for example. Nor will it extend \p SS with the scope
+/// specifier.
+bool Sema::BuildCXXNestedNameSpecifier(Scope *S,
+ IdentifierInfo &Identifier,
+ SourceLocation IdentifierLoc,
+ SourceLocation CCLoc,
+ QualType ObjectType,
+ bool EnteringContext,
+ CXXScopeSpec &SS,
+ NamedDecl *ScopeLookupResult,
+ bool ErrorRecoveryLookup) {
+ LookupResult Found(*this, &Identifier, IdentifierLoc,
+ LookupNestedNameSpecifierName);
// Determine where to perform name lookup
DeclContext *LookupCtx = 0;
@@ -397,7 +399,7 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S,
// The declaration context must be complete.
if (!LookupCtx->isDependentContext() &&
RequireCompleteDeclContext(SS, LookupCtx))
- return 0;
+ return true;
LookupQualifiedName(Found, LookupCtx);
@@ -442,16 +444,14 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S,
!cast<CXXRecordDecl>(LookupCtx)->hasAnyDependentBases()))) {
// Don't speculate if we're just trying to improve error recovery.
if (ErrorRecoveryLookup)
- return 0;
+ return true;
// We were not able to compute the declaration context for a dependent
// base object type or prior nested-name-specifier, so this
// nested-name-specifier refers to an unknown specialization. Just build
// a dependent nested-name-specifier.
- if (!Prefix)
- return NestedNameSpecifier::Create(Context, &II);
-
- return NestedNameSpecifier::Create(Context, Prefix, &II);
+ SS.Extend(Context, &Identifier, IdentifierLoc, CCLoc);
+ return false;
}
// FIXME: Deal with ambiguities cleanly.
@@ -480,7 +480,7 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S,
<< ND->getDeclName();
} else {
Found.clear();
- Found.setLookupName(&II);
+ Found.setLookupName(&Identifier);
}
}
@@ -497,7 +497,8 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S,
// scope, reconstruct the result from the template instantiation itself.
NamedDecl *OuterDecl;
if (S) {
- LookupResult FoundOuter(*this, &II, IdLoc, LookupNestedNameSpecifierName);
+ LookupResult FoundOuter(*this, &Identifier, IdentifierLoc,
+ LookupNestedNameSpecifierName);
LookupName(FoundOuter, S);
OuterDecl = FoundOuter.getAsSingle<NamedDecl>();
} else
@@ -509,39 +510,72 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S,
!Context.hasSameType(
Context.getTypeDeclType(cast<TypeDecl>(OuterDecl)),
Context.getTypeDeclType(cast<TypeDecl>(SD))))) {
- if (ErrorRecoveryLookup)
- return 0;
-
- Diag(IdLoc, diag::err_nested_name_member_ref_lookup_ambiguous)
- << &II;
- Diag(SD->getLocation(), diag::note_ambig_member_ref_object_type)
- << ObjectType;
- Diag(OuterDecl->getLocation(), diag::note_ambig_member_ref_scope);
-
- // Fall through so that we'll pick the name we found in the object
- // type, since that's probably what the user wanted anyway.
- }
+ if (ErrorRecoveryLookup)
+ return true;
+
+ Diag(IdentifierLoc,
+ diag::err_nested_name_member_ref_lookup_ambiguous)
+ << &Identifier;
+ Diag(SD->getLocation(), diag::note_ambig_member_ref_object_type)
+ << ObjectType;
+ Diag(OuterDecl->getLocation(), diag::note_ambig_member_ref_scope);
+
+ // Fall through so that we'll pick the name we found in the object
+ // type, since that's probably what the user wanted anyway.
+ }
}
- if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(SD))
- return NestedNameSpecifier::Create(Context, Prefix, Namespace);
+ // If we're just performing this lookup for error-recovery purposes,
+ // don't extend the nested-name-specifier. Just return now.
+ if (ErrorRecoveryLookup)
+ return false;
+
+ if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(SD)) {
+ SS.Extend(Context, Namespace, IdentifierLoc, CCLoc);
+ return false;
+ }
- // FIXME: It would be nice to maintain the namespace alias name, then
- // see through that alias when resolving the nested-name-specifier down to
- // a declaration context.
- if (NamespaceAliasDecl *Alias = dyn_cast<NamespaceAliasDecl>(SD))
- return NestedNameSpecifier::Create(Context, Prefix,
- Alias->getNamespace());
+ if (NamespaceAliasDecl *Alias = dyn_cast<NamespaceAliasDecl>(SD)) {
+ SS.Extend(Context, Alias, IdentifierLoc, CCLoc);
+ return false;
+ }
QualType T = Context.getTypeDeclType(cast<TypeDecl>(SD));
- return NestedNameSpecifier::Create(Context, Prefix, false,
- T.getTypePtr());
+ TypeLocBuilder TLB;
+ if (isa<InjectedClassNameType>(T)) {
+ InjectedClassNameTypeLoc InjectedTL
+ = TLB.push<InjectedClassNameTypeLoc>(T);
+ InjectedTL.setNameLoc(IdentifierLoc);
+ } else if (isa<RecordDecl>(SD)) {
+ RecordTypeLoc RecordTL = TLB.push<RecordTypeLoc>(T);
+ RecordTL.setNameLoc(IdentifierLoc);
+ } else if (isa<TypedefDecl>(SD)) {
+ TypedefTypeLoc TypedefTL = TLB.push<TypedefTypeLoc>(T);
+ TypedefTL.setNameLoc(IdentifierLoc);
+ } else if (isa<EnumDecl>(SD)) {
+ EnumTypeLoc EnumTL = TLB.push<EnumTypeLoc>(T);
+ EnumTL.setNameLoc(IdentifierLoc);
+ } else if (isa<TemplateTypeParmDecl>(SD)) {
+ TemplateTypeParmTypeLoc TemplateTypeTL
+ = TLB.push<TemplateTypeParmTypeLoc>(T);
+ TemplateTypeTL.setNameLoc(IdentifierLoc);
+ } else {
+ assert(isa<UnresolvedUsingTypenameDecl>(SD) &&
+ "Unhandled TypeDecl node in nested-name-specifier");
+ UnresolvedUsingTypeLoc UnresolvedTL
+ = TLB.push<UnresolvedUsingTypeLoc>(T);
+ UnresolvedTL.setNameLoc(IdentifierLoc);
+ }
+
+ SS.Extend(Context, SourceLocation(), TLB.getTypeLocInContext(Context, T),
+ CCLoc);
+ return false;
}
// Otherwise, we have an error case. If we don't want diagnostics, just
// return an error now.
if (ErrorRecoveryLookup)
- return 0;
+ return true;
// If we didn't find anything during our lookup, try again with
// ordinary name lookup, which can help us produce better error
@@ -555,36 +589,34 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S,
if (!Found.empty())
DiagID = diag::err_expected_class_or_namespace;
else if (SS.isSet()) {
- Diag(IdLoc, diag::err_no_member) << &II << LookupCtx << SS.getRange();
- return 0;
+ Diag(IdentifierLoc, diag::err_no_member)
+ << &Identifier << LookupCtx << SS.getRange();
+ return true;
} else
DiagID = diag::err_undeclared_var_use;
if (SS.isSet())
- Diag(IdLoc, DiagID) << &II << SS.getRange();
+ Diag(IdentifierLoc, DiagID) << &Identifier << SS.getRange();
else
- Diag(IdLoc, DiagID) << &II;
+ Diag(IdentifierLoc, DiagID) << &Identifier;
- return 0;
+ return true;
}
-/// ActOnCXXNestedNameSpecifier - Called during parsing of a
-/// nested-name-specifier. e.g. for "foo::bar::" we parsed "foo::" and now
-/// we want to resolve "bar::". 'SS' is empty or the previously parsed
-/// nested-name part ("foo::"), 'IdLoc' is the source location of 'bar',
-/// 'CCLoc' is the location of '::' and 'II' is the identifier for 'bar'.
-/// Returns a CXXScopeTy* object representing the C++ scope.
-Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S,
- CXXScopeSpec &SS,
- SourceLocation IdLoc,
- SourceLocation CCLoc,
- IdentifierInfo &II,
- ParsedType ObjectTypePtr,
- bool EnteringContext) {
- return BuildCXXNestedNameSpecifier(S, SS, IdLoc, CCLoc, II,
- GetTypeFromParser(ObjectTypePtr),
- /*ScopeLookupResult=*/0, EnteringContext,
- false);
+bool Sema::ActOnCXXNestedNameSpecifier(Scope *S,
+ IdentifierInfo &Identifier,
+ SourceLocation IdentifierLoc,
+ SourceLocation CCLoc,
+ ParsedType ObjectType,
+ bool EnteringContext,
+ CXXScopeSpec &SS) {
+ if (SS.isInvalid())
+ return true;
+
+ return BuildCXXNestedNameSpecifier(S, Identifier, IdentifierLoc, CCLoc,
+ GetTypeFromParser(ObjectType),
+ EnteringContext, SS,
+ /*ScopeLookupResult=*/0, false);
}
/// IsInvalidUnlessNestedName - This method is used for error recovery
@@ -594,23 +626,71 @@ Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S,
///
/// The arguments are the same as those passed to ActOnCXXNestedNameSpecifier.
bool Sema::IsInvalidUnlessNestedName(Scope *S, CXXScopeSpec &SS,
- IdentifierInfo &II, ParsedType ObjectType,
+ IdentifierInfo &Identifier,
+ SourceLocation IdentifierLoc,
+ SourceLocation ColonLoc,
+ ParsedType ObjectType,
bool EnteringContext) {
- return BuildCXXNestedNameSpecifier(S, SS, SourceLocation(), SourceLocation(),
- II, GetTypeFromParser(ObjectType),
- /*ScopeLookupResult=*/0, EnteringContext,
- true);
+ if (SS.isInvalid())
+ return false;
+
+ return !BuildCXXNestedNameSpecifier(S, Identifier, IdentifierLoc, ColonLoc,
+ GetTypeFromParser(ObjectType),
+ EnteringContext, SS,
+ /*ScopeLookupResult=*/0, true);
}
-Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S,
- const CXXScopeSpec &SS,
- ParsedType Ty,
- SourceRange TypeRange,
- SourceLocation CCLoc) {
- NestedNameSpecifier *Prefix = SS.getScopeRep();
- QualType T = GetTypeFromParser(Ty);
- return NestedNameSpecifier::Create(Context, Prefix, /*FIXME:*/false,
- T.getTypePtr());
+bool Sema::ActOnCXXNestedNameSpecifier(Scope *S,
+ ParsedType Type,
+ SourceLocation CCLoc,
+ CXXScopeSpec &SS) {
+ if (SS.isInvalid())
+ return true;
+
+ TypeSourceInfo *TSInfo;
+ QualType T = GetTypeFromParser(Type, &TSInfo);
+ if (T.isNull())
+ return true;
+
+ assert(TSInfo && "Not TypeSourceInfo in nested-name-specifier?");
+ // FIXME: location of the 'template' keyword?
+ SS.Extend(Context, SourceLocation(), TSInfo->getTypeLoc(), CCLoc);
+ return false;
+}
+
+namespace {
+ /// \brief A structure that stores a nested-name-specifier annotation,
+ /// including both the nested-name-specifier
+ struct NestedNameSpecifierAnnotation {
+ NestedNameSpecifier *NNS;
+ };
+}
+
+void *Sema::SaveNestedNameSpecifierAnnotation(CXXScopeSpec &SS) {
+ if (SS.isEmpty() || SS.isInvalid())
+ return 0;
+
+ void *Mem = Context.Allocate((sizeof(NestedNameSpecifierAnnotation) +
+ SS.location_size()),
+ llvm::alignOf<NestedNameSpecifierAnnotation>());
+ NestedNameSpecifierAnnotation *Annotation
+ = new (Mem) NestedNameSpecifierAnnotation;
+ Annotation->NNS = SS.getScopeRep();
+ memcpy(Annotation + 1, SS.location_data(), SS.location_size());
+ return Annotation;
+}
+
+void Sema::RestoreNestedNameSpecifierAnnotation(void *AnnotationPtr,
+ SourceRange AnnotationRange,
+ CXXScopeSpec &SS) {
+ if (!AnnotationPtr) {
+ SS.SetInvalid(AnnotationRange);
+ return;
+ }
+
+ NestedNameSpecifierAnnotation *Annotation
+ = static_cast<NestedNameSpecifierAnnotation *>(AnnotationPtr);
+ SS.Adopt(NestedNameSpecifierLoc(Annotation->NNS, Annotation + 1));
}
bool Sema::ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
@@ -636,6 +716,7 @@ bool Sema::ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
switch (Qualifier->getKind()) {
case NestedNameSpecifier::Global:
case NestedNameSpecifier::Namespace:
+ case NestedNameSpecifier::NamespaceAlias:
// These are always namespace scopes. We never want to enter a
// namespace scope from anything but a file context.
return CurContext->getRedeclContext()->isFileContext();
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp
index 24cdaef..3ffa748 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp
@@ -66,6 +66,26 @@ bool Sema::CheckablePrintfAttr(const FormatAttr *Format, CallExpr *TheCall) {
return false;
}
+/// Checks that a call expression's argument count is the desired number.
+/// This is useful when doing custom type-checking. Returns true on error.
+static bool checkArgCount(Sema &S, CallExpr *call, unsigned desiredArgCount) {
+ unsigned argCount = call->getNumArgs();
+ if (argCount == desiredArgCount) return false;
+
+ if (argCount < desiredArgCount)
+ return S.Diag(call->getLocEnd(), diag::err_typecheck_call_too_few_args)
+ << 0 /*function call*/ << desiredArgCount << argCount
+ << call->getSourceRange();
+
+ // Highlight all the excess arguments.
+ SourceRange range(call->getArg(desiredArgCount)->getLocStart(),
+ call->getArg(argCount - 1)->getLocEnd());
+
+ return S.Diag(range.getBegin(), diag::err_typecheck_call_too_many_args)
+ << 0 /*function call*/ << desiredArgCount << argCount
+ << call->getArg(1)->getSourceRange();
+}
+
ExprResult
Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
ExprResult TheCallResult(Owned(TheCall));
@@ -137,15 +157,14 @@ Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
if (SemaBuiltinLongjmp(TheCall))
return ExprError();
break;
+
+ case Builtin::BI__builtin_classify_type:
+ if (checkArgCount(*this, TheCall, 1)) return true;
+ TheCall->setType(Context.IntTy);
+ break;
case Builtin::BI__builtin_constant_p:
- if (TheCall->getNumArgs() == 0)
- return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args)
- << 0 /*function call*/ << 1 << 0 << TheCall->getSourceRange();
- if (TheCall->getNumArgs() > 1)
- return Diag(TheCall->getArg(1)->getLocStart(),
- diag::err_typecheck_call_too_many_args)
- << 0 /*function call*/ << 1 << TheCall->getNumArgs()
- << TheCall->getArg(1)->getSourceRange();
+ if (checkArgCount(*this, TheCall, 1)) return true;
+ TheCall->setType(Context.IntTy);
break;
case Builtin::BI__sync_fetch_and_add:
case Builtin::BI__sync_fetch_and_sub:
@@ -875,7 +894,7 @@ bool Sema::SemaBuiltinLongjmp(CallExpr *TheCall) {
return false;
}
-// Handle i > 1 ? "x" : "y", recursivelly
+// Handle i > 1 ? "x" : "y", recursively.
bool Sema::SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall,
bool HasVAListArg,
unsigned format_idx, unsigned firstDataArg,
@@ -918,6 +937,12 @@ bool Sema::SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall,
}
return false;
+ case Stmt::PredefinedExprClass:
+ // While __func__, etc., are technically not string literals, they
+ // cannot contain format specifiers and thus are not a security
+ // liability.
+ return true;
+
case Stmt::DeclRefExprClass: {
const DeclRefExpr *DR = cast<DeclRefExpr>(E);
@@ -2896,6 +2921,17 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
return DiagnoseImpCast(S, E, T, CC, DiagID);
}
+ // Diagnose conversions between different enumeration types.
+ if (const EnumType *SourceEnum = Source->getAs<EnumType>())
+ if (const EnumType *TargetEnum = Target->getAs<EnumType>())
+ if ((SourceEnum->getDecl()->getIdentifier() ||
+ SourceEnum->getDecl()->getTypedefForAnonDecl()) &&
+ (TargetEnum->getDecl()->getIdentifier() ||
+ TargetEnum->getDecl()->getTypedefForAnonDecl()) &&
+ SourceEnum != TargetEnum)
+ return DiagnoseImpCast(S, E, T, CC,
+ diag::warn_impcast_different_enum_types);
+
return;
}
@@ -3147,7 +3183,7 @@ void Sema::CheckArrayAccess(const clang::ArraySubscriptExpr *E) {
if (!IndexExpr->isIntegerConstantExpr(index, Context))
return;
- if (!index.isNegative()) {
+ if (index.isUnsigned() || !index.isNegative()) {
llvm::APInt size = ArrayTy->getSize();
if (!size.isStrictlyPositive())
return;
@@ -3159,12 +3195,15 @@ void Sema::CheckArrayAccess(const clang::ArraySubscriptExpr *E) {
if (index.slt(size))
return;
- Diag(E->getBase()->getLocStart(), diag::warn_array_index_exceeds_bounds)
- << index.toString(10, true) << size.toString(10, true)
- << IndexExpr->getSourceRange();
+ DiagRuntimeBehavior(E->getBase()->getLocStart(), BaseExpr,
+ PDiag(diag::warn_array_index_exceeds_bounds)
+ << index.toString(10, true) << size.toString(10, true)
+ << IndexExpr->getSourceRange());
} else {
- Diag(E->getBase()->getLocStart(), diag::warn_array_index_precedes_bounds)
- << index.toString(10, true) << IndexExpr->getSourceRange();
+ DiagRuntimeBehavior(E->getBase()->getLocStart(), BaseExpr,
+ PDiag(diag::warn_array_index_precedes_bounds)
+ << index.toString(10, true)
+ << IndexExpr->getSourceRange());
}
const NamedDecl *ND = NULL;
@@ -3173,7 +3212,8 @@ void Sema::CheckArrayAccess(const clang::ArraySubscriptExpr *E) {
if (const MemberExpr *ME = dyn_cast<MemberExpr>(BaseExpr))
ND = dyn_cast<NamedDecl>(ME->getMemberDecl());
if (ND)
- Diag(ND->getLocStart(), diag::note_array_index_out_of_bounds)
- << ND->getDeclName();
+ DiagRuntimeBehavior(ND->getLocStart(), BaseExpr,
+ PDiag(diag::note_array_index_out_of_bounds)
+ << ND->getDeclName());
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp
index dd30c12..d6efd7a 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp
@@ -2895,8 +2895,7 @@ isOutOfScopePreviousDeclaration(NamedDecl *PrevDecl, DeclContext *DC,
static void SetNestedNameSpecifier(DeclaratorDecl *DD, Declarator &D) {
CXXScopeSpec &SS = D.getCXXScopeSpec();
if (!SS.isSet()) return;
- DD->setQualifierInfo(static_cast<NestedNameSpecifier*>(SS.getScopeRep()),
- SS.getRange());
+ DD->setQualifierInfo(SS.getWithLocInContext(DD->getASTContext()));
}
NamedDecl*
@@ -3026,11 +3025,11 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
NewVD = VarDecl::Create(Context, DC, D.getIdentifierLoc(),
II, R, TInfo, SC, SCAsWritten);
- // If this decl has an auto type in need of deduction, mark the VarDecl so
- // we can diagnose uses of it in its own initializer.
- if (D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto) {
- NewVD->setParsingAutoInit(R->getContainedAutoType());
- }
+ // If this decl has an auto type in need of deduction, make a note of the
+ // Decl so we can diagnose uses of it in its own initializer.
+ if (D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto &&
+ R->getContainedAutoType())
+ ParsingInitForAutoVars.insert(NewVD);
if (D.isInvalidType() || Invalid)
NewVD->setInvalidDecl();
@@ -4534,8 +4533,6 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
// C++0x [decl.spec.auto]p6. Deduce the type which 'auto' stands in for.
if (TypeMayContainAuto && VDecl->getType()->getContainedAutoType()) {
- VDecl->setParsingAutoInit(false);
-
QualType DeducedType;
if (!DeduceAutoType(VDecl->getType(), Init, DeducedType)) {
Diag(VDecl->getLocation(), diag::err_auto_var_deduction_failure)
@@ -4800,9 +4797,8 @@ void Sema::ActOnInitializerError(Decl *D) {
if (!VD) return;
// Auto types are meaningless if we can't make sense of the initializer.
- if (VD->isParsingAutoInit()) {
- VD->setParsingAutoInit(false);
- VD->setInvalidDecl();
+ if (ParsingInitForAutoVars.count(D)) {
+ D->setInvalidDecl();
return;
}
@@ -4840,8 +4836,6 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl,
// C++0x [dcl.spec.auto]p3
if (TypeMayContainAuto && Type->getContainedAutoType()) {
- Var->setParsingAutoInit(false);
-
Diag(Var->getLocation(), diag::err_auto_var_requires_init)
<< Var->getDeclName() << Type;
Var->setInvalidDecl();
@@ -5044,6 +5038,14 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
FinalizeVarWithDestructor(var, recordType);
}
+/// FinalizeDeclaration - called by ParseDeclarationAfterDeclarator to perform
+/// any semantic actions necessary after any initializer has been attached.
+void
+Sema::FinalizeDeclaration(Decl *ThisDecl) {
+ // Note that we are no longer parsing the initializer for this declaration.
+ ParsingInitForAutoVars.erase(ThisDecl);
+}
+
Sema::DeclGroupPtrTy
Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
Decl **Group, unsigned NumDecls) {
@@ -5052,6 +5054,19 @@ Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
if (DS.isTypeSpecOwned())
Decls.push_back(DS.getRepAsDecl());
+ for (unsigned i = 0; i != NumDecls; ++i)
+ if (Decl *D = Group[i])
+ Decls.push_back(D);
+
+ return BuildDeclaratorGroup(Decls.data(), Decls.size(),
+ DS.getTypeSpecType() == DeclSpec::TST_auto);
+}
+
+/// BuildDeclaratorGroup - convert a list of declarations into a declaration
+/// group, performing any necessary semantic checking.
+Sema::DeclGroupPtrTy
+Sema::BuildDeclaratorGroup(Decl **Group, unsigned NumDecls,
+ bool TypeMayContainAuto) {
// C++0x [dcl.spec.auto]p7:
// If the type deduced for the template parameter U is not the same in each
// deduction, the program is ill-formed.
@@ -5059,14 +5074,16 @@ Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
// between the deduced type U and the deduced type which 'auto' stands for.
// auto a = 0, b = { 1, 2, 3 };
// is legal because the deduced type U is 'int' in both cases.
- bool TypeContainsAuto = DS.getTypeSpecType() == DeclSpec::TST_auto;
- if (TypeContainsAuto && NumDecls > 1) {
+ if (TypeMayContainAuto && NumDecls > 1) {
QualType Deduced;
CanQualType DeducedCanon;
VarDecl *DeducedDecl = 0;
for (unsigned i = 0; i != NumDecls; ++i) {
if (VarDecl *D = dyn_cast<VarDecl>(Group[i])) {
AutoType *AT = D->getType()->getContainedAutoType();
+ // Don't reissue diagnostics when instantiating a template.
+ if (AT && D->isInvalidDecl())
+ break;
if (AT && AT->isDeduced()) {
QualType U = AT->getDeducedType();
CanQualType UCanon = Context.getCanonicalType(U);
@@ -5075,11 +5092,13 @@ Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
DeducedCanon = UCanon;
DeducedDecl = D;
} else if (DeducedCanon != UCanon) {
- Diag(DS.getTypeSpecTypeLoc(), diag::err_auto_different_deductions)
+ Diag(D->getTypeSourceInfo()->getTypeLoc().getBeginLoc(),
+ diag::err_auto_different_deductions)
<< Deduced << DeducedDecl->getDeclName()
<< U << D->getDeclName()
<< DeducedDecl->getInit()->getSourceRange()
<< D->getInit()->getSourceRange();
+ D->setInvalidDecl();
break;
}
}
@@ -5087,12 +5106,7 @@ Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
}
}
- for (unsigned i = 0; i != NumDecls; ++i)
- if (Decl *D = Group[i])
- Decls.push_back(D);
-
- return DeclGroupPtrTy::make(DeclGroupRef::Create(Context,
- Decls.data(), Decls.size()));
+ return DeclGroupPtrTy::make(DeclGroupRef::Create(Context, Group, NumDecls));
}
@@ -5537,6 +5551,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
FD = dyn_cast_or_null<FunctionDecl>(dcl);
sema::AnalysisBasedWarnings::Policy WP = AnalysisWarnings.getDefaultPolicy();
+ sema::AnalysisBasedWarnings::Policy *ActivePolicy = 0;
if (FD) {
FD->setBody(Body);
@@ -5605,13 +5620,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
else if (!isa<FunctionTemplateDecl>(dcl)) {
// Since the body is valid, issue any analysis-based warnings that are
// enabled.
- QualType ResultType;
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(dcl)) {
- AnalysisWarnings.IssueWarnings(WP, FD);
- } else {
- ObjCMethodDecl *MD = cast<ObjCMethodDecl>(dcl);
- AnalysisWarnings.IssueWarnings(WP, MD);
- }
+ ActivePolicy = &WP;
}
assert(ExprTemporaries.empty() && "Leftover temporaries in function");
@@ -5620,7 +5629,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
if (!IsInstantiation)
PopDeclContext();
- PopFunctionOrBlockScope();
+ PopFunctionOrBlockScope(ActivePolicy, dcl);
// If any errors have occurred, clear out any temporaries that may have
// been leftover. This ensures that these temporaries won't be picked up for
@@ -6435,9 +6444,7 @@ CreateNewDecl:
// Maybe add qualifier info.
if (SS.isNotEmpty()) {
if (SS.isSet()) {
- NestedNameSpecifier *NNS
- = static_cast<NestedNameSpecifier*>(SS.getScopeRep());
- New->setQualifierInfo(NNS, SS.getRange());
+ New->setQualifierInfo(SS.getWithLocInContext(Context));
if (NumMatchedTemplateParamLists > 0) {
New->setTemplateParameterListsInfo(Context,
NumMatchedTemplateParamLists,
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp
index cbc940f..893cf6a 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp
@@ -1014,54 +1014,48 @@ static void HandleDestructorAttr(Decl *d, const AttributeList &Attr, Sema &S) {
}
static void HandleDeprecatedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
- // check the attribute arguments.
- int noArgs = Attr.getNumArgs();
- if (noArgs > 1) {
+ unsigned NumArgs = Attr.getNumArgs();
+ if (NumArgs > 1) {
S.Diag(Attr.getLoc(),
diag::err_attribute_wrong_number_arguments) << "0 or 1";
return;
}
+
// Handle the case where deprecated attribute has a text message.
- StringLiteral *SE;
- if (noArgs == 1) {
- Expr *ArgExpr = Attr.getArg(0);
- SE = dyn_cast<StringLiteral>(ArgExpr);
+ llvm::StringRef Str;
+ if (NumArgs == 1) {
+ StringLiteral *SE = dyn_cast<StringLiteral>(Attr.getArg(0));
if (!SE) {
- S.Diag(ArgExpr->getLocStart(),
- diag::err_attribute_not_string) << "deprecated";
+ S.Diag(Attr.getArg(0)->getLocStart(), diag::err_attribute_not_string)
+ << "deprecated";
return;
}
+ Str = SE->getString();
}
- else
- SE = StringLiteral::CreateEmpty(S.Context, 1);
- d->addAttr(::new (S.Context) DeprecatedAttr(Attr.getLoc(), S.Context,
- SE->getString()));
+ d->addAttr(::new (S.Context) DeprecatedAttr(Attr.getLoc(), S.Context, Str));
}
static void HandleUnavailableAttr(Decl *d, const AttributeList &Attr, Sema &S) {
- // check the attribute arguments.
- int noArgs = Attr.getNumArgs();
- if (noArgs > 1) {
+ unsigned NumArgs = Attr.getNumArgs();
+ if (NumArgs > 1) {
S.Diag(Attr.getLoc(),
diag::err_attribute_wrong_number_arguments) << "0 or 1";
return;
}
+
// Handle the case where unavailable attribute has a text message.
- StringLiteral *SE;
- if (noArgs == 1) {
- Expr *ArgExpr = Attr.getArg(0);
- SE = dyn_cast<StringLiteral>(ArgExpr);
+ llvm::StringRef Str;
+ if (NumArgs == 1) {
+ StringLiteral *SE = dyn_cast<StringLiteral>(Attr.getArg(0));
if (!SE) {
- S.Diag(ArgExpr->getLocStart(),
+ S.Diag(Attr.getArg(0)->getLocStart(),
diag::err_attribute_not_string) << "unavailable";
return;
}
+ Str = SE->getString();
}
- else
- SE = StringLiteral::CreateEmpty(S.Context, 1);
- d->addAttr(::new (S.Context) UnavailableAttr(Attr.getLoc(), S.Context,
- SE->getString()));
+ d->addAttr(::new (S.Context) UnavailableAttr(Attr.getLoc(), S.Context, Str));
}
static void HandleVisibilityAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -2847,7 +2841,7 @@ NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II) {
FD->getType(), FD->getTypeSourceInfo());
if (FD->getQualifier()) {
FunctionDecl *NewFD = cast<FunctionDecl>(NewD);
- NewFD->setQualifierInfo(FD->getQualifier(), FD->getQualifierRange());
+ NewFD->setQualifierInfo(FD->getQualifierLoc());
}
} else if (VarDecl *VD = dyn_cast<VarDecl>(ND)) {
NewD = VarDecl::Create(VD->getASTContext(), VD->getDeclContext(),
@@ -2857,7 +2851,7 @@ NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II) {
VD->getStorageClassAsWritten());
if (VD->getQualifier()) {
VarDecl *NewVD = cast<VarDecl>(NewD);
- NewVD->setQualifierInfo(VD->getQualifier(), VD->getQualifierRange());
+ NewVD->setQualifierInfo(VD->getQualifierLoc());
}
}
return NewD;
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp
index e8abab8..f483262 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp
@@ -1078,6 +1078,8 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
if (Deleted) // FIXME: Source location is not very good.
SetDeclDeleted(Member, D.getSourceRange().getBegin());
+ FinalizeDeclaration(Member);
+
if (isInstField)
FieldCollector->Add(cast<FieldDecl>(Member));
return Member;
@@ -2586,6 +2588,9 @@ struct CheckAbstractUsage {
void Check(FunctionProtoTypeLoc TL, Sema::AbstractDiagSelID Sel) {
Visit(TL.getResultLoc(), Sema::AbstractReturnType);
for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) {
+ if (!TL.getArg(I))
+ continue;
+
TypeSourceInfo *TSI = TL.getArg(I)->getTypeSourceInfo();
if (TSI) Visit(TSI->getTypeLoc(), Sema::AbstractParamType);
}
@@ -3618,8 +3623,7 @@ Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope,
= UsingDirectiveDecl::Create(Context, CurContext,
/* 'using' */ LBrace,
/* 'namespace' */ SourceLocation(),
- /* qualifier */ SourceRange(),
- /* NNS */ NULL,
+ /* qualifier */ NestedNameSpecifierLoc(),
/* identifier */ SourceLocation(),
Namespc,
/* Ancestor */ CurContext);
@@ -3763,8 +3767,7 @@ Decl *Sema::ActOnUsingDirective(Scope *S,
CommonAncestor = CommonAncestor->getParent();
UDir = UsingDirectiveDecl::Create(Context, CurContext, UsingLoc, NamespcLoc,
- SS.getRange(),
- (NestedNameSpecifier *)SS.getScopeRep(),
+ SS.getWithLocInContext(Context),
IdentLoc, Named, CommonAncestor);
PushUsingDirective(S, UDir);
} else {
@@ -3914,16 +3917,16 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig,
if (OrigDC == CurContext) {
Diag(Using->getLocation(),
diag::err_using_decl_nested_name_specifier_is_current_class)
- << Using->getNestedNameRange();
+ << Using->getQualifierLoc().getSourceRange();
Diag(Orig->getLocation(), diag::note_using_decl_target);
return true;
}
- Diag(Using->getNestedNameRange().getBegin(),
+ Diag(Using->getQualifierLoc().getBeginLoc(),
diag::err_using_decl_nested_name_specifier_is_not_base_class)
- << Using->getTargetNestedNameDecl()
+ << Using->getQualifier()
<< cast<CXXRecordDecl>(CurContext)
- << Using->getNestedNameRange();
+ << Using->getQualifierLoc().getSourceRange();
Diag(Orig->getLocation(), diag::note_using_decl_target);
return true;
}
@@ -4129,8 +4132,6 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
LookupQualifiedName(Previous, CurContext);
}
- NestedNameSpecifier *NNS = SS.getScopeRep();
-
// Check for invalid redeclarations.
if (CheckUsingDeclRedeclaration(UsingLoc, IsTypeName, SS, IdentLoc, Previous))
return 0;
@@ -4141,22 +4142,21 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
DeclContext *LookupContext = computeDeclContext(SS);
NamedDecl *D;
+ NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context);
if (!LookupContext) {
if (IsTypeName) {
// FIXME: not all declaration name kinds are legal here
D = UnresolvedUsingTypenameDecl::Create(Context, CurContext,
UsingLoc, TypenameLoc,
- SS.getRange(), NNS,
+ QualifierLoc,
IdentLoc, NameInfo.getName());
} else {
- D = UnresolvedUsingValueDecl::Create(Context, CurContext,
- UsingLoc, SS.getRange(),
- NNS, NameInfo);
+ D = UnresolvedUsingValueDecl::Create(Context, CurContext, UsingLoc,
+ QualifierLoc, NameInfo);
}
} else {
- D = UsingDecl::Create(Context, CurContext,
- SS.getRange(), UsingLoc, NNS, NameInfo,
- IsTypeName);
+ D = UsingDecl::Create(Context, CurContext, UsingLoc, QualifierLoc,
+ NameInfo, IsTypeName);
}
D->setAccess(AS);
CurContext->addDecl(D);
@@ -4247,7 +4247,7 @@ bool Sema::CheckInheritedConstructorUsingDecl(UsingDecl *UD) {
return true;
}
- const Type *SourceType = UD->getTargetNestedNameDecl()->getAsType();
+ const Type *SourceType = UD->getQualifier()->getAsType();
assert(SourceType &&
"Using decl naming constructor doesn't have type in scope spec.");
CXXRecordDecl *TargetClass = cast<CXXRecordDecl>(CurContext);
@@ -4304,15 +4304,15 @@ bool Sema::CheckUsingDeclRedeclaration(SourceLocation UsingLoc,
NestedNameSpecifier *DQual;
if (UsingDecl *UD = dyn_cast<UsingDecl>(D)) {
DTypename = UD->isTypeName();
- DQual = UD->getTargetNestedNameDecl();
+ DQual = UD->getQualifier();
} else if (UnresolvedUsingValueDecl *UD
= dyn_cast<UnresolvedUsingValueDecl>(D)) {
DTypename = false;
- DQual = UD->getTargetNestedNameSpecifier();
+ DQual = UD->getQualifier();
} else if (UnresolvedUsingTypenameDecl *UD
= dyn_cast<UnresolvedUsingTypenameDecl>(D)) {
DTypename = true;
- DQual = UD->getTargetNestedNameSpecifier();
+ DQual = UD->getQualifier();
} else continue;
// using decls differ if one says 'typename' and the other doesn't.
@@ -4542,8 +4542,7 @@ Decl *Sema::ActOnNamespaceAliasDef(Scope *S,
NamespaceAliasDecl *AliasDecl =
NamespaceAliasDecl::Create(Context, CurContext, NamespaceLoc, AliasLoc,
- Alias, SS.getRange(),
- (NestedNameSpecifier *)SS.getScopeRep(),
+ Alias, SS.getWithLocInContext(Context),
IdentLoc, R.getFoundDecl());
PushOnScopeChains(AliasDecl, S);
@@ -5080,9 +5079,10 @@ BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T,
// reference to operator=; this is required to suppress the virtual
// call mechanism.
CXXScopeSpec SS;
- SS.setRange(Loc);
- SS.setScopeRep(NestedNameSpecifier::Create(S.Context, 0, false,
- T.getTypePtr()));
+ SS.MakeTrivial(S.Context,
+ NestedNameSpecifier::Create(S.Context, 0, false,
+ T.getTypePtr()),
+ Loc);
// Create the reference to operator=.
ExprResult OpEqualRef
@@ -5972,8 +5972,6 @@ void Sema::AddCXXDirectInitializerToDecl(Decl *RealDecl,
// C++0x [decl.spec.auto]p6. Deduce the type which 'auto' stands in for.
if (TypeMayContainAuto && VDecl->getType()->getContainedAutoType()) {
- VDecl->setParsingAutoInit(false);
-
// FIXME: n3225 doesn't actually seem to indicate this is ill-formed
if (Exprs.size() > 1) {
Diag(Exprs.get()[1]->getSourceRange().getBegin(),
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp
index 66f6f2b..652318f 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp
@@ -856,9 +856,21 @@ static SourceRange getTypeRange(TypeSourceInfo *TSI) {
static void CheckMethodOverrideReturn(Sema &S,
ObjCMethodDecl *MethodImpl,
- ObjCMethodDecl *MethodIface) {
+ ObjCMethodDecl *MethodDecl,
+ bool IsProtocolMethodDecl) {
+ if (IsProtocolMethodDecl &&
+ (MethodDecl->getObjCDeclQualifier() !=
+ MethodImpl->getObjCDeclQualifier())) {
+ S.Diag(MethodImpl->getLocation(),
+ diag::warn_conflicting_ret_type_modifiers)
+ << MethodImpl->getDeclName()
+ << getTypeRange(MethodImpl->getResultTypeSourceInfo());
+ S.Diag(MethodDecl->getLocation(), diag::note_previous_declaration)
+ << getTypeRange(MethodDecl->getResultTypeSourceInfo());
+ }
+
if (S.Context.hasSameUnqualifiedType(MethodImpl->getResultType(),
- MethodIface->getResultType()))
+ MethodDecl->getResultType()))
return;
unsigned DiagID = diag::warn_conflicting_ret_types;
@@ -868,7 +880,7 @@ static void CheckMethodOverrideReturn(Sema &S,
if (const ObjCObjectPointerType *ImplPtrTy =
MethodImpl->getResultType()->getAs<ObjCObjectPointerType>()) {
if (const ObjCObjectPointerType *IfacePtrTy =
- MethodIface->getResultType()->getAs<ObjCObjectPointerType>()) {
+ MethodDecl->getResultType()->getAs<ObjCObjectPointerType>()) {
// Allow non-matching return types as long as they don't violate
// the principle of substitutability. Specifically, we permit
// return types that are subclasses of the declared return type,
@@ -882,20 +894,33 @@ static void CheckMethodOverrideReturn(Sema &S,
S.Diag(MethodImpl->getLocation(), DiagID)
<< MethodImpl->getDeclName()
- << MethodIface->getResultType()
+ << MethodDecl->getResultType()
<< MethodImpl->getResultType()
<< getTypeRange(MethodImpl->getResultTypeSourceInfo());
- S.Diag(MethodIface->getLocation(), diag::note_previous_definition)
- << getTypeRange(MethodIface->getResultTypeSourceInfo());
+ S.Diag(MethodDecl->getLocation(), diag::note_previous_definition)
+ << getTypeRange(MethodDecl->getResultTypeSourceInfo());
}
static void CheckMethodOverrideParam(Sema &S,
ObjCMethodDecl *MethodImpl,
- ObjCMethodDecl *MethodIface,
+ ObjCMethodDecl *MethodDecl,
ParmVarDecl *ImplVar,
- ParmVarDecl *IfaceVar) {
+ ParmVarDecl *IfaceVar,
+ bool IsProtocolMethodDecl) {
+ if (IsProtocolMethodDecl &&
+ (ImplVar->getObjCDeclQualifier() !=
+ IfaceVar->getObjCDeclQualifier())) {
+ S.Diag(ImplVar->getLocation(),
+ diag::warn_conflicting_param_modifiers)
+ << getTypeRange(ImplVar->getTypeSourceInfo())
+ << MethodImpl->getDeclName();
+ S.Diag(IfaceVar->getLocation(), diag::note_previous_declaration)
+ << getTypeRange(IfaceVar->getTypeSourceInfo());
+ }
+
QualType ImplTy = ImplVar->getType();
QualType IfaceTy = IfaceVar->getType();
+
if (S.Context.hasSameUnqualifiedType(ImplTy, IfaceTy))
return;
@@ -927,17 +952,20 @@ static void CheckMethodOverrideParam(Sema &S,
void Sema::WarnConflictingTypedMethods(ObjCMethodDecl *ImpMethodDecl,
- ObjCMethodDecl *IntfMethodDecl) {
- CheckMethodOverrideReturn(*this, ImpMethodDecl, IntfMethodDecl);
+ ObjCMethodDecl *MethodDecl,
+ bool IsProtocolMethodDecl) {
+ CheckMethodOverrideReturn(*this, ImpMethodDecl, MethodDecl,
+ IsProtocolMethodDecl);
for (ObjCMethodDecl::param_iterator IM = ImpMethodDecl->param_begin(),
- IF = IntfMethodDecl->param_begin(), EM = ImpMethodDecl->param_end();
+ IF = MethodDecl->param_begin(), EM = ImpMethodDecl->param_end();
IM != EM; ++IM, ++IF)
- CheckMethodOverrideParam(*this, ImpMethodDecl, IntfMethodDecl, *IM, *IF);
+ CheckMethodOverrideParam(*this, ImpMethodDecl, MethodDecl, *IM, *IF,
+ IsProtocolMethodDecl);
- if (ImpMethodDecl->isVariadic() != IntfMethodDecl->isVariadic()) {
+ if (ImpMethodDecl->isVariadic() != MethodDecl->isVariadic()) {
Diag(ImpMethodDecl->getLocation(), diag::warn_conflicting_variadic);
- Diag(IntfMethodDecl->getLocation(), diag::note_previous_declaration);
+ Diag(MethodDecl->getLocation(), diag::note_previous_declaration);
}
}
@@ -1061,13 +1089,14 @@ void Sema::MatchAllMethodDeclarations(const llvm::DenseSet<Selector> &InsMap,
} else {
ObjCMethodDecl *ImpMethodDecl =
IMPDecl->getInstanceMethod((*I)->getSelector());
- ObjCMethodDecl *IntfMethodDecl =
+ ObjCMethodDecl *MethodDecl =
CDecl->getInstanceMethod((*I)->getSelector());
- assert(IntfMethodDecl &&
- "IntfMethodDecl is null in ImplMethodsVsClassMethods");
+ assert(MethodDecl &&
+ "MethodDecl is null in ImplMethodsVsClassMethods");
// ImpMethodDecl may be null as in a @dynamic property.
if (ImpMethodDecl)
- WarnConflictingTypedMethods(ImpMethodDecl, IntfMethodDecl);
+ WarnConflictingTypedMethods(ImpMethodDecl, MethodDecl,
+ isa<ObjCProtocolDecl>(CDecl));
}
}
@@ -1085,9 +1114,10 @@ void Sema::MatchAllMethodDeclarations(const llvm::DenseSet<Selector> &InsMap,
} else {
ObjCMethodDecl *ImpMethodDecl =
IMPDecl->getClassMethod((*I)->getSelector());
- ObjCMethodDecl *IntfMethodDecl =
+ ObjCMethodDecl *MethodDecl =
CDecl->getClassMethod((*I)->getSelector());
- WarnConflictingTypedMethods(ImpMethodDecl, IntfMethodDecl);
+ WarnConflictingTypedMethods(ImpMethodDecl, MethodDecl,
+ isa<ObjCProtocolDecl>(CDecl));
}
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp
index 65b57c3..415ab3f 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp
@@ -76,12 +76,10 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc,
}
// See if this is an auto-typed variable whose initializer we are parsing.
- if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
- if (VD->isParsingAutoInit()) {
- Diag(Loc, diag::err_auto_variable_cannot_appear_in_own_initializer)
- << D->getDeclName();
- return true;
- }
+ if (ParsingInitForAutoVars.count(D)) {
+ Diag(Loc, diag::err_auto_variable_cannot_appear_in_own_initializer)
+ << D->getDeclName();
+ return true;
}
// See if the decl is deprecated.
@@ -389,13 +387,13 @@ bool Sema::DefaultVariadicArgumentPromotion(Expr *&Expr, VariadicCallType CT,
return false;
if (Expr->getType()->isObjCObjectType() &&
- DiagRuntimeBehavior(Expr->getLocStart(),
+ DiagRuntimeBehavior(Expr->getLocStart(), 0,
PDiag(diag::err_cannot_pass_objc_interface_to_vararg)
<< Expr->getType() << CT))
return true;
if (!Expr->getType()->isPODType() &&
- DiagRuntimeBehavior(Expr->getLocStart(),
+ DiagRuntimeBehavior(Expr->getLocStart(), 0,
PDiag(diag::warn_cannot_pass_non_pod_arg_to_vararg)
<< Expr->getType() << CT))
return true;
@@ -1675,20 +1673,6 @@ ExprResult Sema::ActOnIdExpression(Scope *S,
// This is guaranteed from this point on.
assert(!R.empty() || ADL);
- if (VarDecl *Var = R.getAsSingle<VarDecl>()) {
- if (getLangOptions().ObjCNonFragileABI && IvarLookupFollowUp &&
- !(getLangOptions().ObjCDefaultSynthProperties &&
- getLangOptions().ObjCNonFragileABI2) &&
- Var->isFileVarDecl()) {
- ObjCPropertyDecl *Property = canSynthesizeProvisionalIvar(II);
- if (Property) {
- Diag(NameLoc, diag::warn_ivar_variable_conflict) << Var->getDeclName();
- Diag(Property->getLocation(), diag::note_property_declare);
- Diag(Var->getLocation(), diag::note_global_declared_at);
- }
- }
- }
-
// Check whether this might be a C++ implicit instance member access.
// C++ [class.mfct.non-static]p3:
// When an id-expression that is not part of a class member access
@@ -3996,131 +3980,130 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
// Failure cases.
fail:
- // There's a possible road to recovery for function types.
- const FunctionType *Fun = 0;
- SourceLocation ParenInsertionLoc =
- PP.getLocForEndOfToken(BaseExpr->getLocEnd());
-
+ // Recover from dot accesses to pointers, e.g.:
+ // type *foo;
+ // foo.bar
+ // This is actually well-formed in two cases:
+ // - 'type' is an Objective C type
+ // - 'bar' is a pseudo-destructor name which happens to refer to
+ // the appropriate pointer type
if (const PointerType *Ptr = BaseType->getAs<PointerType>()) {
- if ((Fun = Ptr->getPointeeType()->getAs<FunctionType>())) {
- // fall out, handled below.
-
- // Recover from dot accesses to pointers, e.g.:
- // type *foo;
- // foo.bar
- // This is actually well-formed in two cases:
- // - 'type' is an Objective C type
- // - 'bar' is a pseudo-destructor name which happens to refer to
- // the appropriate pointer type
- } else if (!IsArrow && Ptr->getPointeeType()->isRecordType() &&
- MemberName.getNameKind() != DeclarationName::CXXDestructorName) {
+ if (!IsArrow && Ptr->getPointeeType()->isRecordType() &&
+ MemberName.getNameKind() != DeclarationName::CXXDestructorName) {
Diag(OpLoc, diag::err_typecheck_member_reference_suggestion)
- << BaseType << int(IsArrow) << BaseExpr->getSourceRange()
- << FixItHint::CreateReplacement(OpLoc, "->");
+ << BaseType << int(IsArrow) << BaseExpr->getSourceRange()
+ << FixItHint::CreateReplacement(OpLoc, "->");
// Recurse as an -> access.
IsArrow = true;
return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS,
ObjCImpDecl, HasTemplateArgs);
}
- } else {
- Fun = BaseType->getAs<FunctionType>();
- }
-
- // If the user is trying to apply -> or . to a function pointer
- // type, it's probably because they forgot parentheses to call that
- // function. Suggest the addition of those parentheses, build the
- // call, and continue on.
- if (Fun || BaseType == Context.OverloadTy) {
- bool TryCall;
- if (BaseType == Context.OverloadTy) {
- // Plunder the overload set for something that would make the member
- // expression valid.
- const OverloadExpr *Overloads = cast<OverloadExpr>(BaseExpr);
- UnresolvedSet<4> CandidateOverloads;
- bool HasZeroArgCandidateOverload = false;
- for (OverloadExpr::decls_iterator it = Overloads->decls_begin(),
- DeclsEnd = Overloads->decls_end(); it != DeclsEnd; ++it) {
- const FunctionDecl *OverloadDecl = cast<FunctionDecl>(*it);
- QualType ResultTy = OverloadDecl->getResultType();
- if ((!IsArrow && ResultTy->isRecordType()) ||
- (IsArrow && ResultTy->isPointerType() &&
- ResultTy->getPointeeType()->isRecordType())) {
- CandidateOverloads.addDecl(*it);
- if (OverloadDecl->getNumParams() == 0) {
- HasZeroArgCandidateOverload = true;
- }
+ }
+
+ // If the user is trying to apply -> or . to a function name, it's probably
+ // because they forgot parentheses to call that function.
+ bool TryCall = false;
+ bool Overloaded = false;
+ UnresolvedSet<8> AllOverloads;
+ if (const OverloadExpr *Overloads = dyn_cast<OverloadExpr>(BaseExpr)) {
+ AllOverloads.append(Overloads->decls_begin(), Overloads->decls_end());
+ TryCall = true;
+ Overloaded = true;
+ } else if (DeclRefExpr *DeclRef = dyn_cast<DeclRefExpr>(BaseExpr)) {
+ if (FunctionDecl* Fun = dyn_cast<FunctionDecl>(DeclRef->getDecl())) {
+ AllOverloads.addDecl(Fun);
+ TryCall = true;
+ }
+ }
+
+ if (TryCall) {
+ // Plunder the overload set for something that would make the member
+ // expression valid.
+ UnresolvedSet<4> ViableOverloads;
+ bool HasViableZeroArgOverload = false;
+ for (OverloadExpr::decls_iterator it = AllOverloads.begin(),
+ DeclsEnd = AllOverloads.end(); it != DeclsEnd; ++it) {
+ const FunctionDecl *OverloadDecl = cast<FunctionDecl>(*it);
+ QualType ResultTy = OverloadDecl->getResultType();
+ if ((!IsArrow && ResultTy->isRecordType()) ||
+ (IsArrow && ResultTy->isPointerType() &&
+ ResultTy->getPointeeType()->isRecordType())) {
+ ViableOverloads.addDecl(*it);
+ if (OverloadDecl->getMinRequiredArguments() == 0) {
+ HasViableZeroArgOverload = true;
}
}
- if (HasZeroArgCandidateOverload && CandidateOverloads.size() == 1) {
- // We have one reasonable overload, and there's only one way to call it,
- // so emit a fixit and try to recover
- Diag(ParenInsertionLoc, diag::err_member_reference_needs_call)
- << 1
- << BaseExpr->getSourceRange()
- << FixItHint::CreateInsertion(ParenInsertionLoc, "()");
- TryCall = true;
- } else {
- Diag(BaseExpr->getExprLoc(), diag::err_member_reference_needs_call)
- << 0
- << BaseExpr->getSourceRange();
- int CandidateOverloadCount = CandidateOverloads.size();
- int I;
- for (I = 0; I < CandidateOverloadCount; ++I) {
- // FIXME: Magic number for max shown overloads stolen from
- // OverloadCandidateSet::NoteCandidates.
- if (I >= 4 && Diags.getShowOverloads() == Diagnostic::Ovl_Best) {
- break;
- }
- Diag(CandidateOverloads[I].getDecl()->getSourceRange().getBegin(),
- diag::note_member_ref_possible_intended_overload);
- }
- if (I != CandidateOverloadCount) {
- Diag(BaseExpr->getExprLoc(), diag::note_ovl_too_many_candidates)
- << int(CandidateOverloadCount - I);
+ }
+
+ if (!HasViableZeroArgOverload || ViableOverloads.size() != 1) {
+ Diag(BaseExpr->getExprLoc(), diag::err_member_reference_needs_call)
+ << 1 << 0
+ << BaseExpr->getSourceRange();
+ int ViableOverloadCount = ViableOverloads.size();
+ int I;
+ for (I = 0; I < ViableOverloadCount; ++I) {
+ // FIXME: Magic number for max shown overloads stolen from
+ // OverloadCandidateSet::NoteCandidates.
+ if (I >= 4 && Diags.getShowOverloads() == Diagnostic::Ovl_Best) {
+ break;
}
- return ExprError();
+ Diag(ViableOverloads[I].getDecl()->getSourceRange().getBegin(),
+ diag::note_member_ref_possible_intended_overload);
}
- } else {
- if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(Fun)) {
- TryCall = (FPT->getNumArgs() == 0);
- } else {
- TryCall = true;
+ if (I != ViableOverloadCount) {
+ Diag(BaseExpr->getExprLoc(), diag::note_ovl_too_many_candidates)
+ << int(ViableOverloadCount - I);
}
-
- if (TryCall) {
- QualType ResultTy = Fun->getResultType();
- TryCall = (!IsArrow && ResultTy->isRecordType()) ||
- (IsArrow && ResultTy->isPointerType() &&
- ResultTy->getAs<PointerType>()->getPointeeType()->isRecordType());
+ return ExprError();
+ }
+ } else {
+ // We don't have an expression that's convenient to get a Decl from, but we
+ // can at least check if the type is "function of 0 arguments which returns
+ // an acceptable type".
+ const FunctionType *Fun = NULL;
+ if (const PointerType *Ptr = BaseType->getAs<PointerType>()) {
+ if ((Fun = Ptr->getPointeeType()->getAs<FunctionType>())) {
+ TryCall = true;
}
+ } else if ((Fun = BaseType->getAs<FunctionType>())) {
+ TryCall = true;
}
-
if (TryCall) {
- if (Fun) {
- Diag(BaseExpr->getExprLoc(),
- diag::err_member_reference_needs_call_zero_arg)
- << QualType(Fun, 0)
- << FixItHint::CreateInsertion(ParenInsertionLoc, "()");
+ if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(Fun)) {
+ if (FPT->getNumArgs() == 0) {
+ QualType ResultTy = Fun->getResultType();
+ TryCall = (!IsArrow && ResultTy->isRecordType()) ||
+ (IsArrow && ResultTy->isPointerType() &&
+ ResultTy->getPointeeType()->isRecordType());
+ }
}
-
- ExprResult NewBase
- = ActOnCallExpr(0, BaseExpr, ParenInsertionLoc,
- MultiExprArg(*this, 0, 0), ParenInsertionLoc);
- if (NewBase.isInvalid())
- return ExprError();
- BaseExpr = NewBase.takeAs<Expr>();
-
-
- DefaultFunctionArrayConversion(BaseExpr);
- BaseType = BaseExpr->getType();
-
- return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS,
- ObjCImpDecl, HasTemplateArgs);
}
}
+ if (TryCall) {
+ // At this point, we know BaseExpr looks like it's potentially callable with
+ // 0 arguments, and that it returns something of a reasonable type, so we
+ // can emit a fixit and carry on pretending that BaseExpr was actually a
+ // CallExpr.
+ SourceLocation ParenInsertionLoc =
+ PP.getLocForEndOfToken(BaseExpr->getLocEnd());
+ Diag(BaseExpr->getExprLoc(), diag::err_member_reference_needs_call)
+ << int(Overloaded) << 1
+ << BaseExpr->getSourceRange()
+ << FixItHint::CreateInsertion(ParenInsertionLoc, "()");
+ ExprResult NewBase = ActOnCallExpr(0, BaseExpr, ParenInsertionLoc,
+ MultiExprArg(*this, 0, 0),
+ ParenInsertionLoc);
+ if (NewBase.isInvalid())
+ return ExprError();
+ BaseExpr = NewBase.takeAs<Expr>();
+ DefaultFunctionArrayConversion(BaseExpr);
+ return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS,
+ ObjCImpDecl, HasTemplateArgs);
+ }
+
Diag(MemberLoc, diag::err_typecheck_member_reference_struct_union)
<< BaseType << BaseExpr->getSourceRange();
@@ -4298,6 +4281,13 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
const FunctionProtoType *Proto,
Expr **Args, unsigned NumArgs,
SourceLocation RParenLoc) {
+ // Bail out early if calling a builtin with custom typechecking.
+ // We don't need to do this in the
+ if (FDecl)
+ if (unsigned ID = FDecl->getBuiltinID())
+ if (Context.BuiltinInfo.hasCustomTypechecking(ID))
+ return false;
+
// C99 6.5.2.2p7 - the arguments are implicitly converted, as if by
// assignment, to the types of the corresponding parameter, ...
unsigned NumArgsInProto = Proto->getNumArgs();
@@ -4625,22 +4615,41 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
RParenLoc);
}
+ unsigned BuiltinID = (FDecl ? FDecl->getBuiltinID() : 0);
+
+ // Bail out early if calling a builtin with custom typechecking.
+ if (BuiltinID && Context.BuiltinInfo.hasCustomTypechecking(BuiltinID))
+ return CheckBuiltinFunctionCall(BuiltinID, TheCall);
+
const FunctionType *FuncT;
- if (!Fn->getType()->isBlockPointerType()) {
+ if (const PointerType *PT = Fn->getType()->getAs<PointerType>()) {
// C99 6.5.2.2p1 - "The expression that denotes the called function shall
// have type pointer to function".
- const PointerType *PT = Fn->getType()->getAs<PointerType>();
- if (PT == 0)
- return ExprError(Diag(LParenLoc, diag::err_typecheck_call_not_function)
- << Fn->getType() << Fn->getSourceRange());
FuncT = PT->getPointeeType()->getAs<FunctionType>();
- } else { // This is a block call.
- FuncT = Fn->getType()->getAs<BlockPointerType>()->getPointeeType()->
- getAs<FunctionType>();
- }
- if (FuncT == 0)
+ if (FuncT == 0)
+ return ExprError(Diag(LParenLoc, diag::err_typecheck_call_not_function)
+ << Fn->getType() << Fn->getSourceRange());
+ } else if (const BlockPointerType *BPT =
+ Fn->getType()->getAs<BlockPointerType>()) {
+ FuncT = BPT->getPointeeType()->castAs<FunctionType>();
+ } else {
return ExprError(Diag(LParenLoc, diag::err_typecheck_call_not_function)
<< Fn->getType() << Fn->getSourceRange());
+ }
+
+ if (getLangOptions().CUDA) {
+ if (Config) {
+ // CUDA: Kernel calls must be to global functions
+ if (FDecl && !FDecl->hasAttr<CUDAGlobalAttr>())
+ return ExprError(Diag(LParenLoc,diag::err_kern_call_not_global_function)
+ << FDecl->getName() << Fn->getSourceRange());
+
+ // CUDA: Kernel function must have 'void' return type
+ if (!FuncT->getResultType()->isVoidType())
+ return ExprError(Diag(LParenLoc, diag::err_kern_type_not_void_return)
+ << Fn->getType() << Fn->getSourceRange());
+ }
+ }
// Check for a valid return type
if (CheckCallReturnType(FuncT->getResultType(),
@@ -4721,7 +4730,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
if (CheckFunctionCall(FDecl, TheCall))
return ExprError();
- if (unsigned BuiltinID = FDecl->getBuiltinID())
+ if (BuiltinID)
return CheckBuiltinFunctionCall(BuiltinID, TheCall);
} else if (NDecl) {
if (CheckBlockCall(NDecl, TheCall))
@@ -6372,8 +6381,8 @@ QualType Sema::CheckMultiplyDivideOperands(
// Check for division by zero.
if (isDiv &&
rex->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull))
- DiagRuntimeBehavior(Loc, PDiag(diag::warn_division_by_zero)
- << rex->getSourceRange());
+ DiagRuntimeBehavior(Loc, rex, PDiag(diag::warn_division_by_zero)
+ << rex->getSourceRange());
return compType;
}
@@ -6394,8 +6403,8 @@ QualType Sema::CheckRemainderOperands(
// Check for remainder by zero.
if (rex->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull))
- DiagRuntimeBehavior(Loc, PDiag(diag::warn_remainder_by_zero)
- << rex->getSourceRange());
+ DiagRuntimeBehavior(Loc, rex, PDiag(diag::warn_remainder_by_zero)
+ << rex->getSourceRange());
return compType;
}
@@ -6629,9 +6638,61 @@ static bool isScopedEnumerationType(QualType T) {
return false;
}
+static void DiagnoseBadShiftValues(Sema& S, Expr *&lex, Expr *&rex,
+ SourceLocation Loc, unsigned Opc,
+ QualType LHSTy) {
+ llvm::APSInt Right;
+ // Check right/shifter operand
+ if (rex->isValueDependent() || !rex->isIntegerConstantExpr(Right, S.Context))
+ return;
+
+ if (Right.isNegative()) {
+ S.Diag(Loc, diag::warn_shift_negative) << rex->getSourceRange();
+ return;
+ }
+ llvm::APInt LeftBits(Right.getBitWidth(),
+ S.Context.getTypeSize(lex->getType()));
+ if (Right.uge(LeftBits)) {
+ S.Diag(Loc, diag::warn_shift_gt_typewidth) << rex->getSourceRange();
+ return;
+ }
+ if (Opc != BO_Shl)
+ return;
+
+ // When left shifting an ICE which is signed, we can check for overflow which
+ // according to C++ has undefined behavior ([expr.shift] 5.8/2). Unsigned
+ // integers have defined behavior modulo one more than the maximum value
+ // representable in the result type, so never warn for those.
+ llvm::APSInt Left;
+ if (lex->isValueDependent() || !lex->isIntegerConstantExpr(Left, S.Context) ||
+ LHSTy->hasUnsignedIntegerRepresentation())
+ return;
+ llvm::APInt ResultBits =
+ static_cast<llvm::APInt&>(Right) + Left.getMinSignedBits();
+ if (LeftBits.uge(ResultBits))
+ return;
+ llvm::APSInt Result = Left.extend(ResultBits.getLimitedValue());
+ Result = Result.shl(Right);
+
+ // If we are only missing a sign bit, this is less likely to result in actual
+ // bugs -- if the result is cast back to an unsigned type, it will have the
+ // expected value. Thus we place this behind a different warning that can be
+ // turned off separately if needed.
+ if (LeftBits == ResultBits - 1) {
+ S.Diag(Loc, diag::warn_shift_result_overrides_sign_bit)
+ << Result.toString(10) << LHSTy
+ << lex->getSourceRange() << rex->getSourceRange();
+ return;
+ }
+
+ S.Diag(Loc, diag::warn_shift_result_gt_typewidth)
+ << Result.toString(10) << Result.getMinSignedBits() << LHSTy
+ << Left.getBitWidth() << lex->getSourceRange() << rex->getSourceRange();
+}
+
// C99 6.5.7
QualType Sema::CheckShiftOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
- bool isCompAssign) {
+ unsigned Opc, bool isCompAssign) {
// C99 6.5.7p2: Each of the operands shall have integer type.
if (!lex->getType()->hasIntegerRepresentation() ||
!rex->getType()->hasIntegerRepresentation())
@@ -6662,19 +6723,7 @@ QualType Sema::CheckShiftOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
UsualUnaryConversions(rex);
// Sanity-check shift operands
- llvm::APSInt Right;
- // Check right/shifter operand
- if (!rex->isValueDependent() &&
- rex->isIntegerConstantExpr(Right, Context)) {
- if (Right.isNegative())
- Diag(Loc, diag::warn_shift_negative) << rex->getSourceRange();
- else {
- llvm::APInt LeftBits(Right.getBitWidth(),
- Context.getTypeSize(lex->getType()));
- if (Right.uge(LeftBits))
- Diag(Loc, diag::warn_shift_gt_typewidth) << rex->getSourceRange();
- }
- }
+ DiagnoseBadShiftValues(*this, lex, rex, Loc, Opc, LHSTy);
// "The type of the result is that of the promoted left operand."
return LHSTy;
@@ -6738,7 +6787,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
if (DeclRefExpr* DRR = dyn_cast<DeclRefExpr>(RHSStripped)) {
if (DRL->getDecl() == DRR->getDecl() &&
!IsWithinTemplateSpecialization(DRL->getDecl())) {
- DiagRuntimeBehavior(Loc, PDiag(diag::warn_comparison_always)
+ DiagRuntimeBehavior(Loc, 0, PDiag(diag::warn_comparison_always)
<< 0 // self-
<< (Opc == BO_EQ
|| Opc == BO_LE
@@ -6760,7 +6809,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
always_evals_to = 2; // e.g. array1 <= array2
break;
}
- DiagRuntimeBehavior(Loc, PDiag(diag::warn_comparison_always)
+ DiagRuntimeBehavior(Loc, 0, PDiag(diag::warn_comparison_always)
<< 1 // array
<< always_evals_to);
}
@@ -6801,7 +6850,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
default: assert(false && "Invalid comparison operator");
}
- DiagRuntimeBehavior(Loc,
+ DiagRuntimeBehavior(Loc, 0,
PDiag(diag::warn_stringcompare)
<< isa<ObjCEncodeExpr>(literalStringStripped)
<< literalString->getSourceRange());
@@ -7111,7 +7160,7 @@ QualType Sema::CheckVectorCompareOperands(Expr *&lex, Expr *&rex,
if (DeclRefExpr* DRL = dyn_cast<DeclRefExpr>(lex->IgnoreParens()))
if (DeclRefExpr* DRR = dyn_cast<DeclRefExpr>(rex->IgnoreParens()))
if (DRL->getDecl() == DRR->getDecl())
- DiagRuntimeBehavior(Loc,
+ DiagRuntimeBehavior(Loc, 0,
PDiag(diag::warn_comparison_always)
<< 0 // self-
<< 2 // "a constant"
@@ -7372,9 +7421,11 @@ QualType Sema::CheckAssignmentOperands(Expr *LHS, Expr *&RHS,
UO->getSubExpr()->IgnoreParenCasts()->
isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull) &&
!UO->getType().isVolatileQualified()) {
- Diag(UO->getOperatorLoc(), diag::warn_indirection_through_null)
- << UO->getSubExpr()->getSourceRange();
- Diag(UO->getOperatorLoc(), diag::note_indirection_through_null);
+ DiagRuntimeBehavior(UO->getOperatorLoc(), UO,
+ PDiag(diag::warn_indirection_through_null)
+ << UO->getSubExpr()->getSourceRange());
+ DiagRuntimeBehavior(UO->getOperatorLoc(), UO,
+ PDiag(diag::note_indirection_through_null));
}
// Check for trivial buffer overflows.
@@ -7959,7 +8010,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
break;
case BO_Shl:
case BO_Shr:
- ResultTy = CheckShiftOperands(lhs, rhs, OpLoc);
+ ResultTy = CheckShiftOperands(lhs, rhs, OpLoc, Opc);
break;
case BO_LE:
case BO_LT:
@@ -8006,7 +8057,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
break;
case BO_ShlAssign:
case BO_ShrAssign:
- CompResultTy = CheckShiftOperands(lhs, rhs, OpLoc, true);
+ CompResultTy = CheckShiftOperands(lhs, rhs, OpLoc, Opc, true);
CompLHSTy = CompResultTy;
if (!CompResultTy.isNull())
ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompResultTy);
@@ -8563,7 +8614,7 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
// (clause 9).
if (CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(RD)) {
if (!CRD->isPOD() && !DidWarnAboutNonPOD &&
- DiagRuntimeBehavior(BuiltinLoc,
+ DiagRuntimeBehavior(BuiltinLoc, 0,
PDiag(diag::warn_offsetof_non_pod_type)
<< SourceRange(CompPtr[0].LocStart, OC.LocEnd)
<< CurrentType))
@@ -8907,12 +8958,8 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
BlockExpr *Result = new (Context) BlockExpr(BSI->TheDecl, BlockTy);
- // Issue any analysis-based warnings.
- const sema::AnalysisBasedWarnings::Policy &WP =
- AnalysisWarnings.getDefaultPolicy();
- AnalysisWarnings.IssueWarnings(WP, Result);
-
- PopFunctionOrBlockScope();
+ const AnalysisBasedWarnings::Policy &WP = AnalysisWarnings.getDefaultPolicy();
+ PopFunctionOrBlockScope(&WP, Result->getBlockDecl(), Result);
return Owned(Result);
}
@@ -9350,9 +9397,12 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) {
}
}
- // Keep track of used but undefined variables.
+ // Keep track of used but undefined variables. We make a hole in
+ // the warning for static const data members with in-line
+ // initializers.
if (Var->hasDefinition() == VarDecl::DeclarationOnly
- && Var->getLinkage() != ExternalLinkage) {
+ && Var->getLinkage() != ExternalLinkage
+ && !(Var->isStaticDataMember() && Var->hasInit())) {
SourceLocation &old = UndefinedInternals[Var->getCanonicalDecl()];
if (old.isInvalid()) old = Loc;
}
@@ -9484,7 +9534,7 @@ void Sema::MarkDeclarationsReferencedInExpr(Expr *E) {
/// behavior of a program, such as passing a non-POD value through an ellipsis.
/// Failure to do so will likely result in spurious diagnostics or failures
/// during overload resolution or within sizeof/alignof/typeof/typeid.
-bool Sema::DiagRuntimeBehavior(SourceLocation Loc,
+bool Sema::DiagRuntimeBehavior(SourceLocation Loc, const Stmt *stmt,
const PartialDiagnostic &PD) {
switch (ExprEvalContexts.back().Context ) {
case Unevaluated:
@@ -9493,7 +9543,13 @@ bool Sema::DiagRuntimeBehavior(SourceLocation Loc,
case PotentiallyEvaluated:
case PotentiallyEvaluatedIfUsed:
- Diag(Loc, PD);
+ if (stmt && getCurFunctionOrMethodDecl()) {
+ FunctionScopes.back()->PossiblyUnreachableDiags.
+ push_back(sema::PossiblyUnreachableDiag(PD, Loc, stmt));
+ }
+ else
+ Diag(Loc, PD);
+
return true;
case PotentiallyPotentiallyEvaluated:
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp
index f9c2c9a..6dd7aab 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp
@@ -107,7 +107,7 @@ ParsedType Sema::getDestructorName(SourceLocation TildeLoc,
// Nothing left to do.
} else if (LookAtPrefix && (Prefix = NNS->getPrefix())) {
CXXScopeSpec PrefixSS;
- PrefixSS.setScopeRep(Prefix);
+ PrefixSS.Adopt(NestedNameSpecifierLoc(Prefix, SS.location_data()));
LookupCtx = computeDeclContext(PrefixSS, EnteringContext);
isDependent = isDependentScopeSpecifier(PrefixSS);
} else if (ObjectTypePtr) {
@@ -476,7 +476,9 @@ Sema::ActOnCXXNullPtrLiteral(SourceLocation Loc) {
/// ActOnCXXThrow - Parse throw expressions.
ExprResult
Sema::ActOnCXXThrow(SourceLocation OpLoc, Expr *Ex) {
- if (!getLangOptions().Exceptions)
+ // Don't report an error if 'throw' is used in system headers.
+ if (!getLangOptions().Exceptions &&
+ !getSourceManager().isInSystemHeader(OpLoc))
Diag(OpLoc, diag::err_exceptions_disabled) << "throw";
if (Ex && !Ex->isTypeDependent() && CheckCXXThrowOperand(OpLoc, Ex))
@@ -1347,6 +1349,7 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range,
case OR_Success: {
// Got one!
FunctionDecl *FnDecl = Best->Function;
+ MarkDeclarationReferenced(StartLoc, FnDecl);
// The first argument is size_t, and the first parameter must be size_t,
// too. This is checked on declaration and can be assumed. (It can't be
// asserted on, though, since invalid decls are left in there.)
@@ -1384,7 +1387,10 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range,
case OR_Deleted:
Diag(StartLoc, diag::err_ovl_deleted_call)
<< Best->Function->isDeleted()
- << Name << Range;
+ << Name
+ << Best->Function->getMessageUnavailableAttr(
+ !Best->Function->isDeleted())
+ << Range;
Candidates.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs);
return true;
}
@@ -2920,6 +2926,8 @@ static bool FindConditionalOverload(Sema &Self, Expr *&LHS, Expr *&RHS,
Self.PerformImplicitConversion(RHS, Best->BuiltinTypes.ParamTypes[1],
Best->Conversions[1], Sema::AA_Converting))
break;
+ if (Best->Function)
+ Self.MarkDeclarationReferenced(QuestionLoc, Best->Function);
return false;
case OR_No_Viable_Function:
@@ -3580,14 +3588,14 @@ ExprResult Sema::DiagnoseDtorReference(SourceLocation NameLoc,
}
ExprResult Sema::BuildPseudoDestructorExpr(Expr *Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- const CXXScopeSpec &SS,
- TypeSourceInfo *ScopeTypeInfo,
- SourceLocation CCLoc,
- SourceLocation TildeLoc,
+ SourceLocation OpLoc,
+ tok::TokenKind OpKind,
+ const CXXScopeSpec &SS,
+ TypeSourceInfo *ScopeTypeInfo,
+ SourceLocation CCLoc,
+ SourceLocation TildeLoc,
PseudoDestructorTypeStorage Destructed,
- bool HasTrailingLParen) {
+ bool HasTrailingLParen) {
TypeSourceInfo *DestructedTypeInfo = Destructed.getTypeSourceInfo();
// C++ [expr.pseudo]p2:
@@ -3662,7 +3670,7 @@ ExprResult Sema::BuildPseudoDestructorExpr(Expr *Base,
Expr *Result
= new (Context) CXXPseudoDestructorExpr(Context, Base,
OpKind == tok::arrow, OpLoc,
- SS.getScopeRep(), SS.getRange(),
+ SS.getWithLocInContext(Context),
ScopeTypeInfo,
CCLoc,
TildeLoc,
@@ -3675,14 +3683,14 @@ ExprResult Sema::BuildPseudoDestructorExpr(Expr *Base,
}
ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- CXXScopeSpec &SS,
- UnqualifiedId &FirstTypeName,
- SourceLocation CCLoc,
- SourceLocation TildeLoc,
- UnqualifiedId &SecondTypeName,
- bool HasTrailingLParen) {
+ SourceLocation OpLoc,
+ tok::TokenKind OpKind,
+ CXXScopeSpec &SS,
+ UnqualifiedId &FirstTypeName,
+ SourceLocation CCLoc,
+ SourceLocation TildeLoc,
+ UnqualifiedId &SecondTypeName,
+ bool HasTrailingLParen) {
assert((FirstTypeName.getKind() == UnqualifiedId::IK_TemplateId ||
FirstTypeName.getKind() == UnqualifiedId::IK_Identifier) &&
"Invalid first type name in pseudo-destructor");
@@ -3714,8 +3722,8 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
// record types and dependent types matter.
ParsedType ObjectTypePtrForLookup;
if (!SS.isSet()) {
- if (const Type *T = ObjectType->getAs<RecordType>())
- ObjectTypePtrForLookup = ParsedType::make(QualType(T, 0));
+ if (ObjectType->isRecordType())
+ ObjectTypePtrForLookup = ParsedType::make(ObjectType);
else if (ObjectType->isDependentType())
ObjectTypePtrForLookup = ParsedType::make(Context.DependentTy);
}
@@ -3784,7 +3792,7 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
if (FirstTypeName.getKind() == UnqualifiedId::IK_Identifier) {
ParsedType T = getTypeName(*FirstTypeName.Identifier,
FirstTypeName.StartLocation,
- S, &SS, false, false, ObjectTypePtrForLookup);
+ S, &SS, true, false, ObjectTypePtrForLookup);
if (!T) {
Diag(FirstTypeName.StartLocation,
diag::err_pseudo_dtor_destructor_non_type)
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp
index b9a6a57..5882da0 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp
@@ -31,10 +31,8 @@ using namespace clang;
// Sema Initialization Checking
//===----------------------------------------------------------------------===//
-static Expr *IsStringInit(Expr *Init, QualType DeclType, ASTContext &Context) {
- const ArrayType *AT = Context.getAsArrayType(DeclType);
- if (!AT) return 0;
-
+static Expr *IsStringInit(Expr *Init, const ArrayType *AT,
+ ASTContext &Context) {
if (!isa<ConstantArrayType>(AT) && !isa<IncompleteArrayType>(AT))
return 0;
@@ -66,13 +64,20 @@ static Expr *IsStringInit(Expr *Init, QualType DeclType, ASTContext &Context) {
return 0;
}
-static void CheckStringInit(Expr *Str, QualType &DeclT, Sema &S) {
+static Expr *IsStringInit(Expr *init, QualType declType, ASTContext &Context) {
+ const ArrayType *arrayType = Context.getAsArrayType(declType);
+ if (!arrayType) return 0;
+
+ return IsStringInit(init, arrayType, Context);
+}
+
+static void CheckStringInit(Expr *Str, QualType &DeclT, const ArrayType *AT,
+ Sema &S) {
// Get the length of the string as parsed.
uint64_t StrLength =
cast<ConstantArrayType>(Str->getType())->getSize().getZExtValue();
- const ArrayType *AT = S.Context.getAsArrayType(DeclT);
if (const IncompleteArrayType *IAT = dyn_cast<IncompleteArrayType>(AT)) {
// C99 6.7.8p14. We have an array of character type with unknown size
// being initialized to a string literal.
@@ -651,82 +656,93 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity,
newStructuredList, newStructuredIndex);
++StructuredIndex;
++Index;
- } else if (Expr *Str = IsStringInit(expr, ElemType, SemaRef.Context)) {
- CheckStringInit(Str, ElemType, SemaRef);
- UpdateStructuredListElement(StructuredList, StructuredIndex, Str);
- ++Index;
+ return;
} else if (ElemType->isScalarType()) {
- CheckScalarType(Entity, IList, ElemType, Index,
- StructuredList, StructuredIndex);
+ return CheckScalarType(Entity, IList, ElemType, Index,
+ StructuredList, StructuredIndex);
} else if (ElemType->isReferenceType()) {
- CheckReferenceType(Entity, IList, ElemType, Index,
- StructuredList, StructuredIndex);
- } else {
- if (SemaRef.getLangOptions().CPlusPlus) {
- // C++ [dcl.init.aggr]p12:
- // All implicit type conversions (clause 4) are considered when
- // initializing the aggregate member with an ini- tializer from
- // an initializer-list. If the initializer can initialize a
- // member, the member is initialized. [...]
-
- // FIXME: Better EqualLoc?
- InitializationKind Kind =
- InitializationKind::CreateCopy(expr->getLocStart(), SourceLocation());
- InitializationSequence Seq(SemaRef, Entity, Kind, &expr, 1);
-
- if (Seq) {
- ExprResult Result =
- Seq.Perform(SemaRef, Entity, Kind, MultiExprArg(&expr, 1));
- if (Result.isInvalid())
- hadError = true;
-
- UpdateStructuredListElement(StructuredList, StructuredIndex,
- Result.takeAs<Expr>());
- ++Index;
- return;
- }
+ return CheckReferenceType(Entity, IList, ElemType, Index,
+ StructuredList, StructuredIndex);
+ }
- // Fall through for subaggregate initialization
- } else {
- // C99 6.7.8p13:
- //
- // The initializer for a structure or union object that has
- // automatic storage duration shall be either an initializer
- // list as described below, or a single expression that has
- // compatible structure or union type. In the latter case, the
- // initial value of the object, including unnamed members, is
- // that of the expression.
- if ((ElemType->isRecordType() || ElemType->isVectorType()) &&
- SemaRef.CheckSingleAssignmentConstraints(ElemType, expr)
- == Sema::Compatible) {
- SemaRef.DefaultFunctionArrayLvalueConversion(expr);
- UpdateStructuredListElement(StructuredList, StructuredIndex, expr);
- ++Index;
- return;
- }
+ if (const ArrayType *arrayType = SemaRef.Context.getAsArrayType(ElemType)) {
+ // arrayType can be incomplete if we're initializing a flexible
+ // array member. There's nothing we can do with the completed
+ // type here, though.
- // Fall through for subaggregate initialization
+ if (Expr *Str = IsStringInit(expr, arrayType, SemaRef.Context)) {
+ CheckStringInit(Str, ElemType, arrayType, SemaRef);
+ UpdateStructuredListElement(StructuredList, StructuredIndex, Str);
+ ++Index;
+ return;
}
+ // Fall through for subaggregate initialization.
+
+ } else if (SemaRef.getLangOptions().CPlusPlus) {
// C++ [dcl.init.aggr]p12:
+ // All implicit type conversions (clause 4) are considered when
+ // initializing the aggregate member with an ini- tializer from
+ // an initializer-list. If the initializer can initialize a
+ // member, the member is initialized. [...]
+
+ // FIXME: Better EqualLoc?
+ InitializationKind Kind =
+ InitializationKind::CreateCopy(expr->getLocStart(), SourceLocation());
+ InitializationSequence Seq(SemaRef, Entity, Kind, &expr, 1);
+
+ if (Seq) {
+ ExprResult Result =
+ Seq.Perform(SemaRef, Entity, Kind, MultiExprArg(&expr, 1));
+ if (Result.isInvalid())
+ hadError = true;
+
+ UpdateStructuredListElement(StructuredList, StructuredIndex,
+ Result.takeAs<Expr>());
+ ++Index;
+ return;
+ }
+
+ // Fall through for subaggregate initialization
+ } else {
+ // C99 6.7.8p13:
//
- // [...] Otherwise, if the member is itself a non-empty
- // subaggregate, brace elision is assumed and the initializer is
- // considered for the initialization of the first member of
- // the subaggregate.
- if (ElemType->isAggregateType() || ElemType->isVectorType()) {
- CheckImplicitInitList(Entity, IList, ElemType, Index, StructuredList,
- StructuredIndex);
- ++StructuredIndex;
- } else {
- // We cannot initialize this element, so let
- // PerformCopyInitialization produce the appropriate diagnostic.
- SemaRef.PerformCopyInitialization(Entity, SourceLocation(),
- SemaRef.Owned(expr));
- hadError = true;
+ // The initializer for a structure or union object that has
+ // automatic storage duration shall be either an initializer
+ // list as described below, or a single expression that has
+ // compatible structure or union type. In the latter case, the
+ // initial value of the object, including unnamed members, is
+ // that of the expression.
+ if ((ElemType->isRecordType() || ElemType->isVectorType()) &&
+ SemaRef.CheckSingleAssignmentConstraints(ElemType, expr)
+ == Sema::Compatible) {
+ SemaRef.DefaultFunctionArrayLvalueConversion(expr);
+ UpdateStructuredListElement(StructuredList, StructuredIndex, expr);
++Index;
- ++StructuredIndex;
+ return;
}
+
+ // Fall through for subaggregate initialization
+ }
+
+ // C++ [dcl.init.aggr]p12:
+ //
+ // [...] Otherwise, if the member is itself a non-empty
+ // subaggregate, brace elision is assumed and the initializer is
+ // considered for the initialization of the first member of
+ // the subaggregate.
+ if (ElemType->isAggregateType() || ElemType->isVectorType()) {
+ CheckImplicitInitList(Entity, IList, ElemType, Index, StructuredList,
+ StructuredIndex);
+ ++StructuredIndex;
+ } else {
+ // We cannot initialize this element, so let
+ // PerformCopyInitialization produce the appropriate diagnostic.
+ SemaRef.PerformCopyInitialization(Entity, SourceLocation(),
+ SemaRef.Owned(expr));
+ hadError = true;
+ ++Index;
+ ++StructuredIndex;
}
}
@@ -936,11 +952,13 @@ void InitListChecker::CheckArrayType(const InitializedEntity &Entity,
unsigned &Index,
InitListExpr *StructuredList,
unsigned &StructuredIndex) {
+ const ArrayType *arrayType = SemaRef.Context.getAsArrayType(DeclType);
+
// Check for the special-case of initializing an array with a string.
if (Index < IList->getNumInits()) {
- if (Expr *Str = IsStringInit(IList->getInit(Index), DeclType,
+ if (Expr *Str = IsStringInit(IList->getInit(Index), arrayType,
SemaRef.Context)) {
- CheckStringInit(Str, DeclType, SemaRef);
+ CheckStringInit(Str, DeclType, arrayType, SemaRef);
// We place the string literal directly into the resulting
// initializer list. This is the only place where the structure
// of the structured initializer list doesn't match exactly,
@@ -952,8 +970,7 @@ void InitListChecker::CheckArrayType(const InitializedEntity &Entity,
return;
}
}
- if (const VariableArrayType *VAT =
- SemaRef.Context.getAsVariableArrayType(DeclType)) {
+ if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(arrayType)) {
// Check for VLAs; in standard C it would be possible to check this
// earlier, but I don't know where clang accepts VLAs (gcc accepts
// them in all sorts of strange places).
@@ -970,16 +987,14 @@ void InitListChecker::CheckArrayType(const InitializedEntity &Entity,
llvm::APSInt maxElements(elementIndex.getBitWidth(),
elementIndex.isUnsigned());
bool maxElementsKnown = false;
- if (const ConstantArrayType *CAT =
- SemaRef.Context.getAsConstantArrayType(DeclType)) {
+ if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(arrayType)) {
maxElements = CAT->getSize();
elementIndex = elementIndex.extOrTrunc(maxElements.getBitWidth());
elementIndex.setIsUnsigned(maxElements.isUnsigned());
maxElementsKnown = true;
}
- QualType elementType = SemaRef.Context.getAsArrayType(DeclType)
- ->getElementType();
+ QualType elementType = arrayType->getElementType();
while (Index < IList->getNumInits()) {
Expr *Init = IList->getInit(Index);
if (DesignatedInitExpr *DIE = dyn_cast<DesignatedInitExpr>(Init)) {
@@ -2059,6 +2074,7 @@ void InitializationSequence::Step::Destroy() {
case SK_CAssignment:
case SK_StringInit:
case SK_ObjCObjectConversion:
+ case SK_ArrayInit:
break;
case SK_ConversionSequence:
@@ -2090,6 +2106,8 @@ bool InitializationSequence::isAmbiguous() const {
case FK_InitListBadDestinationType:
case FK_DefaultInitOfConst:
case FK_Incomplete:
+ case FK_ArrayTypeMismatch:
+ case FK_NonConstantArrayInit:
return false;
case FK_ReferenceInitOverloadFailed:
@@ -2232,6 +2250,13 @@ void InitializationSequence::AddObjCObjectConversionStep(QualType T) {
Steps.push_back(S);
}
+void InitializationSequence::AddArrayInitStep(QualType T) {
+ Step S;
+ S.Kind = SK_ArrayInit;
+ S.Type = T;
+ Steps.push_back(S);
+}
+
void InitializationSequence::SetOverloadFailure(FailureKind Failure,
OverloadingResult Result) {
SequenceKind = FailedSequence;
@@ -2416,6 +2441,10 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
FunctionDecl *Function = Best->Function;
+ // This is the overload that will actually be used for the initialization, so
+ // mark it as used.
+ S.MarkDeclarationReferenced(DeclLoc, Function);
+
// Compute the returned type of the conversion.
if (isa<CXXConversionDecl>(Function))
T2 = Function->getResultType();
@@ -3020,6 +3049,7 @@ static void TryUserDefinedConversion(Sema &S,
}
FunctionDecl *Function = Best->Function;
+ S.MarkDeclarationReferenced(DeclLoc, Function);
if (isa<CXXConstructorDecl>(Function)) {
// Add the user-defined conversion step. Any cv-qualification conversion is
@@ -3054,6 +3084,25 @@ static void TryUserDefinedConversion(Sema &S,
}
}
+/// \brief Determine whether we have compatible array types for the
+/// purposes of GNU by-copy array initialization.
+static bool hasCompatibleArrayTypes(ASTContext &Context,
+ const ArrayType *Dest,
+ const ArrayType *Source) {
+ // If the source and destination array types are equivalent, we're
+ // done.
+ if (Context.hasSameType(QualType(Dest, 0), QualType(Source, 0)))
+ return true;
+
+ // Make sure that the element types are the same.
+ if (!Context.hasSameType(Dest->getElementType(), Source->getElementType()))
+ return false;
+
+ // The only mismatch we allow is when the destination is an
+ // incomplete array type and the source is a constant array type.
+ return Source->isConstantArrayType() && Dest->isIncompleteArrayType();
+}
+
InitializationSequence::InitializationSequence(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
@@ -3109,14 +3158,6 @@ InitializationSequence::InitializationSequence(Sema &S,
return;
}
- // - If the destination type is an array of characters, an array of
- // char16_t, an array of char32_t, or an array of wchar_t, and the
- // initializer is a string literal, see 8.5.2.
- if (Initializer && IsStringInit(Initializer, DestType, Context)) {
- TryStringLiteralInitialization(S, Entity, Kind, Initializer, *this);
- return;
- }
-
// - If the initializer is (), the object is value-initialized.
if (Kind.getKind() == InitializationKind::IK_Value ||
(Kind.getKind() == InitializationKind::IK_Direct && NumArgs == 0)) {
@@ -3130,10 +3171,34 @@ InitializationSequence::InitializationSequence(Sema &S,
return;
}
+ // - If the destination type is an array of characters, an array of
+ // char16_t, an array of char32_t, or an array of wchar_t, and the
+ // initializer is a string literal, see 8.5.2.
// - Otherwise, if the destination type is an array, the program is
// ill-formed.
- if (const ArrayType *AT = Context.getAsArrayType(DestType)) {
- if (AT->getElementType()->isAnyCharacterType())
+ if (const ArrayType *DestAT = Context.getAsArrayType(DestType)) {
+ if (Initializer && IsStringInit(Initializer, DestAT, Context)) {
+ TryStringLiteralInitialization(S, Entity, Kind, Initializer, *this);
+ return;
+ }
+
+ // Note: as an GNU C extension, we allow initialization of an
+ // array from a compound literal that creates an array of the same
+ // type, so long as the initializer has no side effects.
+ if (!S.getLangOptions().CPlusPlus && Initializer &&
+ isa<CompoundLiteralExpr>(Initializer->IgnoreParens()) &&
+ Initializer->getType()->isArrayType()) {
+ const ArrayType *SourceAT
+ = Context.getAsArrayType(Initializer->getType());
+ if (!hasCompatibleArrayTypes(S.Context, DestAT, SourceAT))
+ SetFailed(FK_ArrayTypeMismatch);
+ else if (Initializer->HasSideEffects(S.Context))
+ SetFailed(FK_NonConstantArrayInit);
+ else {
+ setSequenceKind(ArrayInit);
+ AddArrayInitStep(DestType);
+ }
+ } else if (DestAT->getElementType()->isAnyCharacterType())
SetFailed(FK_ArrayNeedsInitListOrStringLiteral);
else
SetFailed(FK_ArrayNeedsInitList);
@@ -3482,6 +3547,8 @@ static ExprResult CopyObject(Sema &S,
return S.Owned(CurInitExpr);
}
+ S.MarkDeclarationReferenced(Loc, Constructor);
+
// Determine the arguments required to actually perform the
// constructor call (we might have derived-to-base conversions, or
// the copy constructor may have default arguments).
@@ -3616,7 +3683,8 @@ InitializationSequence::Perform(Sema &S,
case SK_ListInitialization:
case SK_CAssignment:
case SK_StringInit:
- case SK_ObjCObjectConversion: {
+ case SK_ObjCObjectConversion:
+ case SK_ArrayInit: {
assert(Args.size() == 1);
Expr *CurInitExpr = Args.get()[0];
if (!CurInitExpr) return ExprError();
@@ -4029,7 +4097,8 @@ InitializationSequence::Perform(Sema &S,
case SK_StringInit: {
QualType Ty = Step->Type;
- CheckStringInit(CurInitExpr, ResultType ? *ResultType : Ty, S);
+ CheckStringInit(CurInitExpr, ResultType ? *ResultType : Ty,
+ S.Context.getAsArrayType(Ty), S);
break;
}
@@ -4040,6 +4109,30 @@ InitializationSequence::Perform(Sema &S,
CurInit.release();
CurInit = S.Owned(CurInitExpr);
break;
+
+ case SK_ArrayInit:
+ // Okay: we checked everything before creating this step. Note that
+ // this is a GNU extension.
+ S.Diag(Kind.getLocation(), diag::ext_array_init_copy)
+ << Step->Type << CurInitExpr->getType()
+ << CurInitExpr->getSourceRange();
+
+ // If the destination type is an incomplete array type, update the
+ // type accordingly.
+ if (ResultType) {
+ if (const IncompleteArrayType *IncompleteDest
+ = S.Context.getAsIncompleteArrayType(Step->Type)) {
+ if (const ConstantArrayType *ConstantSource
+ = S.Context.getAsConstantArrayType(CurInitExpr->getType())) {
+ *ResultType = S.Context.getConstantArrayType(
+ IncompleteDest->getElementType(),
+ ConstantSource->getSize(),
+ ArrayType::Normal, 0);
+ }
+ }
+ }
+
+ break;
}
}
@@ -4081,6 +4174,17 @@ bool InitializationSequence::Diagnose(Sema &S,
<< (Failure == FK_ArrayNeedsInitListOrStringLiteral);
break;
+ case FK_ArrayTypeMismatch:
+ case FK_NonConstantArrayInit:
+ S.Diag(Kind.getLocation(),
+ (Failure == FK_ArrayTypeMismatch
+ ? diag::err_array_init_different_type
+ : diag::err_array_init_non_constant_array))
+ << DestType.getNonReferenceType()
+ << Args[0]->getType()
+ << Args[0]->getSourceRange();
+ break;
+
case FK_AddressOfOverloadFailed: {
DeclAccessPair Found;
S.ResolveAddressOfOverloadedFunction(Args[0],
@@ -4338,6 +4442,14 @@ void InitializationSequence::dump(llvm::raw_ostream &OS) const {
OS << "array requires initializer list or string literal";
break;
+ case FK_ArrayTypeMismatch:
+ OS << "array type mismatch";
+ break;
+
+ case FK_NonConstantArrayInit:
+ OS << "non-constant array initializer";
+ break;
+
case FK_AddressOfOverloadFailed:
OS << "address of overloaded function failed";
break;
@@ -4441,6 +4553,10 @@ void InitializationSequence::dump(llvm::raw_ostream &OS) const {
case StringInit:
OS << "String initialization: ";
break;
+
+ case ArrayInit:
+ OS << "Array initialization: ";
+ break;
}
for (step_iterator S = step_begin(), SEnd = step_end(); S != SEnd; ++S) {
@@ -4520,6 +4636,10 @@ void InitializationSequence::dump(llvm::raw_ostream &OS) const {
case SK_ObjCObjectConversion:
OS << "Objective-C object conversion";
break;
+
+ case SK_ArrayInit:
+ OS << "array initialization";
+ break;
}
}
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp
index 0fd0e08..3deb403 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp
@@ -18,6 +18,7 @@
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/TemplateDeduction.h"
+#include "clang/Sema/ExternalSemaSource.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/Decl.h"
@@ -1132,7 +1133,11 @@ bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) {
if (AllowBuiltinCreation)
return LookupBuiltin(*this, R);
- return false;
+ // If we didn't find a use of this identifier, the ExternalSource
+ // may be able to handle the situation.
+ // Note: some lookup failures are expected!
+ // See e.g. R.isForRedeclaration().
+ return (ExternalSource && ExternalSource->LookupUnqualified(R, S));
}
/// @brief Perform qualified name lookup in the namespaces nominated by
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp
index 6fb789c..8d03285 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp
@@ -2261,6 +2261,8 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
// Record the standard conversion we used and the conversion function.
if (CXXConstructorDecl *Constructor
= dyn_cast<CXXConstructorDecl>(Best->Function)) {
+ S.MarkDeclarationReferenced(From->getLocStart(), Constructor);
+
// C++ [over.ics.user]p1:
// If the user-defined conversion is specified by a
// constructor (12.3.1), the initial standard conversion
@@ -2282,6 +2284,8 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
return OR_Success;
} else if (CXXConversionDecl *Conversion
= dyn_cast<CXXConversionDecl>(Best->Function)) {
+ S.MarkDeclarationReferenced(From->getLocStart(), Conversion);
+
// C++ [over.ics.user]p1:
//
// [...] If the user-defined conversion is specified by a
@@ -3068,6 +3072,8 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS,
if (!Best->FinalConversion.DirectBinding)
return false;
+ if (Best->Function)
+ S.MarkDeclarationReferenced(DeclLoc, Best->Function);
ICS.setUserDefined();
ICS.UserDefined.Before = Best->Conversions[0].Standard;
ICS.UserDefined.After = Best->FinalConversion;
@@ -6280,15 +6286,6 @@ OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc,
Best->Function->getAttr<UnavailableAttr>()))
return OR_Deleted;
- // C++ [basic.def.odr]p2:
- // An overloaded function is used if it is selected by overload resolution
- // when referred to from a potentially-evaluated expression. [Note: this
- // covers calls to named functions (5.2.2), operator overloading
- // (clause 13), user-defined conversions (12.3.2), allocation function for
- // placement new (5.3.4), as well as non-default initialization (8.5).
- if (Best->Function)
- S.MarkDeclarationReferenced(Loc, Best->Function);
-
return OR_Success;
}
@@ -7078,16 +7075,6 @@ void OverloadCandidateSet::NoteCandidates(Sema &S,
S.Diag(OpLoc, diag::note_ovl_too_many_candidates) << int(E - I);
}
-static bool CheckUnresolvedAccess(Sema &S, OverloadExpr *E, DeclAccessPair D) {
- if (isa<UnresolvedLookupExpr>(E))
- return S.CheckUnresolvedLookupAccess(cast<UnresolvedLookupExpr>(E), D);
-
- return S.CheckUnresolvedMemberAccess(cast<UnresolvedMemberExpr>(E), D);
-}
-
-
-
-
// [PossiblyAFunctionType] --> [Return]
// NonFunctionType --> NonFunctionType
// R (A) --> R(A)
@@ -7603,10 +7590,9 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
SourceLocation RParenLoc) {
CXXScopeSpec SS;
- if (ULE->getQualifier()) {
- SS.setScopeRep(ULE->getQualifier());
- SS.setRange(ULE->getQualifierRange());
- }
+ if (ULE->getQualifier())
+ SS.MakeTrivial(SemaRef.Context,
+ ULE->getQualifier(), ULE->getQualifierRange());
TemplateArgumentListInfo TABuffer;
const TemplateArgumentListInfo *ExplicitTemplateArgs = 0;
@@ -7691,6 +7677,7 @@ Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE,
switch (CandidateSet.BestViableFunction(*this, Fn->getLocStart(), Best)) {
case OR_Success: {
FunctionDecl *FDecl = Best->Function;
+ MarkDeclarationReferenced(Fn->getExprLoc(), FDecl);
CheckUnresolvedLookupAccess(ULE, Best->FoundDecl);
DiagnoseUseOfDecl(FDecl? FDecl : Best->FoundDecl.getDecl(),
ULE->getNameLoc());
@@ -7713,11 +7700,15 @@ Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE,
break;
case OR_Deleted:
- Diag(Fn->getSourceRange().getBegin(), diag::err_ovl_deleted_call)
- << Best->Function->isDeleted()
- << ULE->getName()
- << Fn->getSourceRange();
- CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs);
+ {
+ Diag(Fn->getSourceRange().getBegin(), diag::err_ovl_deleted_call)
+ << Best->Function->isDeleted()
+ << ULE->getName()
+ << Best->Function->getMessageUnavailableAttr(
+ !Best->Function->isDeleted())
+ << Fn->getSourceRange();
+ CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs);
+ }
break;
}
@@ -7824,6 +7815,8 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn,
// We matched an overloaded operator. Build a call to that
// operator.
+ MarkDeclarationReferenced(OpLoc, FnDecl);
+
// Convert the arguments.
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) {
CheckMemberOperatorAccess(OpLoc, Args[0], 0, Best->FoundDecl);
@@ -7895,6 +7888,8 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn,
Diag(OpLoc, diag::err_ovl_deleted_oper)
<< Best->Function->isDeleted()
<< UnaryOperator::getOpcodeStr(Opc)
+ << Best->Function->getMessageUnavailableAttr(
+ !Best->Function->isDeleted())
<< Input->getSourceRange();
CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs);
return ExprError();
@@ -8047,6 +8042,8 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
// We matched an overloaded operator. Build a call to that
// operator.
+ MarkDeclarationReferenced(OpLoc, FnDecl);
+
// Convert the arguments.
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) {
// Best->Access is only meaningful for class members.
@@ -8161,6 +8158,8 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
Diag(OpLoc, diag::err_ovl_deleted_oper)
<< Best->Function->isDeleted()
<< BinaryOperator::getOpcodeStr(Opc)
+ << Best->Function->getMessageUnavailableAttr(
+ !Best->Function->isDeleted())
<< Args[0]->getSourceRange() << Args[1]->getSourceRange();
CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, 2);
return ExprError();
@@ -8228,6 +8227,8 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
// We matched an overloaded operator. Build a call to that
// operator.
+ MarkDeclarationReferenced(LLoc, FnDecl);
+
CheckMemberOperatorAccess(LLoc, Args[0], Args[1], Best->FoundDecl);
DiagnoseUseOfDecl(Best->FoundDecl, LLoc);
@@ -8307,6 +8308,8 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
case OR_Deleted:
Diag(LLoc, diag::err_ovl_deleted_oper)
<< Best->Function->isDeleted() << "[]"
+ << Best->Function->getMessageUnavailableAttr(
+ !Best->Function->isDeleted())
<< Args[0]->getSourceRange() << Args[1]->getSourceRange();
CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, 2,
"[]", LLoc);
@@ -8399,6 +8402,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
Best)) {
case OR_Success:
Method = cast<CXXMethodDecl>(Best->Function);
+ MarkDeclarationReferenced(UnresExpr->getMemberLoc(), Method);
FoundDecl = Best->FoundDecl;
CheckUnresolvedMemberAccess(UnresExpr, Best->FoundDecl);
DiagnoseUseOfDecl(Best->FoundDecl, UnresExpr->getNameLoc());
@@ -8422,7 +8426,10 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
case OR_Deleted:
Diag(UnresExpr->getMemberLoc(), diag::err_ovl_deleted_member_call)
<< Best->Function->isDeleted()
- << DeclName << MemExprE->getSourceRange();
+ << DeclName
+ << Best->Function->getMessageUnavailableAttr(
+ !Best->Function->isDeleted())
+ << MemExprE->getSourceRange();
CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs);
// FIXME: Leaking incoming expressions!
return ExprError();
@@ -8594,7 +8601,10 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
Diag(Object->getSourceRange().getBegin(),
diag::err_ovl_deleted_object_call)
<< Best->Function->isDeleted()
- << Object->getType() << Object->getSourceRange();
+ << Object->getType()
+ << Best->Function->getMessageUnavailableAttr(
+ !Best->Function->isDeleted())
+ << Object->getSourceRange();
CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs);
break;
}
@@ -8626,6 +8636,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
RParenLoc);
}
+ MarkDeclarationReferenced(LParenLoc, Best->Function);
CheckMemberOperatorAccess(LParenLoc, Object, 0, Best->FoundDecl);
DiagnoseUseOfDecl(Best->FoundDecl, LParenLoc);
@@ -8799,11 +8810,15 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc) {
case OR_Deleted:
Diag(OpLoc, diag::err_ovl_deleted_oper)
<< Best->Function->isDeleted()
- << "->" << Base->getSourceRange();
+ << "->"
+ << Best->Function->getMessageUnavailableAttr(
+ !Best->Function->isDeleted())
+ << Base->getSourceRange();
CandidateSet.NoteCandidates(*this, OCD_AllCandidates, &Base, 1);
return ExprError();
}
+ MarkDeclarationReferenced(OpLoc, Best->Function);
CheckMemberOperatorAccess(OpLoc, Base, 0, Best->FoundDecl);
DiagnoseUseOfDecl(Best->FoundDecl, OpLoc);
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp
index e995e8f..89957e6 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp
@@ -25,6 +25,7 @@
#include "clang/AST/TypeLoc.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Basic/TargetInfo.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
using namespace clang;
@@ -92,6 +93,8 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) {
unsigned DiagID = diag::warn_unused_expr;
if (const ExprWithCleanups *Temps = dyn_cast<ExprWithCleanups>(E))
E = Temps->getSubExpr();
+ if (const CXXBindTemporaryExpr *TempExpr = dyn_cast<CXXBindTemporaryExpr>(E))
+ E = TempExpr->getSubExpr();
E = E->IgnoreParenImpCasts();
if (const CallExpr *CE = dyn_cast<CallExpr>(E)) {
@@ -143,7 +146,7 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) {
}
}
- DiagRuntimeBehavior(Loc, PDiag(DiagID) << R1 << R2);
+ DiagRuntimeBehavior(Loc, 0, PDiag(DiagID) << R1 << R2);
}
StmtResult
@@ -499,8 +502,7 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
bool HasDependentValue
= CondExpr->isTypeDependent() || CondExpr->isValueDependent();
unsigned CondWidth
- = HasDependentValue? 0
- : static_cast<unsigned>(Context.getTypeSize(CondTypeBeforePromotion));
+ = HasDependentValue ? 0 : Context.getIntWidth(CondTypeBeforePromotion);
bool CondIsSigned = CondTypeBeforePromotion->isSignedIntegerType();
// Accumulate all of the case values in a vector so that we can sort them
@@ -1392,19 +1394,29 @@ static bool CheckAsmLValue(const Expr *E, Sema &S) {
return true;
}
+/// isOperandMentioned - Return true if the specified operand # is mentioned
+/// anywhere in the decomposed asm string.
+static bool isOperandMentioned(unsigned OpNo,
+ llvm::ArrayRef<AsmStmt::AsmStringPiece> AsmStrPieces) {
+ for (unsigned p = 0, e = AsmStrPieces.size(); p != e; ++p) {
+ const AsmStmt::AsmStringPiece &Piece = AsmStrPieces[p];
+ if (!Piece.isOperand()) continue;
+
+ // If this is a reference to the input and if the input was the smaller
+ // one, then we have to reject this asm.
+ if (Piece.getOperandNo() == OpNo)
+ return true;
+ }
+
+ return false;
+}
-StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc,
- bool IsSimple,
- bool IsVolatile,
- unsigned NumOutputs,
- unsigned NumInputs,
- IdentifierInfo **Names,
- MultiExprArg constraints,
- MultiExprArg exprs,
- Expr *asmString,
- MultiExprArg clobbers,
- SourceLocation RParenLoc,
- bool MSAsm) {
+StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, bool IsSimple,
+ bool IsVolatile, unsigned NumOutputs,
+ unsigned NumInputs, IdentifierInfo **Names,
+ MultiExprArg constraints, MultiExprArg exprs,
+ Expr *asmString, MultiExprArg clobbers,
+ SourceLocation RParenLoc, bool MSAsm) {
unsigned NumClobbers = clobbers.size();
StringLiteral **Constraints =
reinterpret_cast<StringLiteral**>(constraints.get());
@@ -1529,8 +1541,9 @@ StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc,
if (!Info.hasTiedOperand()) continue;
unsigned TiedTo = Info.getTiedOperand();
+ unsigned InputOpNo = i+NumOutputs;
Expr *OutputExpr = Exprs[TiedTo];
- Expr *InputExpr = Exprs[i+NumOutputs];
+ Expr *InputExpr = Exprs[InputOpNo];
QualType InTy = InputExpr->getType();
QualType OutTy = OutputExpr->getType();
if (Context.hasSameType(InTy, OutTy))
@@ -1569,30 +1582,22 @@ StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc,
continue;
// If the smaller input/output operand is not mentioned in the asm string,
- // then we can promote it and the asm string won't notice. Check this
- // case now.
+ // then we can promote the smaller one to a larger input and the asm string
+ // won't notice.
bool SmallerValueMentioned = false;
- for (unsigned p = 0, e = Pieces.size(); p != e; ++p) {
- AsmStmt::AsmStringPiece &Piece = Pieces[p];
- if (!Piece.isOperand()) continue;
-
- // If this is a reference to the input and if the input was the smaller
- // one, then we have to reject this asm.
- if (Piece.getOperandNo() == i+NumOutputs) {
- if (InSize < OutSize) {
- SmallerValueMentioned = true;
- break;
- }
- }
-
- // If this is a reference to the input and if the input was the smaller
- // one, then we have to reject this asm.
- if (Piece.getOperandNo() == TiedTo) {
- if (InSize > OutSize) {
- SmallerValueMentioned = true;
- break;
- }
- }
+
+ // If this is a reference to the input and if the input was the smaller
+ // one, then we have to reject this asm.
+ if (isOperandMentioned(InputOpNo, Pieces)) {
+ // This is a use in the asm string of the smaller operand. Since we
+ // codegen this by promoting to a wider value, the asm will get printed
+ // "wrong".
+ SmallerValueMentioned |= InSize < OutSize;
+ }
+ if (isOperandMentioned(TiedTo, Pieces)) {
+ // If this is a reference to the output, and if the output is the larger
+ // value, then it's ok because we'll promote the input to the larger type.
+ SmallerValueMentioned |= OutSize < InSize;
}
// If the smaller value wasn't mentioned in the asm string, and if the
@@ -1601,7 +1606,20 @@ StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc,
if (!SmallerValueMentioned && InputDomain != AD_Other &&
OutputConstraintInfos[TiedTo].allowsRegister())
continue;
-
+
+ // Either both of the operands were mentioned or the smaller one was
+ // mentioned. One more special case that we'll allow: if the tied input is
+ // integer, unmentioned, and is a constant, then we'll allow truncating it
+ // down to the size of the destination.
+ if (InputDomain == AD_Int && OutputDomain == AD_Int &&
+ !isOperandMentioned(InputOpNo, Pieces) &&
+ InputExpr->isEvaluatable(Context)) {
+ ImpCastExprToType(InputExpr, OutTy, CK_IntegralCast);
+ Exprs[InputOpNo] = InputExpr;
+ NS->setInputExpr(i, InputExpr);
+ continue;
+ }
+
Diag(InputExpr->getLocStart(),
diag::err_asm_tying_incompatible_types)
<< InTy << OutTy << OutputExpr->getSourceRange()
@@ -1747,8 +1765,10 @@ public:
StmtResult
Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock,
MultiStmtArg RawHandlers) {
- if (!getLangOptions().Exceptions)
- Diag(TryLoc, diag::err_exceptions_disabled) << "try";
+ // Don't report an error if 'try' is used in system headers.
+ if (!getLangOptions().Exceptions &&
+ !getSourceManager().isInSystemHeader(TryLoc))
+ Diag(TryLoc, diag::err_exceptions_disabled) << "try";
unsigned NumHandlers = RawHandlers.size();
assert(NumHandlers > 0 &&
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp
index f0a0103..f02dd25 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp
@@ -400,8 +400,7 @@ Sema::BuildDependentDeclRefExpr(const CXXScopeSpec &SS,
const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *TemplateArgs) {
return Owned(DependentScopeDeclRefExpr::Create(Context,
- static_cast<NestedNameSpecifier*>(SS.getScopeRep()),
- SS.getRange(),
+ SS.getWithLocInContext(Context),
NameInfo,
TemplateArgs));
}
@@ -783,8 +782,7 @@ Sema::ActOnTemplateParameterList(unsigned Depth,
static void SetNestedNameSpecifier(TagDecl *T, const CXXScopeSpec &SS) {
if (SS.isSet())
- T->setQualifierInfo(static_cast<NestedNameSpecifier*>(SS.getScopeRep()),
- SS.getRange());
+ T->setQualifierInfo(SS.getWithLocInContext(T->getASTContext()));
}
DeclResult
@@ -2333,9 +2331,13 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
DeclarationNameInfo NameInfo(DTN->getIdentifier(),
Arg.getTemplateNameLoc());
+ // FIXME: TemplateArgumentLoc should store a NestedNameSpecifierLoc
+ // for the template name.
+ CXXScopeSpec SS;
+ SS.MakeTrivial(Context, DTN->getQualifier(),
+ Arg.getTemplateQualifierRange());
Expr *E = DependentScopeDeclRefExpr::Create(Context,
- DTN->getQualifier(),
- Arg.getTemplateQualifierRange(),
+ SS.getWithLocInContext(Context),
NameInfo);
// If we parsed the template argument as a pack expansion, create a
@@ -2868,6 +2870,7 @@ bool UnnamedLocalNoLinkageFinder::VisitNestedNameSpecifier(
switch (NNS->getKind()) {
case NestedNameSpecifier::Identifier:
case NestedNameSpecifier::Namespace:
+ case NestedNameSpecifier::NamespaceAlias:
case NestedNameSpecifier::Global:
return false;
@@ -3610,7 +3613,7 @@ Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg,
= NestedNameSpecifier::Create(Context, 0, false,
ClassType.getTypePtr());
CXXScopeSpec SS;
- SS.setScopeRep(Qualifier);
+ SS.MakeTrivial(Context, Qualifier, Loc);
// The actual value-ness of this is unimportant, but for
// internal consistency's sake, references to instance methods
@@ -5997,8 +6000,7 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
SourceLocation KeywordLoc, SourceRange NNSRange,
SourceLocation IILoc) {
CXXScopeSpec SS;
- SS.setScopeRep(NNS);
- SS.setRange(NNSRange);
+ SS.MakeTrivial(Context, NNS, NNSRange);
DeclContext *Ctx = computeDeclContext(SS);
if (!Ctx) {
@@ -6036,7 +6038,7 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
<< Name << Ctx << FullRange;
if (UnresolvedUsingValueDecl *Using
= dyn_cast<UnresolvedUsingValueDecl>(Result.getRepresentativeDecl())){
- SourceLocation Loc = Using->getTargetNestedNameRange().getBegin();
+ SourceLocation Loc = Using->getQualifierLoc().getBeginLoc();
Diag(Loc, diag::note_using_value_decl_missing_typename)
<< FixItHint::CreateInsertion(Loc, "typename ");
}
@@ -6168,16 +6170,18 @@ ExprResult Sema::RebuildExprInCurrentInstantiation(Expr *E) {
}
bool Sema::RebuildNestedNameSpecifierInCurrentInstantiation(CXXScopeSpec &SS) {
- if (SS.isInvalid()) return true;
+ if (SS.isInvalid())
+ return true;
- NestedNameSpecifier *NNS = static_cast<NestedNameSpecifier*>(SS.getScopeRep());
+ NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context);
CurrentInstantiationRebuilder Rebuilder(*this, SS.getRange().getBegin(),
DeclarationName());
- NestedNameSpecifier *Rebuilt =
- Rebuilder.TransformNestedNameSpecifier(NNS, SS.getRange());
- if (!Rebuilt) return true;
+ NestedNameSpecifierLoc Rebuilt
+ = Rebuilder.TransformNestedNameSpecifierLoc(QualifierLoc);
+ if (!Rebuilt)
+ return true;
- SS.setScopeRep(Rebuilt);
+ SS.Adopt(Rebuilt);
return false;
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp
index bd0a618..139fafb 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -3004,12 +3004,12 @@ Sema::DeduceAutoType(QualType Type, Expr *Init, QualType &Result) {
LocalInstantiationScope InstScope(*this);
// Build template<class TemplParam> void Func(FuncParam);
- NamedDecl *TemplParam
- = TemplateTypeParmDecl::Create(Context, 0, Loc, 0, 0, 0, false, false);
- TemplateParameterList *TemplateParams
- = TemplateParameterList::Create(Context, Loc, Loc, &TemplParam, 1, Loc);
-
QualType TemplArg = Context.getTemplateTypeParmType(0, 0, false);
+ TemplateTypeParmDecl TemplParam(0, Loc, 0, false, TemplArg, false);
+ NamedDecl *TemplParamPtr = &TemplParam;
+ FixedSizeTemplateParameterList<1> TemplateParams(Loc, Loc, &TemplParamPtr,
+ Loc);
+
QualType FuncParam =
SubstituteAutoTransform(*this, TemplArg).TransformType(Type);
@@ -3018,13 +3018,13 @@ Sema::DeduceAutoType(QualType Type, Expr *Init, QualType &Result) {
Deduced.resize(1);
QualType InitType = Init->getType();
unsigned TDF = 0;
- if (AdjustFunctionParmAndArgTypesForDeduction(*this, TemplateParams,
+ if (AdjustFunctionParmAndArgTypesForDeduction(*this, &TemplateParams,
FuncParam, InitType, Init,
TDF))
return false;
TemplateDeductionInfo Info(Context, Loc);
- if (::DeduceTemplateArguments(*this, TemplateParams,
+ if (::DeduceTemplateArguments(*this, &TemplateParams,
FuncParam, InitType, Info, Deduced,
TDF))
return false;
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 44f5913..ae0ac9c 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -2140,6 +2140,17 @@ Sema::SubstNestedNameSpecifier(NestedNameSpecifier *NNS,
return Instantiator.TransformNestedNameSpecifier(NNS, Range);
}
+NestedNameSpecifierLoc
+Sema::SubstNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
+ const MultiLevelTemplateArgumentList &TemplateArgs) {
+ if (!NNS)
+ return NestedNameSpecifierLoc();
+
+ TemplateInstantiator Instantiator(*this, TemplateArgs, NNS.getBeginLoc(),
+ DeclarationName());
+ return Instantiator.TransformNestedNameSpecifierLoc(NNS);
+}
+
/// \brief Do template substitution on declaration name info.
DeclarationNameInfo
Sema::SubstDeclarationNameInfo(const DeclarationNameInfo &NameInfo,
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index c0150c0..3a40b6f 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -27,33 +27,33 @@ using namespace clang;
bool TemplateDeclInstantiator::SubstQualifier(const DeclaratorDecl *OldDecl,
DeclaratorDecl *NewDecl) {
- NestedNameSpecifier *OldQual = OldDecl->getQualifier();
- if (!OldQual) return false;
-
- SourceRange QualRange = OldDecl->getQualifierRange();
-
- NestedNameSpecifier *NewQual
- = SemaRef.SubstNestedNameSpecifier(OldQual, QualRange, TemplateArgs);
- if (!NewQual)
+ if (!OldDecl->getQualifierLoc())
+ return false;
+
+ NestedNameSpecifierLoc NewQualifierLoc
+ = SemaRef.SubstNestedNameSpecifierLoc(OldDecl->getQualifierLoc(),
+ TemplateArgs);
+
+ if (!NewQualifierLoc)
return true;
-
- NewDecl->setQualifierInfo(NewQual, QualRange);
+
+ NewDecl->setQualifierInfo(NewQualifierLoc);
return false;
}
bool TemplateDeclInstantiator::SubstQualifier(const TagDecl *OldDecl,
TagDecl *NewDecl) {
- NestedNameSpecifier *OldQual = OldDecl->getQualifier();
- if (!OldQual) return false;
-
- SourceRange QualRange = OldDecl->getQualifierRange();
-
- NestedNameSpecifier *NewQual
- = SemaRef.SubstNestedNameSpecifier(OldQual, QualRange, TemplateArgs);
- if (!NewQual)
+ if (!OldDecl->getQualifierLoc())
+ return false;
+
+ NestedNameSpecifierLoc NewQualifierLoc
+ = SemaRef.SubstNestedNameSpecifierLoc(OldDecl->getQualifierLoc(),
+ TemplateArgs);
+
+ if (!NewQualifierLoc)
return true;
-
- NewDecl->setQualifierInfo(NewQual, QualRange);
+
+ NewDecl->setQualifierInfo(NewQualifierLoc);
return false;
}
@@ -120,9 +120,8 @@ TemplateDeclInstantiator::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
= NamespaceAliasDecl::Create(SemaRef.Context, Owner,
D->getNamespaceLoc(),
D->getAliasLoc(),
- D->getNamespace()->getIdentifier(),
- D->getQualifierRange(),
- D->getQualifier(),
+ D->getIdentifier(),
+ D->getQualifierLoc(),
D->getTargetNameLoc(),
D->getNamespace());
Owner->addDecl(Inst);
@@ -642,12 +641,12 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
// Instantiate the qualifier. We have to do this first in case
// we're a friend declaration, because if we are then we need to put
// the new declaration in the appropriate context.
- NestedNameSpecifier *Qualifier = Pattern->getQualifier();
- if (Qualifier) {
- Qualifier = SemaRef.SubstNestedNameSpecifier(Qualifier,
- Pattern->getQualifierRange(),
- TemplateArgs);
- if (!Qualifier) return 0;
+ NestedNameSpecifierLoc QualifierLoc = Pattern->getQualifierLoc();
+ if (QualifierLoc) {
+ QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc,
+ TemplateArgs);
+ if (!QualifierLoc)
+ return 0;
}
CXXRecordDecl *PrevDecl = 0;
@@ -668,10 +667,9 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
// the appropriate context.
DeclContext *DC = Owner;
if (isFriend) {
- if (Qualifier) {
+ if (QualifierLoc) {
CXXScopeSpec SS;
- SS.setScopeRep(Qualifier);
- SS.setRange(Pattern->getQualifierRange());
+ SS.Adopt(QualifierLoc);
DC = SemaRef.computeDeclContext(SS);
if (!DC) return 0;
} else {
@@ -692,10 +690,10 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
PrevDecl = PrevClassTemplate->getTemplatedDecl();
}
- if (!PrevClassTemplate && Qualifier) {
+ if (!PrevClassTemplate && QualifierLoc) {
SemaRef.Diag(Pattern->getLocation(), diag::err_not_tag_in_scope)
<< D->getTemplatedDecl()->getTagKind() << Pattern->getDeclName() << DC
- << Pattern->getQualifierRange();
+ << QualifierLoc.getSourceRange();
return 0;
}
@@ -756,8 +754,8 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
Pattern->getTagKeywordLoc(), PrevDecl,
/*DelayTypeCreation=*/true);
- if (Qualifier)
- RecordInst->setQualifierInfo(Qualifier, Pattern->getQualifierRange());
+ if (QualifierLoc)
+ RecordInst->setQualifierInfo(QualifierLoc);
ClassTemplateDecl *Inst
= ClassTemplateDecl::Create(SemaRef.Context, DC, D->getLocation(),
@@ -969,12 +967,12 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
return 0;
QualType T = TInfo->getType();
- NestedNameSpecifier *Qualifier = D->getQualifier();
- if (Qualifier) {
- Qualifier = SemaRef.SubstNestedNameSpecifier(Qualifier,
- D->getQualifierRange(),
- TemplateArgs);
- if (!Qualifier) return 0;
+ NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc();
+ if (QualifierLoc) {
+ QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc,
+ TemplateArgs);
+ if (!QualifierLoc)
+ return 0;
}
// If we're instantiating a local function declaration, put the result
@@ -982,10 +980,9 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
DeclContext *DC;
if (D->getDeclContext()->isFunctionOrMethod())
DC = Owner;
- else if (isFriend && Qualifier) {
+ else if (isFriend && QualifierLoc) {
CXXScopeSpec SS;
- SS.setScopeRep(Qualifier);
- SS.setRange(D->getQualifierRange());
+ SS.Adopt(QualifierLoc);
DC = SemaRef.computeDeclContext(SS);
if (!DC) return 0;
} else {
@@ -999,8 +996,8 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
D->getStorageClass(), D->getStorageClassAsWritten(),
D->isInlineSpecified(), D->hasWrittenPrototype());
- if (Qualifier)
- Function->setQualifierInfo(Qualifier, D->getQualifierRange());
+ if (QualifierLoc)
+ Function->setQualifierInfo(QualifierLoc);
DeclContext *LexicalDC = Owner;
if (!isFriend && D->isOutOfLine()) {
@@ -1262,20 +1259,19 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
return 0;
}
- NestedNameSpecifier *Qualifier = D->getQualifier();
- if (Qualifier) {
- Qualifier = SemaRef.SubstNestedNameSpecifier(Qualifier,
- D->getQualifierRange(),
+ NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc();
+ if (QualifierLoc) {
+ QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc,
TemplateArgs);
- if (!Qualifier) return 0;
+ if (!QualifierLoc)
+ return 0;
}
DeclContext *DC = Owner;
if (isFriend) {
- if (Qualifier) {
+ if (QualifierLoc) {
CXXScopeSpec SS;
- SS.setScopeRep(Qualifier);
- SS.setRange(D->getQualifierRange());
+ SS.Adopt(QualifierLoc);
DC = SemaRef.computeDeclContext(SS);
if (DC && SemaRef.RequireCompleteDeclContext(SS, DC))
@@ -1318,8 +1314,8 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
D->isInlineSpecified());
}
- if (Qualifier)
- Method->setQualifierInfo(Qualifier, D->getQualifierRange());
+ if (QualifierLoc)
+ Method->setQualifierInfo(QualifierLoc);
if (TemplateParams) {
// Our resulting instantiation is actually a function template, since we
@@ -1641,12 +1637,13 @@ TemplateDeclInstantiator::VisitTemplateTemplateParmDecl(
}
Decl *TemplateDeclInstantiator::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
- // Using directives are never dependent, so they require no explicit
+ // Using directives are never dependent (and never contain any types or
+ // expressions), so they require no explicit instantiation work.
UsingDirectiveDecl *Inst
= UsingDirectiveDecl::Create(SemaRef.Context, Owner, D->getLocation(),
D->getNamespaceKeyLocation(),
- D->getQualifierRange(), D->getQualifier(),
+ D->getQualifierLoc(),
D->getIdentLocation(),
D->getNominatedNamespace(),
D->getCommonAncestor());
@@ -1664,12 +1661,11 @@ Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) {
// template struct t<int>;
// Here, in using s1::f1, s1 refers to t<T>::s1;
// we need to substitute for t<int>::s1.
- NestedNameSpecifier *NNS =
- SemaRef.SubstNestedNameSpecifier(D->getTargetNestedNameDecl(),
- D->getNestedNameRange(),
- TemplateArgs);
- if (!NNS)
- return 0;
+ NestedNameSpecifierLoc QualifierLoc
+ = SemaRef.SubstNestedNameSpecifierLoc(D->getQualifierLoc(),
+ TemplateArgs);
+ if (!QualifierLoc)
+ return 0;
// The name info is non-dependent, so no transformation
// is required.
@@ -1684,16 +1680,13 @@ Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) {
Sema::ForRedeclaration);
UsingDecl *NewUD = UsingDecl::Create(SemaRef.Context, Owner,
- D->getNestedNameRange(),
D->getUsingLocation(),
- NNS,
+ QualifierLoc,
NameInfo,
D->isTypeName());
CXXScopeSpec SS;
- SS.setScopeRep(NNS);
- SS.setRange(D->getNestedNameRange());
-
+ SS.Adopt(QualifierLoc);
if (CheckRedeclaration) {
Prev.setHideTags(false);
SemaRef.LookupQualifiedName(Prev, Owner);
@@ -1752,16 +1745,14 @@ Decl *TemplateDeclInstantiator::VisitUsingShadowDecl(UsingShadowDecl *D) {
Decl * TemplateDeclInstantiator
::VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) {
- NestedNameSpecifier *NNS =
- SemaRef.SubstNestedNameSpecifier(D->getTargetNestedNameSpecifier(),
- D->getTargetNestedNameRange(),
- TemplateArgs);
- if (!NNS)
+ NestedNameSpecifierLoc QualifierLoc
+ = SemaRef.SubstNestedNameSpecifierLoc(D->getQualifierLoc(),
+ TemplateArgs);
+ if (!QualifierLoc)
return 0;
CXXScopeSpec SS;
- SS.setRange(D->getTargetNestedNameRange());
- SS.setScopeRep(NNS);
+ SS.Adopt(QualifierLoc);
// Since NameInfo refers to a typename, it cannot be a C++ special name.
// Hence, no tranformation is required for it.
@@ -1779,16 +1770,13 @@ Decl * TemplateDeclInstantiator
Decl * TemplateDeclInstantiator
::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
- NestedNameSpecifier *NNS =
- SemaRef.SubstNestedNameSpecifier(D->getTargetNestedNameSpecifier(),
- D->getTargetNestedNameRange(),
- TemplateArgs);
- if (!NNS)
+ NestedNameSpecifierLoc QualifierLoc
+ = SemaRef.SubstNestedNameSpecifierLoc(D->getQualifierLoc(), TemplateArgs);
+ if (!QualifierLoc)
return 0;
-
+
CXXScopeSpec SS;
- SS.setRange(D->getTargetNestedNameRange());
- SS.setScopeRep(NNS);
+ SS.Adopt(QualifierLoc);
DeclarationNameInfo NameInfo
= SemaRef.SubstDeclarationNameInfo(D->getNameInfo(), TemplateArgs);
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp
index c88baa5..ba80076 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp
@@ -1395,6 +1395,56 @@ QualType Sema::GetTypeFromParser(ParsedType Ty, TypeSourceInfo **TInfo) {
return QT;
}
+static void DiagnoseIgnoredQualifiers(unsigned Quals,
+ SourceLocation ConstQualLoc,
+ SourceLocation VolatileQualLoc,
+ SourceLocation RestrictQualLoc,
+ Sema& S) {
+ std::string QualStr;
+ unsigned NumQuals = 0;
+ SourceLocation Loc;
+
+ FixItHint ConstFixIt;
+ FixItHint VolatileFixIt;
+ FixItHint RestrictFixIt;
+
+ // FIXME: The locations here are set kind of arbitrarily. It'd be nicer to
+ // find a range and grow it to encompass all the qualifiers, regardless of
+ // the order in which they textually appear.
+ if (Quals & Qualifiers::Const) {
+ ConstFixIt = FixItHint::CreateRemoval(ConstQualLoc);
+ Loc = ConstQualLoc;
+ ++NumQuals;
+ QualStr = "const";
+ }
+ if (Quals & Qualifiers::Volatile) {
+ VolatileFixIt = FixItHint::CreateRemoval(VolatileQualLoc);
+ if (NumQuals == 0) {
+ Loc = VolatileQualLoc;
+ QualStr = "volatile";
+ } else {
+ QualStr += " volatile";
+ }
+ ++NumQuals;
+ }
+ if (Quals & Qualifiers::Restrict) {
+ RestrictFixIt = FixItHint::CreateRemoval(RestrictQualLoc);
+ if (NumQuals == 0) {
+ Loc = RestrictQualLoc;
+ QualStr = "restrict";
+ } else {
+ QualStr += " restrict";
+ }
+ ++NumQuals;
+ }
+
+ assert(NumQuals > 0 && "No known qualifiers?");
+
+ S.Diag(Loc, diag::warn_qual_return_type)
+ << QualStr << NumQuals
+ << ConstFixIt << VolatileFixIt << RestrictFixIt;
+}
+
/// GetTypeForDeclarator - Convert the type for the specified
/// declarator to Type instances.
///
@@ -1450,8 +1500,12 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
if (D.getAttributes())
distributeTypeAttrsFromDeclarator(state, T);
+ // C++0x [dcl.spec.auto]p5: reject 'auto' if it is not in an allowed context.
+ // In C++0x, a function declarator using 'auto' must have a trailing return
+ // type (this is checked later) and we can skip this. In other languages
+ // using auto, we need to check regardless.
if (D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto &&
- !D.isFunctionDeclarator()) {
+ (!getLangOptions().CPlusPlus0x || !D.isFunctionDeclarator())) {
int Error = -1;
switch (D.getContext()) {
@@ -1483,7 +1537,7 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
break;
case Declarator::TypeNameContext:
if (!AutoAllowedInTypeName)
- Error = 8; // Generic
+ Error = 10; // Generic
break;
case Declarator::FileContext:
case Declarator::BlockContext:
@@ -1492,6 +1546,32 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
break;
}
+ if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef)
+ Error = 8;
+
+ // In Objective-C it is an error to use 'auto' on a function declarator.
+ if (D.isFunctionDeclarator())
+ Error = 9;
+
+ // C++0x [dcl.spec.auto]p2: 'auto' is always fine if the declarator
+ // contains a trailing return type. That is only legal at the outermost
+ // level. Check all declarator chunks (outermost first) anyway, to give
+ // better diagnostics.
+ if (getLangOptions().CPlusPlus0x && Error != -1) {
+ for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
+ unsigned chunkIndex = e - i - 1;
+ state.setCurrentChunkIndex(chunkIndex);
+ DeclaratorChunk &DeclType = D.getTypeObject(chunkIndex);
+ if (DeclType.Kind == DeclaratorChunk::Function) {
+ const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun;
+ if (FTI.TrailingReturnType) {
+ Error = -1;
+ break;
+ }
+ }
+ }
+ }
+
if (Error != -1) {
Diag(D.getDeclSpec().getTypeSpecTypeLoc(), diag::err_auto_not_allowed)
<< Error;
@@ -1499,7 +1579,7 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
D.setInvalidType(true);
}
}
-
+
if (T.isNull())
return Context.getNullTypeSourceInfo();
@@ -1600,21 +1680,6 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
// of the type, otherwise the argument list is ().
const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun;
- // C99 6.7.5.3p1: The return type may not be a function or array type.
- // For conversion functions, we'll diagnose this particular error later.
- if ((T->isArrayType() || T->isFunctionType()) &&
- (D.getName().getKind() != UnqualifiedId::IK_ConversionFunctionId)) {
- unsigned diagID = diag::err_func_returning_array_function;
- // Last processing chunk in block context means this function chunk
- // represents the block.
- if (chunkIndex == 0 &&
- D.getContext() == Declarator::BlockLiteralContext)
- diagID = diag::err_block_returning_array_function;
- Diag(DeclType.Loc, diagID) << T->isFunctionType() << T;
- T = Context.IntTy;
- D.setInvalidType(true);
- }
-
// Check for auto functions and trailing return type and adjust the
// return type accordingly.
if (!D.isInvalidType()) {
@@ -1627,8 +1692,13 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
T = Context.IntTy;
D.setInvalidType(true);
} else if (FTI.TrailingReturnType) {
- if (T.hasQualifiers() || !isa<AutoType>(T)) {
- // T must be exactly 'auto' at this point. See CWG issue 681.
+ // T must be exactly 'auto' at this point. See CWG issue 681.
+ if (isa<ParenType>(T)) {
+ Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
+ diag::err_trailing_return_in_parens)
+ << T << D.getDeclSpec().getSourceRange();
+ D.setInvalidType(true);
+ } else if (T.hasQualifiers() || !isa<AutoType>(T)) {
Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
diag::err_trailing_return_without_auto)
<< T << D.getDeclSpec().getSourceRange();
@@ -1641,48 +1711,48 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
}
}
+ // C99 6.7.5.3p1: The return type may not be a function or array type.
+ // For conversion functions, we'll diagnose this particular error later.
+ if ((T->isArrayType() || T->isFunctionType()) &&
+ (D.getName().getKind() != UnqualifiedId::IK_ConversionFunctionId)) {
+ unsigned diagID = diag::err_func_returning_array_function;
+ // Last processing chunk in block context means this function chunk
+ // represents the block.
+ if (chunkIndex == 0 &&
+ D.getContext() == Declarator::BlockLiteralContext)
+ diagID = diag::err_block_returning_array_function;
+ Diag(DeclType.Loc, diagID) << T->isFunctionType() << T;
+ T = Context.IntTy;
+ D.setInvalidType(true);
+ }
+
// cv-qualifiers on return types are pointless except when the type is a
// class type in C++.
- if (T.getCVRQualifiers() && D.getDeclSpec().getTypeQualifiers() &&
+ if (T->isPointerType() && T.getCVRQualifiers() &&
+ (!getLangOptions().CPlusPlus || !T->isDependentType())) {
+ assert(chunkIndex + 1 < e && "No DeclaratorChunk for the return type?");
+ DeclaratorChunk ReturnTypeChunk = D.getTypeObject(chunkIndex + 1);
+ assert(ReturnTypeChunk.Kind == DeclaratorChunk::Pointer);
+
+ DeclaratorChunk::PointerTypeInfo &PTI = ReturnTypeChunk.Ptr;
+
+ DiagnoseIgnoredQualifiers(PTI.TypeQuals,
+ SourceLocation::getFromRawEncoding(PTI.ConstQualLoc),
+ SourceLocation::getFromRawEncoding(PTI.VolatileQualLoc),
+ SourceLocation::getFromRawEncoding(PTI.RestrictQualLoc),
+ *this);
+
+ } else if (T.getCVRQualifiers() && D.getDeclSpec().getTypeQualifiers() &&
(!getLangOptions().CPlusPlus ||
(!T->isDependentType() && !T->isRecordType()))) {
- unsigned Quals = D.getDeclSpec().getTypeQualifiers();
- std::string QualStr;
- unsigned NumQuals = 0;
- SourceLocation Loc;
- if (Quals & Qualifiers::Const) {
- Loc = D.getDeclSpec().getConstSpecLoc();
- ++NumQuals;
- QualStr = "const";
- }
- if (Quals & Qualifiers::Volatile) {
- if (NumQuals == 0) {
- Loc = D.getDeclSpec().getVolatileSpecLoc();
- QualStr = "volatile";
- } else
- QualStr += " volatile";
- ++NumQuals;
- }
- if (Quals & Qualifiers::Restrict) {
- if (NumQuals == 0) {
- Loc = D.getDeclSpec().getRestrictSpecLoc();
- QualStr = "restrict";
- } else
- QualStr += " restrict";
- ++NumQuals;
- }
- assert(NumQuals > 0 && "No known qualifiers?");
-
- SemaDiagnosticBuilder DB = Diag(Loc, diag::warn_qual_return_type);
- DB << QualStr << NumQuals;
- if (Quals & Qualifiers::Const)
- DB << FixItHint::CreateRemoval(D.getDeclSpec().getConstSpecLoc());
- if (Quals & Qualifiers::Volatile)
- DB << FixItHint::CreateRemoval(D.getDeclSpec().getVolatileSpecLoc());
- if (Quals & Qualifiers::Restrict)
- DB << FixItHint::CreateRemoval(D.getDeclSpec().getRestrictSpecLoc());
+
+ DiagnoseIgnoredQualifiers(D.getDeclSpec().getTypeQualifiers(),
+ D.getDeclSpec().getConstSpecLoc(),
+ D.getDeclSpec().getVolatileSpecLoc(),
+ D.getDeclSpec().getRestrictSpecLoc(),
+ *this);
}
-
+
if (getLangOptions().CPlusPlus && D.getDeclSpec().isTypeSpecOwned()) {
// C++ [dcl.fct]p6:
// Types shall not be defined in return or parameter types.
@@ -1825,6 +1895,7 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
break;
case NestedNameSpecifier::Namespace:
+ case NestedNameSpecifier::NamespaceAlias:
case NestedNameSpecifier::Global:
llvm_unreachable("Nested-name-specifier must name a type");
break;
@@ -2047,7 +2118,7 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
break;
}
}
-
+
if (T.isNull())
return Context.getNullTypeSourceInfo();
else if (D.isInvalidType())
diff --git a/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h b/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h
index 944e6a1..57a44ad 100644
--- a/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h
+++ b/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h
@@ -385,6 +385,17 @@ public:
QualType ObjectType = QualType(),
NamedDecl *FirstQualifierInScope = 0);
+ /// \brief Transform the given nested-name-specifier with source-location
+ /// information.
+ ///
+ /// By default, transforms all of the types and declarations within the
+ /// nested-name-specifier. Subclasses may override this function to provide
+ /// alternate behavior.
+ NestedNameSpecifierLoc TransformNestedNameSpecifierLoc(
+ NestedNameSpecifierLoc NNS,
+ QualType ObjectType = QualType(),
+ NamedDecl *FirstQualifierInScope = 0);
+
/// \brief Transform the given declaration name.
///
/// By default, transforms the types of conversion function, constructor,
@@ -759,8 +770,7 @@ public:
SourceRange NNSRange,
SourceLocation IdLoc) {
CXXScopeSpec SS;
- SS.setScopeRep(NNS);
- SS.setRange(NNSRange);
+ SS.MakeTrivial(SemaRef.Context, NNS, NNSRange);
if (NNS->isDependent()) {
// If the name is still dependent, just build a new dependent name type.
@@ -878,6 +888,16 @@ public:
NamespaceDecl *NS);
/// \brief Build a new nested-name-specifier given the prefix and the
+ /// namespace alias named in the next step in the nested-name-specifier.
+ ///
+ /// By default, performs semantic analysis when building the new
+ /// nested-name-specifier. Subclasses may override this routine to provide
+ /// different behavior.
+ NestedNameSpecifier *RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix,
+ SourceRange Range,
+ NamespaceAliasDecl *Alias);
+
+ /// \brief Build a new nested-name-specifier given the prefix and the
/// type named in the next step in the nested-name-specifier.
///
/// By default, performs semantic analysis when building the new
@@ -1083,11 +1103,8 @@ public:
StmtResult RebuildDeclStmt(Decl **Decls, unsigned NumDecls,
SourceLocation StartLoc,
SourceLocation EndLoc) {
- return getSema().Owned(
- new (getSema().Context) DeclStmt(
- DeclGroupRef::Create(getSema().Context,
- Decls, NumDecls),
- StartLoc, EndLoc));
+ Sema::DeclGroupPtrTy DG = getSema().BuildDeclaratorGroup(Decls, NumDecls);
+ return getSema().ActOnDeclStmt(DG, StartLoc, EndLoc);
}
/// \brief Build a new inline asm statement.
@@ -1246,8 +1263,7 @@ public:
const DeclarationNameInfo &NameInfo,
TemplateArgumentListInfo *TemplateArgs) {
CXXScopeSpec SS;
- SS.setScopeRep(Qualifier);
- SS.setRange(QualifierRange);
+ SS.MakeTrivial(SemaRef.Context, Qualifier, QualifierRange);
// FIXME: loses template args.
@@ -1268,13 +1284,12 @@ public:
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
ExprResult RebuildCXXPseudoDestructorExpr(Expr *Base,
- SourceLocation OperatorLoc,
- bool isArrow,
- NestedNameSpecifier *Qualifier,
- SourceRange QualifierRange,
- TypeSourceInfo *ScopeType,
- SourceLocation CCLoc,
- SourceLocation TildeLoc,
+ SourceLocation OperatorLoc,
+ bool isArrow,
+ CXXScopeSpec &SS,
+ TypeSourceInfo *ScopeType,
+ SourceLocation CCLoc,
+ SourceLocation TildeLoc,
PseudoDestructorTypeStorage Destroyed);
/// \brief Build a new unary operator expression.
@@ -1386,8 +1401,7 @@ public:
CXXScopeSpec SS;
if (Qualifier) {
- SS.setRange(QualifierRange);
- SS.setScopeRep(Qualifier);
+ SS.MakeTrivial(SemaRef.Context, Qualifier, QualifierRange);
}
getSema().DefaultFunctionArrayConversion(Base);
@@ -1873,13 +1887,12 @@ public:
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- ExprResult RebuildDependentScopeDeclRefExpr(NestedNameSpecifier *NNS,
- SourceRange QualifierRange,
+ ExprResult RebuildDependentScopeDeclRefExpr(
+ NestedNameSpecifierLoc QualifierLoc,
const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *TemplateArgs) {
CXXScopeSpec SS;
- SS.setRange(QualifierRange);
- SS.setScopeRep(NNS);
+ SS.Adopt(QualifierLoc);
if (TemplateArgs)
return getSema().BuildQualifiedTemplateIdExpr(SS, NameInfo,
@@ -1964,8 +1977,7 @@ public:
const DeclarationNameInfo &MemberNameInfo,
const TemplateArgumentListInfo *TemplateArgs) {
CXXScopeSpec SS;
- SS.setRange(QualifierRange);
- SS.setScopeRep(Qualifier);
+ SS.MakeTrivial(SemaRef.Context, Qualifier, QualifierRange);
return SemaRef.BuildMemberReferenceExpr(BaseE, BaseType,
OperatorLoc, IsArrow,
@@ -1988,8 +2000,7 @@ public:
LookupResult &R,
const TemplateArgumentListInfo *TemplateArgs) {
CXXScopeSpec SS;
- SS.setRange(QualifierRange);
- SS.setScopeRep(Qualifier);
+ SS.MakeTrivial(SemaRef.Context, Qualifier, QualifierRange);
return SemaRef.BuildMemberReferenceExpr(BaseE, BaseType,
OperatorLoc, IsArrow,
@@ -2263,6 +2274,11 @@ private:
QualType ObjectType,
NamedDecl *FirstQualifierInScope,
NestedNameSpecifier *Prefix);
+
+ TypeLoc TransformTypeInObjectScope(TypeLoc TL,
+ QualType ObjectType,
+ NamedDecl *FirstQualifierInScope,
+ CXXScopeSpec &SS);
};
template<typename Derived>
@@ -2459,6 +2475,19 @@ TreeTransform<Derived>::TransformNestedNameSpecifier(NestedNameSpecifier *NNS,
return getDerived().RebuildNestedNameSpecifier(Prefix, Range, NS);
}
+ case NestedNameSpecifier::NamespaceAlias: {
+ NamespaceAliasDecl *Alias
+ = cast_or_null<NamespaceAliasDecl>(
+ getDerived().TransformDecl(Range.getBegin(),
+ NNS->getAsNamespaceAlias()));
+ if (!getDerived().AlwaysRebuild() &&
+ Prefix == NNS->getPrefix() &&
+ Alias == NNS->getAsNamespaceAlias())
+ return NNS;
+
+ return getDerived().RebuildNestedNameSpecifier(Prefix, Range, Alias);
+ }
+
case NestedNameSpecifier::Global:
// There is no meaningful transformation that one could perform on the
// global scope.
@@ -2490,6 +2519,103 @@ TreeTransform<Derived>::TransformNestedNameSpecifier(NestedNameSpecifier *NNS,
}
template<typename Derived>
+NestedNameSpecifierLoc
+TreeTransform<Derived>::TransformNestedNameSpecifierLoc(
+ NestedNameSpecifierLoc NNS,
+ QualType ObjectType,
+ NamedDecl *FirstQualifierInScope) {
+ llvm::SmallVector<NestedNameSpecifierLoc, 4> Qualifiers;
+ for (NestedNameSpecifierLoc Qualifier = NNS; Qualifier;
+ Qualifier = Qualifier.getPrefix())
+ Qualifiers.push_back(Qualifier);
+
+ CXXScopeSpec SS;
+ while (!Qualifiers.empty()) {
+ NestedNameSpecifierLoc Q = Qualifiers.pop_back_val();
+ NestedNameSpecifier *QNNS = Q.getNestedNameSpecifier();
+
+ switch (QNNS->getKind()) {
+ case NestedNameSpecifier::Identifier:
+ if (SemaRef.BuildCXXNestedNameSpecifier(/*Scope=*/0,
+ *QNNS->getAsIdentifier(),
+ Q.getLocalBeginLoc(),
+ Q.getLocalEndLoc(),
+ ObjectType, false, SS,
+ FirstQualifierInScope, false))
+ return NestedNameSpecifierLoc();
+
+ break;
+
+ case NestedNameSpecifier::Namespace: {
+ NamespaceDecl *NS
+ = cast_or_null<NamespaceDecl>(
+ getDerived().TransformDecl(
+ Q.getLocalBeginLoc(),
+ QNNS->getAsNamespace()));
+ SS.Extend(SemaRef.Context, NS, Q.getLocalBeginLoc(), Q.getLocalEndLoc());
+ break;
+ }
+
+ case NestedNameSpecifier::NamespaceAlias: {
+ NamespaceAliasDecl *Alias
+ = cast_or_null<NamespaceAliasDecl>(
+ getDerived().TransformDecl(Q.getLocalBeginLoc(),
+ QNNS->getAsNamespaceAlias()));
+ SS.Extend(SemaRef.Context, Alias, Q.getLocalBeginLoc(),
+ Q.getLocalEndLoc());
+ break;
+ }
+
+ case NestedNameSpecifier::Global:
+ // There is no meaningful transformation that one could perform on the
+ // global scope.
+ SS.MakeGlobal(SemaRef.Context, Q.getBeginLoc());
+ break;
+
+ case NestedNameSpecifier::TypeSpecWithTemplate:
+ case NestedNameSpecifier::TypeSpec: {
+ TypeLoc TL = TransformTypeInObjectScope(Q.getTypeLoc(), ObjectType,
+ FirstQualifierInScope, SS);
+
+ if (!TL)
+ return NestedNameSpecifierLoc();
+
+ if (TL.getType()->isDependentType() || TL.getType()->isRecordType() ||
+ (SemaRef.getLangOptions().CPlusPlus0x &&
+ TL.getType()->isEnumeralType())) {
+ assert(!TL.getType().hasLocalQualifiers() &&
+ "Can't get cv-qualifiers here");
+ SS.Extend(SemaRef.Context, /*FIXME:*/SourceLocation(), TL,
+ Q.getLocalEndLoc());
+ break;
+ }
+
+ SemaRef.Diag(TL.getBeginLoc(), diag::err_nested_name_spec_non_tag)
+ << TL.getType() << SS.getRange();
+ return NestedNameSpecifierLoc();
+ }
+ }
+
+ // The qualifier-in-scope only applies to the leftmost entity.
+ FirstQualifierInScope = 0;
+ }
+
+ // Don't rebuild the nested-name-specifier if we don't have to.
+ if (SS.getScopeRep() == NNS.getNestedNameSpecifier() &&
+ !getDerived().AlwaysRebuild())
+ return NNS;
+
+ // If we can re-use the source-location data from the original
+ // nested-name-specifier, do so.
+ if (SS.location_size() == NNS.getDataLength() &&
+ memcmp(SS.location_data(), NNS.getOpaqueData(), SS.location_size()) == 0)
+ return NestedNameSpecifierLoc(SS.getScopeRep(), NNS.getOpaqueData());
+
+ // Allocate new nested-name-specifier location information.
+ return SS.getWithLocInContext(SemaRef.Context);
+}
+
+template<typename Derived>
DeclarationNameInfo
TreeTransform<Derived>
::TransformDeclarationNameInfo(const DeclarationNameInfo &NameInfo) {
@@ -3085,7 +3211,7 @@ TreeTransform<Derived>::TransformTypeInObjectScope(TypeSourceInfo *TSI,
QualType ObjectType,
NamedDecl *UnqualLookup,
NestedNameSpecifier *Prefix) {
- // TODO: in some cases, we might be some verification to do here.
+ // TODO: in some cases, we might have some verification to do here.
if (ObjectType.isNull())
return getDerived().TransformType(TSI);
@@ -3122,6 +3248,62 @@ TreeTransform<Derived>::TransformTypeInObjectScope(TypeSourceInfo *TSI,
return TLB.getTypeSourceInfo(SemaRef.Context, Result);
}
+template<typename Derived>
+TypeLoc
+TreeTransform<Derived>::TransformTypeInObjectScope(TypeLoc TL,
+ QualType ObjectType,
+ NamedDecl *UnqualLookup,
+ CXXScopeSpec &SS) {
+ // FIXME: Painfully copy-paste from the above!
+
+ // TODO: in some cases, we might have some verification to do here.
+ if (ObjectType.isNull()) {
+ TypeLocBuilder TLB;
+ TLB.reserve(TL.getFullDataSize());
+ QualType Result = getDerived().TransformType(TLB, TL);
+ if (Result.isNull())
+ return TypeLoc();
+
+ return TLB.getTypeSourceInfo(SemaRef.Context, Result)->getTypeLoc();
+ }
+
+ QualType T = TL.getType();
+ if (getDerived().AlreadyTransformed(T))
+ return TL;
+
+ TypeLocBuilder TLB;
+ QualType Result;
+
+ if (isa<TemplateSpecializationType>(T)) {
+ TemplateSpecializationTypeLoc SpecTL
+ = cast<TemplateSpecializationTypeLoc>(TL);
+
+ TemplateName Template =
+ getDerived().TransformTemplateName(SpecTL.getTypePtr()->getTemplateName(),
+ ObjectType, UnqualLookup);
+ if (Template.isNull())
+ return TypeLoc();
+
+ Result = getDerived().TransformTemplateSpecializationType(TLB, SpecTL,
+ Template);
+ } else if (isa<DependentTemplateSpecializationType>(T)) {
+ DependentTemplateSpecializationTypeLoc SpecTL
+ = cast<DependentTemplateSpecializationTypeLoc>(TL);
+
+ Result = getDerived().TransformDependentTemplateSpecializationType(TLB,
+ SpecTL,
+ SS.getScopeRep());
+ } else {
+ // Nothing special needs to be done for these.
+ Result = getDerived().TransformType(TLB, TL);
+ }
+
+ if (Result.isNull())
+ return TypeLoc();
+
+ return TLB.getTypeSourceInfo(SemaRef.Context, Result)->getTypeLoc();
+}
+
template <class TyLoc> static inline
QualType TransformTypeSpecType(TypeLocBuilder &TLB, TyLoc T) {
TyLoc NewT = TLB.push<TyLoc>(T.getType());
@@ -4337,7 +4519,8 @@ QualType TreeTransform<Derived>::
TemplateArgumentListInfo NewTemplateArgs;
NewTemplateArgs.setLAngleLoc(TL.getLAngleLoc());
NewTemplateArgs.setRAngleLoc(TL.getRAngleLoc());
-
+
+ // FIXME: Nested-name-specifier source location info!
typedef TemplateArgumentLocContainerIterator<
DependentTemplateSpecializationTypeLoc> ArgIterator;
if (getDerived().TransformTemplateArguments(ArgIterator(TL, 0),
@@ -6426,21 +6609,22 @@ TreeTransform<Derived>::TransformCXXPseudoDestructorExpr(
return ExprError();
QualType ObjectType = ObjectTypePtr.get();
- NestedNameSpecifier *Qualifier = E->getQualifier();
- if (Qualifier) {
- Qualifier
- = getDerived().TransformNestedNameSpecifier(E->getQualifier(),
- E->getQualifierRange(),
- ObjectType);
- if (!Qualifier)
+ NestedNameSpecifierLoc QualifierLoc = E->getQualifierLoc();
+ if (QualifierLoc) {
+ QualifierLoc
+ = getDerived().TransformNestedNameSpecifierLoc(QualifierLoc, ObjectType);
+ if (!QualifierLoc)
return ExprError();
}
+ CXXScopeSpec SS;
+ SS.Adopt(QualifierLoc);
PseudoDestructorTypeStorage Destroyed;
if (E->getDestroyedTypeInfo()) {
TypeSourceInfo *DestroyedTypeInfo
= getDerived().TransformTypeInObjectScope(E->getDestroyedTypeInfo(),
- ObjectType, 0, Qualifier);
+ ObjectType, 0,
+ QualifierLoc.getNestedNameSpecifier());
if (!DestroyedTypeInfo)
return ExprError();
Destroyed = DestroyedTypeInfo;
@@ -6451,12 +6635,6 @@ TreeTransform<Derived>::TransformCXXPseudoDestructorExpr(
E->getDestroyedTypeLoc());
} else {
// Look for a destructor known with the given name.
- CXXScopeSpec SS;
- if (Qualifier) {
- SS.setScopeRep(Qualifier);
- SS.setRange(E->getQualifierRange());
- }
-
ParsedType T = SemaRef.getDestructorName(E->getTildeLoc(),
*E->getDestroyedTypeIdentifier(),
E->getDestroyedTypeLoc(),
@@ -6481,8 +6659,7 @@ TreeTransform<Derived>::TransformCXXPseudoDestructorExpr(
return getDerived().RebuildCXXPseudoDestructorExpr(Base.get(),
E->getOperatorLoc(),
E->isArrow(),
- Qualifier,
- E->getQualifierRange(),
+ SS,
ScopeTypeInfo,
E->getColonColonLoc(),
E->getTildeLoc(),
@@ -6538,8 +6715,7 @@ TreeTransform<Derived>::TransformUnresolvedLookupExpr(
if (!Qualifier)
return ExprError();
- SS.setScopeRep(Qualifier);
- SS.setRange(Old->getQualifierRange());
+ SS.MakeTrivial(SemaRef.Context, Qualifier, Old->getQualifierRange());
}
if (Old->getNamingClass()) {
@@ -6611,10 +6787,9 @@ template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformDependentScopeDeclRefExpr(
DependentScopeDeclRefExpr *E) {
- NestedNameSpecifier *NNS
- = getDerived().TransformNestedNameSpecifier(E->getQualifier(),
- E->getQualifierRange());
- if (!NNS)
+ NestedNameSpecifierLoc QualifierLoc
+ = getDerived().TransformNestedNameSpecifierLoc(E->getQualifierLoc());
+ if (!QualifierLoc)
return ExprError();
// TODO: If this is a conversion-function-id, verify that the
@@ -6628,14 +6803,13 @@ TreeTransform<Derived>::TransformDependentScopeDeclRefExpr(
if (!E->hasExplicitTemplateArgs()) {
if (!getDerived().AlwaysRebuild() &&
- NNS == E->getQualifier() &&
+ QualifierLoc == E->getQualifierLoc() &&
// Note: it is sufficient to compare the Name component of NameInfo:
// if name has not changed, DNLoc has not changed either.
NameInfo.getName() == E->getDeclName())
return SemaRef.Owned(E);
- return getDerived().RebuildDependentScopeDeclRefExpr(NNS,
- E->getQualifierRange(),
+ return getDerived().RebuildDependentScopeDeclRefExpr(QualifierLoc,
NameInfo,
/*TemplateArgs*/ 0);
}
@@ -6646,8 +6820,7 @@ TreeTransform<Derived>::TransformDependentScopeDeclRefExpr(
TransArgs))
return ExprError();
- return getDerived().RebuildDependentScopeDeclRefExpr(NNS,
- E->getQualifierRange(),
+ return getDerived().RebuildDependentScopeDeclRefExpr(QualifierLoc,
NameInfo,
&TransArgs);
}
@@ -7560,14 +7733,15 @@ TreeTransform<Derived>::RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix,
NamedDecl *FirstQualifierInScope) {
CXXScopeSpec SS;
// FIXME: The source location information is all wrong.
- SS.setRange(Range);
- SS.setScopeRep(Prefix);
- return static_cast<NestedNameSpecifier *>(
- SemaRef.BuildCXXNestedNameSpecifier(0, SS, Range.getEnd(),
- Range.getEnd(), II,
- ObjectType,
- FirstQualifierInScope,
- false, false));
+ SS.MakeTrivial(SemaRef.Context, Prefix, Range);
+ if (SemaRef.BuildCXXNestedNameSpecifier(0, II, /*FIXME:*/Range.getBegin(),
+ /*FIXME:*/Range.getEnd(),
+ ObjectType, false,
+ SS, FirstQualifierInScope,
+ false))
+ return 0;
+
+ return SS.getScopeRep();
}
template<typename Derived>
@@ -7582,6 +7756,14 @@ template<typename Derived>
NestedNameSpecifier *
TreeTransform<Derived>::RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix,
SourceRange Range,
+ NamespaceAliasDecl *Alias) {
+ return NestedNameSpecifier::Create(SemaRef.Context, Prefix, Alias);
+}
+
+template<typename Derived>
+NestedNameSpecifier *
+TreeTransform<Derived>::RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix,
+ SourceRange Range,
bool TemplateKW,
QualType T) {
if (T->isDependentType() || T->isRecordType() ||
@@ -7612,8 +7794,7 @@ TreeTransform<Derived>::RebuildTemplateName(NestedNameSpecifier *Qualifier,
QualType ObjectType,
NamedDecl *FirstQualifierInScope) {
CXXScopeSpec SS;
- SS.setRange(QualifierRange);
- SS.setScopeRep(Qualifier);
+ SS.MakeTrivial(SemaRef.Context, Qualifier, QualifierRange);
UnqualifiedId Name;
Name.setIdentifier(&II, /*FIXME:*/getDerived().getBaseLocation());
Sema::TemplateTy Template;
@@ -7633,8 +7814,7 @@ TreeTransform<Derived>::RebuildTemplateName(NestedNameSpecifier *Qualifier,
OverloadedOperatorKind Operator,
QualType ObjectType) {
CXXScopeSpec SS;
- SS.setRange(SourceRange(getDerived().getBaseLocation()));
- SS.setScopeRep(Qualifier);
+ SS.MakeTrivial(SemaRef.Context, Qualifier, SourceRange(getDerived().getBaseLocation()));
UnqualifiedId Name;
SourceLocation SymbolLocations[3]; // FIXME: Bogus location information.
Name.setOperatorFunctionId(/*FIXME:*/getDerived().getBaseLocation(),
@@ -7740,18 +7920,11 @@ ExprResult
TreeTransform<Derived>::RebuildCXXPseudoDestructorExpr(Expr *Base,
SourceLocation OperatorLoc,
bool isArrow,
- NestedNameSpecifier *Qualifier,
- SourceRange QualifierRange,
+ CXXScopeSpec &SS,
TypeSourceInfo *ScopeType,
SourceLocation CCLoc,
SourceLocation TildeLoc,
PseudoDestructorTypeStorage Destroyed) {
- CXXScopeSpec SS;
- if (Qualifier) {
- SS.setRange(QualifierRange);
- SS.setScopeRep(Qualifier);
- }
-
QualType BaseType = Base->getType();
if (Base->isTypeDependent() || Destroyed.getIdentifier() ||
(!isArrow && !BaseType->getAs<RecordType>()) ||
diff --git a/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h b/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h
index 3d20a52..1e0a7c4 100644
--- a/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h
+++ b/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h
@@ -107,6 +107,19 @@ class TypeLocBuilder {
return DI;
}
+ /// \brief Copies the type-location information to the given AST context and
+ /// returns a \c TypeLoc referring into the AST context.
+ TypeLoc getTypeLocInContext(ASTContext &Context, QualType T) {
+#ifndef NDEBUG
+ assert(T == LastTy && "type doesn't match last type pushed!");
+#endif
+
+ size_t FullDataSize = Capacity - Index;
+ void *Mem = Context.Allocate(FullDataSize);
+ memcpy(Mem, &Buffer[Index], FullDataSize);
+ return TypeLoc(T, Mem);
+ }
+
private:
TypeLoc pushImpl(QualType T, size_t LocalSize) {
#ifndef NDEBUG
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp
index ce87b11..c3953ba 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp
@@ -97,8 +97,9 @@ PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts) {
diag::warn_pch_lax_vector_conversions);
PARSE_LANGOPT_IMPORTANT(AltiVec, diag::warn_pch_altivec);
PARSE_LANGOPT_IMPORTANT(Exceptions, diag::warn_pch_exceptions);
- PARSE_LANGOPT_IMPORTANT(SjLjExceptions, diag::warn_pch_sjlj_exceptions);
PARSE_LANGOPT_IMPORTANT(ObjCExceptions, diag::warn_pch_objc_exceptions);
+ PARSE_LANGOPT_IMPORTANT(CXXExceptions, diag::warn_pch_cxx_exceptions);
+ PARSE_LANGOPT_IMPORTANT(SjLjExceptions, diag::warn_pch_sjlj_exceptions);
PARSE_LANGOPT_IMPORTANT(MSBitfields, diag::warn_pch_ms_bitfields);
PARSE_LANGOPT_IMPORTANT(NeXTRuntime, diag::warn_pch_objc_runtime);
PARSE_LANGOPT_IMPORTANT(Freestanding, diag::warn_pch_freestanding);
@@ -243,14 +244,15 @@ FindMacro(const PCHPredefinesBlocks &Buffers, llvm::StringRef MacroDef) {
bool PCHValidator::ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers,
llvm::StringRef OriginalFileName,
- std::string &SuggestedPredefines) {
+ std::string &SuggestedPredefines,
+ FileManager &FileMgr) {
// We are in the context of an implicit include, so the predefines buffer will
// have a #include entry for the PCH file itself (as normalized by the
// preprocessor initialization). Find it and skip over it in the checking
// below.
llvm::SmallString<256> PCHInclude;
PCHInclude += "#include \"";
- PCHInclude += NormalizeDashIncludePath(OriginalFileName);
+ PCHInclude += NormalizeDashIncludePath(OriginalFileName, FileMgr);
PCHInclude += "\"\n";
std::pair<llvm::StringRef,llvm::StringRef> Split =
llvm::StringRef(PP.getPredefines()).split(PCHInclude.str());
@@ -960,7 +962,8 @@ bool ASTReader::CheckPredefinesBuffers() {
if (Listener)
return Listener->ReadPredefinesBuffer(PCHPredefinesBuffers,
ActualOriginalFileName,
- SuggestedPredefines);
+ SuggestedPredefines,
+ FileMgr);
return false;
}
@@ -2799,8 +2802,9 @@ bool ASTReader::ParseLanguageOptions(
PARSE_LANGOPT(LaxVectorConversions);
PARSE_LANGOPT(AltiVec);
PARSE_LANGOPT(Exceptions);
- PARSE_LANGOPT(SjLjExceptions);
PARSE_LANGOPT(ObjCExceptions);
+ PARSE_LANGOPT(CXXExceptions);
+ PARSE_LANGOPT(SjLjExceptions);
PARSE_LANGOPT(MSBitfields);
PARSE_LANGOPT(NeXTRuntime);
PARSE_LANGOPT(Freestanding);
@@ -4476,8 +4480,7 @@ void ASTReader::ReadDeclarationNameInfo(PerFileData &F,
void ASTReader::ReadQualifierInfo(PerFileData &F, QualifierInfo &Info,
const RecordData &Record, unsigned &Idx) {
- Info.NNS = ReadNestedNameSpecifier(Record, Idx);
- Info.NNSRange = ReadSourceRange(F, Record, Idx);
+ Info.QualifierLoc = ReadNestedNameSpecifierLoc(F, Record, Idx);
unsigned NumTPLists = Record[Idx++];
Info.NumTemplParamLists = NumTPLists;
if (NumTPLists) {
@@ -4726,6 +4729,13 @@ ASTReader::ReadNestedNameSpecifier(const RecordData &Record, unsigned &Idx) {
break;
}
+ case NestedNameSpecifier::NamespaceAlias: {
+ NamespaceAliasDecl *Alias
+ = cast<NamespaceAliasDecl>(GetDecl(Record[Idx++]));
+ NNS = NestedNameSpecifier::Create(*Context, Prev, Alias);
+ break;
+ }
+
case NestedNameSpecifier::TypeSpec:
case NestedNameSpecifier::TypeSpecWithTemplate: {
const Type *T = GetType(Record[Idx++]).getTypePtrOrNull();
@@ -4748,6 +4758,109 @@ ASTReader::ReadNestedNameSpecifier(const RecordData &Record, unsigned &Idx) {
return NNS;
}
+NestedNameSpecifierLoc
+ASTReader::ReadNestedNameSpecifierLoc(PerFileData &F, const RecordData &Record,
+ unsigned &Idx) {
+ unsigned N = Record[Idx++];
+ NestedNameSpecifier *NNS = 0, *Prev = 0;
+ llvm::SmallVector<char, 32> LocationData;
+ for (unsigned I = 0; I != N; ++I) {
+ NestedNameSpecifier::SpecifierKind Kind
+ = (NestedNameSpecifier::SpecifierKind)Record[Idx++];
+ switch (Kind) {
+ case NestedNameSpecifier::Identifier: {
+ // Nested-name-specifier
+ IdentifierInfo *II = GetIdentifierInfo(Record, Idx);
+ NNS = NestedNameSpecifier::Create(*Context, Prev, II);
+
+ // Location information
+ SourceRange Range = ReadSourceRange(F, Record, Idx);
+ unsigned RawStart = Range.getBegin().getRawEncoding();
+ unsigned RawEnd = Range.getEnd().getRawEncoding();
+ LocationData.append(reinterpret_cast<char*>(&RawStart),
+ reinterpret_cast<char*>(&RawStart) +sizeof(unsigned));
+ LocationData.append(reinterpret_cast<char*>(&RawEnd),
+ reinterpret_cast<char*>(&RawEnd) + sizeof(unsigned));
+ break;
+ }
+
+ case NestedNameSpecifier::Namespace: {
+ // Nested-name-specifier
+ NamespaceDecl *NS = cast<NamespaceDecl>(GetDecl(Record[Idx++]));
+ NNS = NestedNameSpecifier::Create(*Context, Prev, NS);
+
+ // Location information
+ SourceRange Range = ReadSourceRange(F, Record, Idx);
+ unsigned RawStart = Range.getBegin().getRawEncoding();
+ unsigned RawEnd = Range.getEnd().getRawEncoding();
+ LocationData.append(reinterpret_cast<char*>(&RawStart),
+ reinterpret_cast<char*>(&RawStart) +sizeof(unsigned));
+ LocationData.append(reinterpret_cast<char*>(&RawEnd),
+ reinterpret_cast<char*>(&RawEnd) + sizeof(unsigned));
+ break;
+ }
+
+ case NestedNameSpecifier::NamespaceAlias: {
+ // Nested-name-specifier
+ NamespaceAliasDecl *Alias
+ = cast<NamespaceAliasDecl>(GetDecl(Record[Idx++]));
+ NNS = NestedNameSpecifier::Create(*Context, Prev, Alias);
+
+ // Location information
+ SourceRange Range = ReadSourceRange(F, Record, Idx);
+ unsigned RawStart = Range.getBegin().getRawEncoding();
+ unsigned RawEnd = Range.getEnd().getRawEncoding();
+ LocationData.append(reinterpret_cast<char*>(&RawStart),
+ reinterpret_cast<char*>(&RawStart) +sizeof(unsigned));
+ LocationData.append(reinterpret_cast<char*>(&RawEnd),
+ reinterpret_cast<char*>(&RawEnd) + sizeof(unsigned));
+
+ break;
+ }
+
+ case NestedNameSpecifier::TypeSpec:
+ case NestedNameSpecifier::TypeSpecWithTemplate: {
+ // Nested-name-specifier
+ bool Template = Record[Idx++];
+ TypeSourceInfo *T = GetTypeSourceInfo(F, Record, Idx);
+ if (!T)
+ return NestedNameSpecifierLoc();
+ NNS = NestedNameSpecifier::Create(*Context, Prev, Template,
+ T->getType().getTypePtr());
+
+ // Location information.
+ SourceLocation ColonColonLoc = ReadSourceLocation(F, Record, Idx);
+ unsigned RawLocation = ColonColonLoc.getRawEncoding();
+ void *OpaqueTypeData = T->getTypeLoc().getOpaqueData();
+ LocationData.append(reinterpret_cast<char*>(&OpaqueTypeData),
+ (reinterpret_cast<char*>(&OpaqueTypeData)
+ + sizeof(void *)));
+ LocationData.append(reinterpret_cast<char*>(&RawLocation),
+ (reinterpret_cast<char*>(&RawLocation) +
+ sizeof(unsigned)));
+ break;
+ }
+
+ case NestedNameSpecifier::Global: {
+ // Nested-name-specifier
+ NNS = NestedNameSpecifier::GlobalSpecifier(*Context);
+
+ SourceLocation ColonColonLoc = ReadSourceLocation(F, Record, Idx);
+ unsigned RawLocation = ColonColonLoc.getRawEncoding();
+ LocationData.append(reinterpret_cast<char*>(&RawLocation),
+ (reinterpret_cast<char*>(&RawLocation) +
+ sizeof(unsigned)));
+ break;
+ }
+ }
+ Prev = NNS;
+ }
+
+ void *Mem = Context->Allocate(LocationData.size(), llvm::alignOf<void*>());
+ memcpy(Mem, LocationData.data(), LocationData.size());
+ return NestedNameSpecifierLoc(NNS, Mem);
+}
+
SourceRange
ASTReader::ReadSourceRange(PerFileData &F, const RecordData &Record,
unsigned &Idx) {
@@ -4932,4 +5045,3 @@ ASTReader::PerFileData::~PerFileData() {
delete static_cast<HeaderFileInfoLookupTable *>(HeaderFileInfoTable);
delete static_cast<ASTSelectorLookupTable *>(SelectorLookupTable);
}
-
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp
index dec15dd..493ccba 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -744,17 +744,15 @@ void ASTDeclReader::VisitNamespaceDecl(NamespaceDecl *D) {
void ASTDeclReader::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
VisitNamedDecl(D);
D->NamespaceLoc = ReadSourceLocation(Record, Idx);
- D->setQualifierRange(ReadSourceRange(Record, Idx));
- D->setQualifier(Reader.ReadNestedNameSpecifier(Record, Idx));
D->IdentLoc = ReadSourceLocation(Record, Idx);
+ D->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx);
D->Namespace = cast<NamedDecl>(Reader.GetDecl(Record[Idx++]));
}
void ASTDeclReader::VisitUsingDecl(UsingDecl *D) {
VisitNamedDecl(D);
D->setUsingLocation(ReadSourceLocation(Record, Idx));
- D->setNestedNameRange(ReadSourceRange(Record, Idx));
- D->setTargetNestedNameDecl(Reader.ReadNestedNameSpecifier(Record, Idx));
+ D->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx);
ReadDeclarationNameLoc(D->DNLoc, D->getDeclName(), Record, Idx);
D->FirstUsingShadow = cast_or_null<UsingShadowDecl>(Reader.GetDecl(Record[Idx++]));
D->setTypeName(Record[Idx++]);
@@ -777,27 +775,24 @@ void ASTDeclReader::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
VisitNamedDecl(D);
D->UsingLoc = ReadSourceLocation(Record, Idx);
D->NamespaceLoc = ReadSourceLocation(Record, Idx);
- D->QualifierRange = ReadSourceRange(Record, Idx);
- D->Qualifier = Reader.ReadNestedNameSpecifier(Record, Idx);
+ D->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx);
D->NominatedNamespace = cast<NamedDecl>(Reader.GetDecl(Record[Idx++]));
D->CommonAncestor = cast_or_null<DeclContext>(Reader.GetDecl(Record[Idx++]));
}
void ASTDeclReader::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
VisitValueDecl(D);
- D->setTargetNestedNameRange(ReadSourceRange(Record, Idx));
D->setUsingLoc(ReadSourceLocation(Record, Idx));
- D->setTargetNestedNameSpecifier(Reader.ReadNestedNameSpecifier(Record, Idx));
+ D->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx);
ReadDeclarationNameLoc(D->DNLoc, D->getDeclName(), Record, Idx);
}
void ASTDeclReader::VisitUnresolvedUsingTypenameDecl(
UnresolvedUsingTypenameDecl *D) {
VisitTypeDecl(D);
- D->TargetNestedNameRange = ReadSourceRange(Record, Idx);
D->UsingLocation = ReadSourceLocation(Record, Idx);
D->TypenameLocation = ReadSourceLocation(Record, Idx);
- D->TargetNestedNameSpecifier = Reader.ReadNestedNameSpecifier(Record, Idx);
+ D->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx);
}
void ASTDeclReader::ReadCXXDefinitionData(
@@ -1432,30 +1427,33 @@ Decl *ASTReader::ReadDeclRecord(unsigned Index, DeclID ID) {
break;
case DECL_NAMESPACE_ALIAS:
D = NamespaceAliasDecl::Create(*Context, 0, SourceLocation(),
- SourceLocation(), 0, SourceRange(), 0,
+ SourceLocation(), 0,
+ NestedNameSpecifierLoc(),
SourceLocation(), 0);
break;
case DECL_USING:
- D = UsingDecl::Create(*Context, 0, SourceRange(), SourceLocation(),
- 0, DeclarationNameInfo(), false);
+ D = UsingDecl::Create(*Context, 0, SourceLocation(),
+ NestedNameSpecifierLoc(), DeclarationNameInfo(),
+ false);
break;
case DECL_USING_SHADOW:
D = UsingShadowDecl::Create(*Context, 0, SourceLocation(), 0, 0);
break;
case DECL_USING_DIRECTIVE:
D = UsingDirectiveDecl::Create(*Context, 0, SourceLocation(),
- SourceLocation(), SourceRange(), 0,
+ SourceLocation(), NestedNameSpecifierLoc(),
SourceLocation(), 0, 0);
break;
case DECL_UNRESOLVED_USING_VALUE:
D = UnresolvedUsingValueDecl::Create(*Context, 0, SourceLocation(),
- SourceRange(), 0,
+ NestedNameSpecifierLoc(),
DeclarationNameInfo());
break;
case DECL_UNRESOLVED_USING_TYPENAME:
D = UnresolvedUsingTypenameDecl::Create(*Context, 0, SourceLocation(),
- SourceLocation(), SourceRange(),
- 0, SourceLocation(),
+ SourceLocation(),
+ NestedNameSpecifierLoc(),
+ SourceLocation(),
DeclarationName());
break;
case DECL_CXX_RECORD:
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp
index 4e91c98..42f0b1a 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -1167,14 +1167,13 @@ void ASTStmtReader::VisitCXXDeleteExpr(CXXDeleteExpr *E) {
void ASTStmtReader::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) {
VisitExpr(E);
- E->setBase(Reader.ReadSubExpr());
- E->setArrow(Record[Idx++]);
- E->setOperatorLoc(ReadSourceLocation(Record, Idx));
- E->setQualifier(Reader.ReadNestedNameSpecifier(Record, Idx));
- E->setQualifierRange(ReadSourceRange(Record, Idx));
- E->setScopeTypeInfo(GetTypeSourceInfo(Record, Idx));
- E->setColonColonLoc(ReadSourceLocation(Record, Idx));
- E->setTildeLoc(ReadSourceLocation(Record, Idx));
+ E->Base = Reader.ReadSubExpr();
+ E->IsArrow = Record[Idx++];
+ E->OperatorLoc = ReadSourceLocation(Record, Idx);
+ E->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx);
+ E->ScopeType = GetTypeSourceInfo(Record, Idx);
+ E->ColonColonLoc = ReadSourceLocation(Record, Idx);
+ E->TildeLoc = ReadSourceLocation(Record, Idx);
IdentifierInfo *II = Reader.GetIdentifierInfo(Record, Idx);
if (II)
@@ -1220,10 +1219,9 @@ ASTStmtReader::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) {
if (Record[Idx++])
ReadExplicitTemplateArgumentList(E->getExplicitTemplateArgs(),
Record[Idx++]);
-
+
+ E->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx);
ReadDeclarationNameInfo(E->NameInfo, Record, Idx);
- E->setQualifierRange(ReadSourceRange(Record, Idx));
- E->setQualifier(Reader.ReadNestedNameSpecifier(Record, Idx));
}
void
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp
index 8fcb535..383ca3d 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp
@@ -1023,8 +1023,9 @@ void ASTWriter::WriteLanguageOptions(const LangOptions &LangOpts) {
Record.push_back(LangOpts.LaxVectorConversions);
Record.push_back(LangOpts.AltiVec);
Record.push_back(LangOpts.Exceptions); // Support exception handling.
- Record.push_back(LangOpts.SjLjExceptions);
Record.push_back(LangOpts.ObjCExceptions);
+ Record.push_back(LangOpts.CXXExceptions);
+ Record.push_back(LangOpts.SjLjExceptions);
Record.push_back(LangOpts.MSBitfields); // MS-compatible structure layout
Record.push_back(LangOpts.NeXTRuntime); // Use NeXT runtime.
@@ -3275,15 +3276,21 @@ void ASTWriter::AddTemplateArgumentLoc(const TemplateArgumentLoc &Arg,
Record);
}
-void ASTWriter::AddTypeSourceInfo(TypeSourceInfo *TInfo, RecordDataImpl &Record) {
+void ASTWriter::AddTypeSourceInfo(TypeSourceInfo *TInfo,
+ RecordDataImpl &Record) {
if (TInfo == 0) {
AddTypeRef(QualType(), Record);
return;
}
- AddTypeRef(TInfo->getType(), Record);
+ AddTypeLoc(TInfo->getTypeLoc(), Record);
+}
+
+void ASTWriter::AddTypeLoc(TypeLoc TL, RecordDataImpl &Record) {
+ AddTypeRef(TL.getType(), Record);
+
TypeLocWriter TLW(*this, Record);
- for (TypeLoc TL = TInfo->getTypeLoc(); !TL.isNull(); TL = TL.getNextTypeLoc())
+ for (; !TL.isNull(); TL = TL.getNextTypeLoc())
TLW.Visit(TL);
}
@@ -3436,8 +3443,7 @@ void ASTWriter::AddDeclarationNameInfo(const DeclarationNameInfo &NameInfo,
void ASTWriter::AddQualifierInfo(const QualifierInfo &Info,
RecordDataImpl &Record) {
- AddNestedNameSpecifier(Info.NNS, Record);
- AddSourceRange(Info.NNSRange, Record);
+ AddNestedNameSpecifierLoc(Info.QualifierLoc, Record);
Record.push_back(Info.NumTemplParamLists);
for (unsigned i=0, e=Info.NumTemplParamLists; i != e; ++i)
AddTemplateParameterList(Info.TemplParamLists[i], Record);
@@ -3469,6 +3475,10 @@ void ASTWriter::AddNestedNameSpecifier(NestedNameSpecifier *NNS,
AddDeclRef(NNS->getAsNamespace(), Record);
break;
+ case NestedNameSpecifier::NamespaceAlias:
+ AddDeclRef(NNS->getAsNamespaceAlias(), Record);
+ break;
+
case NestedNameSpecifier::TypeSpec:
case NestedNameSpecifier::TypeSpecWithTemplate:
AddTypeRef(QualType(NNS->getAsType(), 0), Record);
@@ -3482,6 +3492,55 @@ void ASTWriter::AddNestedNameSpecifier(NestedNameSpecifier *NNS,
}
}
+void ASTWriter::AddNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
+ RecordDataImpl &Record) {
+ // Nested name specifiers usually aren't too long. I think that 8 would
+ // typically accomodate the vast majority.
+ llvm::SmallVector<NestedNameSpecifierLoc , 8> NestedNames;
+
+ // Push each of the nested-name-specifiers's onto a stack for
+ // serialization in reverse order.
+ while (NNS) {
+ NestedNames.push_back(NNS);
+ NNS = NNS.getPrefix();
+ }
+
+ Record.push_back(NestedNames.size());
+ while(!NestedNames.empty()) {
+ NNS = NestedNames.pop_back_val();
+ NestedNameSpecifier::SpecifierKind Kind
+ = NNS.getNestedNameSpecifier()->getKind();
+ Record.push_back(Kind);
+ switch (Kind) {
+ case NestedNameSpecifier::Identifier:
+ AddIdentifierRef(NNS.getNestedNameSpecifier()->getAsIdentifier(), Record);
+ AddSourceRange(NNS.getLocalSourceRange(), Record);
+ break;
+
+ case NestedNameSpecifier::Namespace:
+ AddDeclRef(NNS.getNestedNameSpecifier()->getAsNamespace(), Record);
+ AddSourceRange(NNS.getLocalSourceRange(), Record);
+ break;
+
+ case NestedNameSpecifier::NamespaceAlias:
+ AddDeclRef(NNS.getNestedNameSpecifier()->getAsNamespaceAlias(), Record);
+ AddSourceRange(NNS.getLocalSourceRange(), Record);
+ break;
+
+ case NestedNameSpecifier::TypeSpec:
+ case NestedNameSpecifier::TypeSpecWithTemplate:
+ Record.push_back(Kind == NestedNameSpecifier::TypeSpecWithTemplate);
+ AddTypeLoc(NNS.getTypeLoc(), Record);
+ AddSourceLocation(NNS.getLocalSourceRange().getEnd(), Record);
+ break;
+
+ case NestedNameSpecifier::Global:
+ AddSourceLocation(NNS.getLocalSourceRange().getEnd(), Record);
+ break;
+ }
+ }
+}
+
void ASTWriter::AddTemplateName(TemplateName Name, RecordDataImpl &Record) {
TemplateName::NameKind Kind = Name.getKind();
Record.push_back(Kind);
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp
index ce07e138..12d1226 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp
@@ -697,18 +697,16 @@ void ASTDeclWriter::VisitNamespaceDecl(NamespaceDecl *D) {
void ASTDeclWriter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
VisitNamedDecl(D);
Writer.AddSourceLocation(D->getNamespaceLoc(), Record);
- Writer.AddSourceRange(D->getQualifierRange(), Record);
- Writer.AddNestedNameSpecifier(D->getQualifier(), Record);
Writer.AddSourceLocation(D->getTargetNameLoc(), Record);
+ Writer.AddNestedNameSpecifierLoc(D->getQualifierLoc(), Record);
Writer.AddDeclRef(D->getNamespace(), Record);
Code = serialization::DECL_NAMESPACE_ALIAS;
}
void ASTDeclWriter::VisitUsingDecl(UsingDecl *D) {
VisitNamedDecl(D);
- Writer.AddSourceRange(D->getNestedNameRange(), Record);
Writer.AddSourceLocation(D->getUsingLocation(), Record);
- Writer.AddNestedNameSpecifier(D->getTargetNestedNameDecl(), Record);
+ Writer.AddNestedNameSpecifierLoc(D->getQualifierLoc(), Record);
Writer.AddDeclarationNameLoc(D->DNLoc, D->getDeclName(), Record);
Writer.AddDeclRef(D->FirstUsingShadow, Record);
Record.push_back(D->isTypeName());
@@ -728,8 +726,7 @@ void ASTDeclWriter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
VisitNamedDecl(D);
Writer.AddSourceLocation(D->getUsingLoc(), Record);
Writer.AddSourceLocation(D->getNamespaceKeyLocation(), Record);
- Writer.AddSourceRange(D->getQualifierRange(), Record);
- Writer.AddNestedNameSpecifier(D->getQualifier(), Record);
+ Writer.AddNestedNameSpecifierLoc(D->getQualifierLoc(), Record);
Writer.AddDeclRef(D->getNominatedNamespace(), Record);
Writer.AddDeclRef(dyn_cast<Decl>(D->getCommonAncestor()), Record);
Code = serialization::DECL_USING_DIRECTIVE;
@@ -737,9 +734,8 @@ void ASTDeclWriter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
void ASTDeclWriter::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
VisitValueDecl(D);
- Writer.AddSourceRange(D->getTargetNestedNameRange(), Record);
Writer.AddSourceLocation(D->getUsingLoc(), Record);
- Writer.AddNestedNameSpecifier(D->getTargetNestedNameSpecifier(), Record);
+ Writer.AddNestedNameSpecifierLoc(D->getQualifierLoc(), Record);
Writer.AddDeclarationNameLoc(D->DNLoc, D->getDeclName(), Record);
Code = serialization::DECL_UNRESOLVED_USING_VALUE;
}
@@ -747,10 +743,9 @@ void ASTDeclWriter::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
void ASTDeclWriter::VisitUnresolvedUsingTypenameDecl(
UnresolvedUsingTypenameDecl *D) {
VisitTypeDecl(D);
- Writer.AddSourceRange(D->getTargetNestedNameRange(), Record);
Writer.AddSourceLocation(D->getUsingLoc(), Record);
Writer.AddSourceLocation(D->getTypenameLoc(), Record);
- Writer.AddNestedNameSpecifier(D->getTargetNestedNameSpecifier(), Record);
+ Writer.AddNestedNameSpecifierLoc(D->getQualifierLoc(), Record);
Code = serialization::DECL_UNRESOLVED_USING_TYPENAME;
}
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp
index 8a5ffe9..af846a9 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp
@@ -1150,8 +1150,7 @@ void ASTStmtWriter::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) {
Writer.AddStmt(E->getBase());
Record.push_back(E->isArrow());
Writer.AddSourceLocation(E->getOperatorLoc(), Record);
- Writer.AddNestedNameSpecifier(E->getQualifier(), Record);
- Writer.AddSourceRange(E->getQualifierRange(), Record);
+ Writer.AddNestedNameSpecifierLoc(E->getQualifierLoc(), Record);
Writer.AddTypeSourceInfo(E->getScopeTypeInfo(), Record);
Writer.AddSourceLocation(E->getColonColonLoc(), Record);
Writer.AddSourceLocation(E->getTildeLoc(), Record);
@@ -1217,9 +1216,8 @@ ASTStmtWriter::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) {
AddExplicitTemplateArgumentList(Args);
}
+ Writer.AddNestedNameSpecifierLoc(E->getQualifierLoc(), Record);
Writer.AddDeclarationNameInfo(E->NameInfo, Record);
- Writer.AddSourceRange(E->getQualifierRange(), Record);
- Writer.AddNestedNameSpecifier(E->getQualifier(), Record);
Code = serialization::EXPR_CXX_DEPENDENT_SCOPE_DECL_REF;
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp
index 9194791..25e224e 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp
@@ -12,9 +12,11 @@
//
//===----------------------------------------------------------------------===//
-#include "InternalChecks.h"
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerV2.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
using namespace clang;
@@ -22,21 +24,15 @@ using namespace ento;
namespace {
class ArrayBoundChecker :
- public CheckerVisitor<ArrayBoundChecker> {
- BuiltinBug *BT;
+ public CheckerV2<check::Location> {
+ mutable llvm::OwningPtr<BuiltinBug> BT;
public:
- ArrayBoundChecker() : BT(0) {}
- static void *getTag() { static int x = 0; return &x; }
- void visitLocation(CheckerContext &C, const Stmt *S, SVal l, bool isLoad);
+ void checkLocation(SVal l, bool isLoad, CheckerContext &C) const;
};
}
-void ento::RegisterArrayBoundChecker(ExprEngine &Eng) {
- Eng.registerCheck(new ArrayBoundChecker());
-}
-
-void ArrayBoundChecker::visitLocation(CheckerContext &C, const Stmt *S, SVal l,
- bool isLoad) {
+void ArrayBoundChecker::checkLocation(SVal l, bool isLoad,
+ CheckerContext &C) const {
// Check for out of bound array element access.
const MemRegion *R = l.getAsRegion();
if (!R)
@@ -69,8 +65,8 @@ void ArrayBoundChecker::visitLocation(CheckerContext &C, const Stmt *S, SVal l,
return;
if (!BT)
- BT = new BuiltinBug("Out-of-bound array access",
- "Access out-of-bound array element (buffer overflow)");
+ BT.reset(new BuiltinBug("Out-of-bound array access",
+ "Access out-of-bound array element (buffer overflow)"));
// FIXME: It would be nice to eventually make this diagnostic more clear,
// e.g., by referencing the original declaration or by saying *why* this
@@ -80,7 +76,7 @@ void ArrayBoundChecker::visitLocation(CheckerContext &C, const Stmt *S, SVal l,
RangedBugReport *report =
new RangedBugReport(*BT, BT->getDescription(), N);
- report->addRange(S->getSourceRange());
+ report->addRange(C.getStmt()->getSourceRange());
C.EmitReport(report);
return;
}
@@ -90,3 +86,7 @@ void ArrayBoundChecker::visitLocation(CheckerContext &C, const Stmt *S, SVal l,
assert(StInBound);
C.addTransition(StInBound);
}
+
+void ento::registerArrayBoundChecker(CheckerManager &mgr) {
+ mgr.registerChecker<ArrayBoundChecker>();
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
index 1b6c528..7aff201 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
@@ -16,14 +16,14 @@
#include "BasicObjCFoundationChecks.h"
#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerV2.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
#include "clang/StaticAnalyzer/Checkers/LocalCheckers.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
@@ -69,22 +69,23 @@ static inline bool isNil(SVal X) {
//===----------------------------------------------------------------------===//
namespace {
- class NilArgChecker : public CheckerVisitor<NilArgChecker> {
- APIMisuse *BT;
- void WarnNilArg(CheckerContext &C, const ObjCMessage &msg, unsigned Arg);
+ class NilArgChecker : public CheckerV2<check::PreObjCMessage> {
+ mutable llvm::OwningPtr<APIMisuse> BT;
+
+ void WarnNilArg(CheckerContext &C,
+ const ObjCMessage &msg, unsigned Arg) const;
+
public:
- NilArgChecker() : BT(0) {}
- static void *getTag() { static int x = 0; return &x; }
- void preVisitObjCMessage(CheckerContext &C, ObjCMessage msg);
+ void checkPreObjCMessage(ObjCMessage msg, CheckerContext &C) const;
};
}
void NilArgChecker::WarnNilArg(CheckerContext &C,
const ObjCMessage &msg,
- unsigned int Arg)
+ unsigned int Arg) const
{
if (!BT)
- BT = new APIMisuse("nil argument");
+ BT.reset(new APIMisuse("nil argument"));
if (ExplodedNode *N = C.generateSink()) {
llvm::SmallString<128> sbuf;
@@ -98,9 +99,8 @@ void NilArgChecker::WarnNilArg(CheckerContext &C,
}
}
-void NilArgChecker::preVisitObjCMessage(CheckerContext &C,
- ObjCMessage msg)
-{
+void NilArgChecker::checkPreObjCMessage(ObjCMessage msg,
+ CheckerContext &C) const {
const ObjCInterfaceType *ReceiverType = GetReceiverType(msg);
if (!ReceiverType)
return;
@@ -140,14 +140,14 @@ void NilArgChecker::preVisitObjCMessage(CheckerContext &C,
//===----------------------------------------------------------------------===//
namespace {
-class CFNumberCreateChecker : public CheckerVisitor<CFNumberCreateChecker> {
- APIMisuse* BT;
- IdentifierInfo* II;
+class CFNumberCreateChecker : public CheckerV2< check::PreStmt<CallExpr> > {
+ mutable llvm::OwningPtr<APIMisuse> BT;
+ mutable IdentifierInfo* II;
public:
- CFNumberCreateChecker() : BT(0), II(0) {}
- ~CFNumberCreateChecker() {}
- static void *getTag() { static int x = 0; return &x; }
- void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
+ CFNumberCreateChecker() : II(0) {}
+
+ void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
+
private:
void EmitError(const TypedRegion* R, const Expr* Ex,
uint64_t SourceSize, uint64_t TargetSize, uint64_t NumberKind);
@@ -247,9 +247,8 @@ static const char* GetCFNumberTypeStr(uint64_t i) {
}
#endif
-void CFNumberCreateChecker::PreVisitCallExpr(CheckerContext &C,
- const CallExpr *CE)
-{
+void CFNumberCreateChecker::checkPreStmt(const CallExpr *CE,
+ CheckerContext &C) const {
const Expr* Callee = CE->getCallee();
const GRState *state = C.getState();
SVal CallV = state->getSVal(Callee);
@@ -335,7 +334,7 @@ void CFNumberCreateChecker::PreVisitCallExpr(CheckerContext &C,
<< " bits of the input integer will be lost.";
if (!BT)
- BT = new APIMisuse("Bad use of CFNumberCreate");
+ BT.reset(new APIMisuse("Bad use of CFNumberCreate"));
RangedBugReport *report = new RangedBugReport(*BT, os.str(), N);
report->addRange(CE->getArg(2)->getSourceRange());
@@ -348,19 +347,18 @@ void CFNumberCreateChecker::PreVisitCallExpr(CheckerContext &C,
//===----------------------------------------------------------------------===//
namespace {
-class CFRetainReleaseChecker : public CheckerVisitor<CFRetainReleaseChecker> {
- APIMisuse *BT;
- IdentifierInfo *Retain, *Release;
+class CFRetainReleaseChecker : public CheckerV2< check::PreStmt<CallExpr> > {
+ mutable llvm::OwningPtr<APIMisuse> BT;
+ mutable IdentifierInfo *Retain, *Release;
public:
- CFRetainReleaseChecker(): BT(0), Retain(0), Release(0) {}
- static void *getTag() { static int x = 0; return &x; }
- void PreVisitCallExpr(CheckerContext& C, const CallExpr* CE);
+ CFRetainReleaseChecker(): Retain(0), Release(0) {}
+ void checkPreStmt(const CallExpr* CE, CheckerContext& C) const;
};
} // end anonymous namespace
-void CFRetainReleaseChecker::PreVisitCallExpr(CheckerContext& C,
- const CallExpr* CE) {
+void CFRetainReleaseChecker::checkPreStmt(const CallExpr* CE,
+ CheckerContext& C) const {
// If the CallExpr doesn't have exactly 1 argument just give up checking.
if (CE->getNumArgs() != 1)
return;
@@ -377,7 +375,7 @@ void CFRetainReleaseChecker::PreVisitCallExpr(CheckerContext& C,
ASTContext &Ctx = C.getASTContext();
Retain = &Ctx.Idents.get("CFRetain");
Release = &Ctx.Idents.get("CFRelease");
- BT = new APIMisuse("null passed to CFRetain/CFRelease");
+ BT.reset(new APIMisuse("null passed to CFRetain/CFRelease"));
}
// Check if we called CFRetain/CFRelease.
@@ -431,28 +429,24 @@ void CFRetainReleaseChecker::PreVisitCallExpr(CheckerContext& C,
//===----------------------------------------------------------------------===//
namespace {
-class ClassReleaseChecker : public CheckerVisitor<ClassReleaseChecker> {
- Selector releaseS;
- Selector retainS;
- Selector autoreleaseS;
- Selector drainS;
- BugType *BT;
-public:
- ClassReleaseChecker()
- : BT(0) {}
+class ClassReleaseChecker : public CheckerV2<check::PreObjCMessage> {
+ mutable Selector releaseS;
+ mutable Selector retainS;
+ mutable Selector autoreleaseS;
+ mutable Selector drainS;
+ mutable llvm::OwningPtr<BugType> BT;
- static void *getTag() { static int x = 0; return &x; }
-
- void preVisitObjCMessage(CheckerContext &C, ObjCMessage msg);
+public:
+ void checkPreObjCMessage(ObjCMessage msg, CheckerContext &C) const;
};
}
-void ClassReleaseChecker::preVisitObjCMessage(CheckerContext &C,
- ObjCMessage msg) {
+void ClassReleaseChecker::checkPreObjCMessage(ObjCMessage msg,
+ CheckerContext &C) const {
if (!BT) {
- BT = new APIMisuse("message incorrectly sent to class instead of class "
- "instance");
+ BT.reset(new APIMisuse("message incorrectly sent to class instead of class "
+ "instance"));
ASTContext &Ctx = C.getASTContext();
releaseS = GetNullarySelector("release", Ctx);
@@ -488,34 +482,18 @@ void ClassReleaseChecker::preVisitObjCMessage(CheckerContext &C,
// Check registration.
//===----------------------------------------------------------------------===//
-static void RegisterNilArgChecker(ExprEngine& Eng) {
- Eng.registerCheck(new NilArgChecker());
-}
-
void ento::registerNilArgChecker(CheckerManager &mgr) {
- mgr.addCheckerRegisterFunction(RegisterNilArgChecker);
-}
-
-static void RegisterCFNumberCreateChecker(ExprEngine& Eng) {
- Eng.registerCheck(new CFNumberCreateChecker());
+ mgr.registerChecker<NilArgChecker>();
}
void ento::registerCFNumberCreateChecker(CheckerManager &mgr) {
- mgr.addCheckerRegisterFunction(RegisterCFNumberCreateChecker);
-}
-
-static void RegisterCFRetainReleaseChecker(ExprEngine& Eng) {
- Eng.registerCheck(new CFRetainReleaseChecker());
+ mgr.registerChecker<CFNumberCreateChecker>();
}
void ento::registerCFRetainReleaseChecker(CheckerManager &mgr) {
- mgr.addCheckerRegisterFunction(RegisterCFRetainReleaseChecker);
-}
-
-static void RegisterClassReleaseChecker(ExprEngine& Eng) {
- Eng.registerCheck(new ClassReleaseChecker());
+ mgr.registerChecker<CFRetainReleaseChecker>();
}
void ento::registerClassReleaseChecker(CheckerManager &mgr) {
- mgr.addCheckerRegisterFunction(RegisterClassReleaseChecker);
+ mgr.registerChecker<ClassReleaseChecker>();
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
index 03f9047..2566e3c 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
@@ -13,9 +13,10 @@
//===----------------------------------------------------------------------===//
#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerV2.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h"
#include "llvm/ADT/StringSwitch.h"
@@ -23,75 +24,86 @@ using namespace clang;
using namespace ento;
namespace {
-class CStringChecker : public CheckerVisitor<CStringChecker> {
- BugType *BT_Null, *BT_Bounds, *BT_BoundsWrite, *BT_Overlap, *BT_NotCString;
+class CStringChecker : public CheckerV2< eval::Call,
+ check::PreStmt<DeclStmt>,
+ check::LiveSymbols,
+ check::DeadSymbols,
+ check::RegionChanges
+ > {
+ mutable llvm::OwningPtr<BugType> BT_Null, BT_Bounds, BT_BoundsWrite,
+ BT_Overlap, BT_NotCString;
public:
- CStringChecker()
- : BT_Null(0), BT_Bounds(0), BT_BoundsWrite(0), BT_Overlap(0), BT_NotCString(0)
- {}
static void *getTag() { static int tag; return &tag; }
- bool evalCallExpr(CheckerContext &C, const CallExpr *CE);
- void PreVisitDeclStmt(CheckerContext &C, const DeclStmt *DS);
- void MarkLiveSymbols(const GRState *state, SymbolReaper &SR);
- void evalDeadSymbols(CheckerContext &C, SymbolReaper &SR);
- bool wantsRegionChangeUpdate(const GRState *state);
+ bool evalCall(const CallExpr *CE, CheckerContext &C) const;
+ void checkPreStmt(const DeclStmt *DS, CheckerContext &C) const;
+ void checkLiveSymbols(const GRState *state, SymbolReaper &SR) const;
+ void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const;
+ bool wantsRegionChangeUpdate(const GRState *state) const;
- const GRState *EvalRegionChanges(const GRState *state,
- const MemRegion * const *Begin,
- const MemRegion * const *End,
- bool*);
+ const GRState *checkRegionChanges(const GRState *state,
+ const MemRegion * const *Begin,
+ const MemRegion * const *End) const;
- typedef void (CStringChecker::*FnCheck)(CheckerContext &, const CallExpr *);
+ typedef void (CStringChecker::*FnCheck)(CheckerContext &,
+ const CallExpr *) const;
- void evalMemcpy(CheckerContext &C, const CallExpr *CE);
- void evalMemmove(CheckerContext &C, const CallExpr *CE);
- void evalBcopy(CheckerContext &C, const CallExpr *CE);
+ void evalMemcpy(CheckerContext &C, const CallExpr *CE) const;
+ void evalMemmove(CheckerContext &C, const CallExpr *CE) const;
+ void evalBcopy(CheckerContext &C, const CallExpr *CE) const;
void evalCopyCommon(CheckerContext &C, const GRState *state,
const Expr *Size, const Expr *Source, const Expr *Dest,
- bool Restricted = false);
+ bool Restricted = false) const;
- void evalMemcmp(CheckerContext &C, const CallExpr *CE);
+ void evalMemcmp(CheckerContext &C, const CallExpr *CE) const;
- void evalstrLength(CheckerContext &C, const CallExpr *CE);
+ void evalstrLength(CheckerContext &C, const CallExpr *CE) const;
+ void evalstrnLength(CheckerContext &C, const CallExpr *CE) const;
+ void evalstrLengthCommon(CheckerContext &C, const CallExpr *CE,
+ bool IsStrnlen = false) const;
- void evalStrcpy(CheckerContext &C, const CallExpr *CE);
- void evalStpcpy(CheckerContext &C, const CallExpr *CE);
- void evalStrcpyCommon(CheckerContext &C, const CallExpr *CE, bool returnEnd);
+ void evalStrcpy(CheckerContext &C, const CallExpr *CE) const;
+ void evalStrncpy(CheckerContext &C, const CallExpr *CE) const;
+ void evalStpcpy(CheckerContext &C, const CallExpr *CE) const;
+ void evalStrcpyCommon(CheckerContext &C, const CallExpr *CE, bool returnEnd,
+ bool isStrncpy) const;
// Utility methods
std::pair<const GRState*, const GRState*>
- assumeZero(CheckerContext &C, const GRState *state, SVal V, QualType Ty);
-
- const GRState *setCStringLength(const GRState *state, const MemRegion *MR,
- SVal strLength);
- SVal getCStringLengthForRegion(CheckerContext &C, const GRState *&state,
- const Expr *Ex, const MemRegion *MR);
+ static assumeZero(CheckerContext &C,
+ const GRState *state, SVal V, QualType Ty);
+
+ static const GRState *setCStringLength(const GRState *state,
+ const MemRegion *MR, SVal strLength);
+ static SVal getCStringLengthForRegion(CheckerContext &C,
+ const GRState *&state,
+ const Expr *Ex, const MemRegion *MR);
SVal getCStringLength(CheckerContext &C, const GRState *&state,
- const Expr *Ex, SVal Buf);
+ const Expr *Ex, SVal Buf) const;
- const GRState *InvalidateBuffer(CheckerContext &C, const GRState *state,
- const Expr *Ex, SVal V);
+ static const GRState *InvalidateBuffer(CheckerContext &C,
+ const GRState *state,
+ const Expr *Ex, SVal V);
- bool SummarizeRegion(llvm::raw_ostream& os, ASTContext& Ctx,
- const MemRegion *MR);
+ static bool SummarizeRegion(llvm::raw_ostream& os, ASTContext& Ctx,
+ const MemRegion *MR);
// Re-usable checks
const GRState *checkNonNull(CheckerContext &C, const GRState *state,
- const Expr *S, SVal l);
+ const Expr *S, SVal l) const;
const GRState *CheckLocation(CheckerContext &C, const GRState *state,
const Expr *S, SVal l,
- bool IsDestination = false);
+ bool IsDestination = false) const;
const GRState *CheckBufferAccess(CheckerContext &C, const GRState *state,
const Expr *Size,
const Expr *FirstBuf,
const Expr *SecondBuf = NULL,
- bool FirstIsDestination = false);
+ bool FirstIsDestination = false) const;
const GRState *CheckOverlap(CheckerContext &C, const GRState *state,
const Expr *Size, const Expr *First,
- const Expr *Second);
+ const Expr *Second) const;
void emitOverlapBug(CheckerContext &C, const GRState *state,
- const Stmt *First, const Stmt *Second);
+ const Stmt *First, const Stmt *Second) const;
};
class CStringLength {
@@ -110,14 +122,6 @@ namespace ento {
}
}
-static void RegisterCStringChecker(ExprEngine &Eng) {
- Eng.registerCheck(new CStringChecker());
-}
-
-void ento::registerCStringChecker(CheckerManager &mgr) {
- mgr.addCheckerRegisterFunction(RegisterCStringChecker);
-}
-
//===----------------------------------------------------------------------===//
// Individual checks and utility methods.
//===----------------------------------------------------------------------===//
@@ -136,7 +140,7 @@ CStringChecker::assumeZero(CheckerContext &C, const GRState *state, SVal V,
const GRState *CStringChecker::checkNonNull(CheckerContext &C,
const GRState *state,
- const Expr *S, SVal l) {
+ const Expr *S, SVal l) const {
// If a previous check has failed, propagate the failure.
if (!state)
return NULL;
@@ -150,11 +154,11 @@ const GRState *CStringChecker::checkNonNull(CheckerContext &C,
return NULL;
if (!BT_Null)
- BT_Null = new BuiltinBug("API",
- "Null pointer argument in call to byte string function");
+ BT_Null.reset(new BuiltinBug("API",
+ "Null pointer argument in call to byte string function"));
// Generate a report for this bug.
- BuiltinBug *BT = static_cast<BuiltinBug*>(BT_Null);
+ BuiltinBug *BT = static_cast<BuiltinBug*>(BT_Null.get());
EnhancedBugReport *report = new EnhancedBugReport(*BT,
BT->getDescription(), N);
@@ -173,7 +177,7 @@ const GRState *CStringChecker::checkNonNull(CheckerContext &C,
const GRState *CStringChecker::CheckLocation(CheckerContext &C,
const GRState *state,
const Expr *S, SVal l,
- bool IsDestination) {
+ bool IsDestination) const {
// If a previous check has failed, propagate the failure.
if (!state)
return NULL;
@@ -209,16 +213,16 @@ const GRState *CStringChecker::CheckLocation(CheckerContext &C,
BuiltinBug *BT;
if (IsDestination) {
if (!BT_BoundsWrite) {
- BT_BoundsWrite = new BuiltinBug("Out-of-bound array access",
- "Byte string function overflows destination buffer");
+ BT_BoundsWrite.reset(new BuiltinBug("Out-of-bound array access",
+ "Byte string function overflows destination buffer"));
}
- BT = static_cast<BuiltinBug*>(BT_BoundsWrite);
+ BT = static_cast<BuiltinBug*>(BT_BoundsWrite.get());
} else {
if (!BT_Bounds) {
- BT_Bounds = new BuiltinBug("Out-of-bound array access",
- "Byte string function accesses out-of-bound array element");
+ BT_Bounds.reset(new BuiltinBug("Out-of-bound array access",
+ "Byte string function accesses out-of-bound array element"));
}
- BT = static_cast<BuiltinBug*>(BT_Bounds);
+ BT = static_cast<BuiltinBug*>(BT_Bounds.get());
}
// FIXME: It would be nice to eventually make this diagnostic more clear,
@@ -243,7 +247,7 @@ const GRState *CStringChecker::CheckBufferAccess(CheckerContext &C,
const Expr *Size,
const Expr *FirstBuf,
const Expr *SecondBuf,
- bool FirstIsDestination) {
+ bool FirstIsDestination) const {
// If a previous check has failed, propagate the failure.
if (!state)
return NULL;
@@ -306,7 +310,7 @@ const GRState *CStringChecker::CheckOverlap(CheckerContext &C,
const GRState *state,
const Expr *Size,
const Expr *First,
- const Expr *Second) {
+ const Expr *Second) const {
// Do a simple check for overlap: if the two arguments are from the same
// buffer, see if the end of the first is greater than the start of the second
// or vice versa.
@@ -413,13 +417,13 @@ const GRState *CStringChecker::CheckOverlap(CheckerContext &C,
}
void CStringChecker::emitOverlapBug(CheckerContext &C, const GRState *state,
- const Stmt *First, const Stmt *Second) {
+ const Stmt *First, const Stmt *Second) const {
ExplodedNode *N = C.generateSink(state);
if (!N)
return;
if (!BT_Overlap)
- BT_Overlap = new BugType("Unix API", "Improper arguments");
+ BT_Overlap.reset(new BugType("Unix API", "Improper arguments"));
// Generate a report for this bug.
RangedBugReport *report =
@@ -480,13 +484,14 @@ SVal CStringChecker::getCStringLengthForRegion(CheckerContext &C,
unsigned Count = C.getNodeBuilder().getCurrentBlockCount();
SValBuilder &svalBuilder = C.getSValBuilder();
QualType sizeTy = svalBuilder.getContext().getSizeType();
- SVal strLength = svalBuilder.getMetadataSymbolVal(getTag(), MR, Ex, sizeTy, Count);
+ SVal strLength = svalBuilder.getMetadataSymbolVal(CStringChecker::getTag(),
+ MR, Ex, sizeTy, Count);
state = state->set<CStringLength>(MR, strLength);
return strLength;
}
SVal CStringChecker::getCStringLength(CheckerContext &C, const GRState *&state,
- const Expr *Ex, SVal Buf) {
+ const Expr *Ex, SVal Buf) const {
const MemRegion *MR = Buf.getAsRegion();
if (!MR) {
// If we can't get a region, see if it's something we /know/ isn't a
@@ -495,8 +500,8 @@ SVal CStringChecker::getCStringLength(CheckerContext &C, const GRState *&state,
if (loc::GotoLabel *Label = dyn_cast<loc::GotoLabel>(&Buf)) {
if (ExplodedNode *N = C.generateNode(state)) {
if (!BT_NotCString)
- BT_NotCString = new BuiltinBug("API",
- "Argument is not a null-terminated string.");
+ BT_NotCString.reset(new BuiltinBug("API",
+ "Argument is not a null-terminated string."));
llvm::SmallString<120> buf;
llvm::raw_svector_ostream os(buf);
@@ -551,8 +556,8 @@ SVal CStringChecker::getCStringLength(CheckerContext &C, const GRState *&state,
// The caller should always be prepared to handle this case.
if (ExplodedNode *N = C.generateNode(state)) {
if (!BT_NotCString)
- BT_NotCString = new BuiltinBug("API",
- "Argument is not a null-terminated string.");
+ BT_NotCString.reset(new BuiltinBug("API",
+ "Argument is not a null-terminated string."));
llvm::SmallString<120> buf;
llvm::raw_svector_ostream os(buf);
@@ -652,7 +657,7 @@ bool CStringChecker::SummarizeRegion(llvm::raw_ostream& os, ASTContext& Ctx,
void CStringChecker::evalCopyCommon(CheckerContext &C, const GRState *state,
const Expr *Size, const Expr *Dest,
- const Expr *Source, bool Restricted) {
+ const Expr *Source, bool Restricted) const {
// See if the size argument is zero.
SVal sizeVal = state->getSVal(Size);
QualType sizeTy = Size->getType();
@@ -685,7 +690,7 @@ void CStringChecker::evalCopyCommon(CheckerContext &C, const GRState *state,
}
-void CStringChecker::evalMemcpy(CheckerContext &C, const CallExpr *CE) {
+void CStringChecker::evalMemcpy(CheckerContext &C, const CallExpr *CE) const {
// void *memcpy(void *restrict dst, const void *restrict src, size_t n);
// The return value is the address of the destination buffer.
const Expr *Dest = CE->getArg(0);
@@ -694,7 +699,7 @@ void CStringChecker::evalMemcpy(CheckerContext &C, const CallExpr *CE) {
evalCopyCommon(C, state, CE->getArg(2), Dest, CE->getArg(1), true);
}
-void CStringChecker::evalMemmove(CheckerContext &C, const CallExpr *CE) {
+void CStringChecker::evalMemmove(CheckerContext &C, const CallExpr *CE) const {
// void *memmove(void *dst, const void *src, size_t n);
// The return value is the address of the destination buffer.
const Expr *Dest = CE->getArg(0);
@@ -703,12 +708,12 @@ void CStringChecker::evalMemmove(CheckerContext &C, const CallExpr *CE) {
evalCopyCommon(C, state, CE->getArg(2), Dest, CE->getArg(1));
}
-void CStringChecker::evalBcopy(CheckerContext &C, const CallExpr *CE) {
+void CStringChecker::evalBcopy(CheckerContext &C, const CallExpr *CE) const {
// void bcopy(const void *src, void *dst, size_t n);
evalCopyCommon(C, C.getState(), CE->getArg(2), CE->getArg(1), CE->getArg(0));
}
-void CStringChecker::evalMemcmp(CheckerContext &C, const CallExpr *CE) {
+void CStringChecker::evalMemcmp(CheckerContext &C, const CallExpr *CE) const {
// int memcmp(const void *s1, const void *s2, size_t n);
const Expr *Left = CE->getArg(0);
const Expr *Right = CE->getArg(1);
@@ -774,8 +779,20 @@ void CStringChecker::evalMemcmp(CheckerContext &C, const CallExpr *CE) {
}
}
-void CStringChecker::evalstrLength(CheckerContext &C, const CallExpr *CE) {
+void CStringChecker::evalstrLength(CheckerContext &C,
+ const CallExpr *CE) const {
// size_t strlen(const char *s);
+ evalstrLengthCommon(C, CE, /* IsStrnlen = */ false);
+}
+
+void CStringChecker::evalstrnLength(CheckerContext &C,
+ const CallExpr *CE) const {
+ // size_t strnlen(const char *s, size_t maxlen);
+ evalstrLengthCommon(C, CE, /* IsStrnlen = */ true);
+}
+
+void CStringChecker::evalstrLengthCommon(CheckerContext &C, const CallExpr *CE,
+ bool IsStrnlen) const {
const GRState *state = C.getState();
const Expr *Arg = CE->getArg(0);
SVal ArgVal = state->getSVal(Arg);
@@ -791,6 +808,32 @@ void CStringChecker::evalstrLength(CheckerContext &C, const CallExpr *CE) {
if (strLength.isUndef())
return;
+ // If the check is for strnlen() then bind the return value to no more than
+ // the maxlen value.
+ if (IsStrnlen) {
+ const Expr *maxlenExpr = CE->getArg(1);
+ SVal maxlenVal = state->getSVal(maxlenExpr);
+
+ NonLoc *strLengthNL = dyn_cast<NonLoc>(&strLength);
+ NonLoc *maxlenValNL = dyn_cast<NonLoc>(&maxlenVal);
+
+ QualType cmpTy = C.getSValBuilder().getContext().IntTy;
+ const GRState *stateTrue, *stateFalse;
+
+ // Check if the strLength is greater than or equal to the maxlen
+ llvm::tie(stateTrue, stateFalse) =
+ state->assume(cast<DefinedOrUnknownSVal>
+ (C.getSValBuilder().evalBinOpNN(state, BO_GE,
+ *strLengthNL, *maxlenValNL,
+ cmpTy)));
+
+ // If the strLength is greater than or equal to the maxlen, set strLength
+ // to maxlen
+ if (stateTrue && !stateFalse) {
+ strLength = maxlenVal;
+ }
+ }
+
// If getCStringLength couldn't figure out the length, conjure a return
// value, so it can be used in constraints, at least.
if (strLength.isUnknown()) {
@@ -804,18 +847,23 @@ void CStringChecker::evalstrLength(CheckerContext &C, const CallExpr *CE) {
}
}
-void CStringChecker::evalStrcpy(CheckerContext &C, const CallExpr *CE) {
+void CStringChecker::evalStrcpy(CheckerContext &C, const CallExpr *CE) const {
+ // char *strcpy(char *restrict dst, const char *restrict src);
+ evalStrcpyCommon(C, CE, /* returnEnd = */ false, /* isStrncpy = */ false);
+}
+
+void CStringChecker::evalStrncpy(CheckerContext &C, const CallExpr *CE) const {
// char *strcpy(char *restrict dst, const char *restrict src);
- evalStrcpyCommon(C, CE, /* returnEnd = */ false);
+ evalStrcpyCommon(C, CE, /* returnEnd = */ false, /* isStrncpy = */ true);
}
-void CStringChecker::evalStpcpy(CheckerContext &C, const CallExpr *CE) {
+void CStringChecker::evalStpcpy(CheckerContext &C, const CallExpr *CE) const {
// char *stpcpy(char *restrict dst, const char *restrict src);
- evalStrcpyCommon(C, CE, /* returnEnd = */ true);
+ evalStrcpyCommon(C, CE, /* returnEnd = */ true, /* isStrncpy = */ false);
}
void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE,
- bool returnEnd) {
+ bool returnEnd, bool isStrncpy) const {
const GRState *state = C.getState();
// Check that the destination is non-null
@@ -840,6 +888,31 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE,
if (strLength.isUndef())
return;
+ if (isStrncpy) {
+ // Get the max number of characters to copy
+ const Expr *lenExpr = CE->getArg(2);
+ SVal lenVal = state->getSVal(lenExpr);
+
+ NonLoc *strLengthNL = dyn_cast<NonLoc>(&strLength);
+ NonLoc *lenValNL = dyn_cast<NonLoc>(&lenVal);
+
+ QualType cmpTy = C.getSValBuilder().getContext().IntTy;
+ const GRState *stateTrue, *stateFalse;
+
+ // Check if the max number to copy is less than the length of the src
+ llvm::tie(stateTrue, stateFalse) =
+ state->assume(cast<DefinedOrUnknownSVal>
+ (C.getSValBuilder().evalBinOpNN(state, BO_GT,
+ *strLengthNL, *lenValNL,
+ cmpTy)));
+
+ if (stateTrue) {
+ // Max number to copy is less than the length of the src, so the actual
+ // strLength copied is the max number arg.
+ strLength = lenVal;
+ }
+ }
+
SVal Result = (returnEnd ? UnknownVal() : DstVal);
// If the destination is a MemRegion, try to check for a buffer overflow and
@@ -889,7 +962,7 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE,
// The driver method, and other Checker callbacks.
//===----------------------------------------------------------------------===//
-bool CStringChecker::evalCallExpr(CheckerContext &C, const CallExpr *CE) {
+bool CStringChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
// Get the callee. All the functions we care about are C functions
// with simple identifiers.
const GRState *state = C.getState();
@@ -912,8 +985,10 @@ bool CStringChecker::evalCallExpr(CheckerContext &C, const CallExpr *CE) {
.Cases("memcmp", "bcmp", &CStringChecker::evalMemcmp)
.Cases("memmove", "__memmove_chk", &CStringChecker::evalMemmove)
.Cases("strcpy", "__strcpy_chk", &CStringChecker::evalStrcpy)
+ .Cases("strncpy", "__strncpy_chk", &CStringChecker::evalStrncpy)
.Cases("stpcpy", "__stpcpy_chk", &CStringChecker::evalStpcpy)
.Case("strlen", &CStringChecker::evalstrLength)
+ .Case("strnlen", &CStringChecker::evalstrnLength)
.Case("bcopy", &CStringChecker::evalBcopy)
.Default(NULL);
@@ -926,7 +1001,7 @@ bool CStringChecker::evalCallExpr(CheckerContext &C, const CallExpr *CE) {
return true;
}
-void CStringChecker::PreVisitDeclStmt(CheckerContext &C, const DeclStmt *DS) {
+void CStringChecker::checkPreStmt(const DeclStmt *DS, CheckerContext &C) const {
// Record string length for char a[] = "abc";
const GRState *state = C.getState();
@@ -962,15 +1037,15 @@ void CStringChecker::PreVisitDeclStmt(CheckerContext &C, const DeclStmt *DS) {
C.addTransition(state);
}
-bool CStringChecker::wantsRegionChangeUpdate(const GRState *state) {
+bool CStringChecker::wantsRegionChangeUpdate(const GRState *state) const {
CStringLength::EntryMap Entries = state->get<CStringLength>();
return !Entries.isEmpty();
}
-const GRState *CStringChecker::EvalRegionChanges(const GRState *state,
- const MemRegion * const *Begin,
- const MemRegion * const *End,
- bool *) {
+const GRState *
+CStringChecker::checkRegionChanges(const GRState *state,
+ const MemRegion * const *Begin,
+ const MemRegion * const *End) const {
CStringLength::EntryMap Entries = state->get<CStringLength>();
if (Entries.isEmpty())
return state;
@@ -1017,7 +1092,8 @@ const GRState *CStringChecker::EvalRegionChanges(const GRState *state,
return state->set<CStringLength>(Entries);
}
-void CStringChecker::MarkLiveSymbols(const GRState *state, SymbolReaper &SR) {
+void CStringChecker::checkLiveSymbols(const GRState *state,
+ SymbolReaper &SR) const {
// Mark all symbols in our string length map as valid.
CStringLength::EntryMap Entries = state->get<CStringLength>();
@@ -1029,7 +1105,8 @@ void CStringChecker::MarkLiveSymbols(const GRState *state, SymbolReaper &SR) {
}
}
-void CStringChecker::evalDeadSymbols(CheckerContext &C, SymbolReaper &SR) {
+void CStringChecker::checkDeadSymbols(SymbolReaper &SR,
+ CheckerContext &C) const {
if (!SR.hasDeadSymbols())
return;
@@ -1051,3 +1128,7 @@ void CStringChecker::evalDeadSymbols(CheckerContext &C, SymbolReaper &SR) {
state = state->set<CStringLength>(Entries);
C.generateNode(state);
}
+
+void ento::registerCStringChecker(CheckerManager &mgr) {
+ mgr.registerChecker<CStringChecker>();
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp
index 518cf96..6a4506b 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp
@@ -11,30 +11,25 @@
// whether the size of the symbolic region is a multiple of the size of T.
//
//===----------------------------------------------------------------------===//
-#include "clang/AST/CharUnits.h"
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerV2.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
-#include "InternalChecks.h"
+#include "clang/AST/CharUnits.h"
using namespace clang;
using namespace ento;
namespace {
-class CastSizeChecker : public CheckerVisitor<CastSizeChecker> {
- BuiltinBug *BT;
+class CastSizeChecker : public CheckerV2< check::PreStmt<CastExpr> > {
+ mutable llvm::OwningPtr<BuiltinBug> BT;
public:
- CastSizeChecker() : BT(0) {}
- static void *getTag();
- void PreVisitCastExpr(CheckerContext &C, const CastExpr *B);
+ void checkPreStmt(const CastExpr *CE, CheckerContext &C) const;
};
}
-void *CastSizeChecker::getTag() {
- static int x;
- return &x;
-}
-
-void CastSizeChecker::PreVisitCastExpr(CheckerContext &C, const CastExpr *CE) {
+void CastSizeChecker::checkPreStmt(const CastExpr *CE,CheckerContext &C) const {
const Expr *E = CE->getSubExpr();
ASTContext &Ctx = C.getASTContext();
QualType ToTy = Ctx.getCanonicalType(CE->getType());
@@ -74,9 +69,9 @@ void CastSizeChecker::PreVisitCastExpr(CheckerContext &C, const CastExpr *CE) {
if (regionSize % typeSize != 0) {
if (ExplodedNode *errorNode = C.generateSink()) {
if (!BT)
- BT = new BuiltinBug("Cast region with wrong size.",
+ BT.reset(new BuiltinBug("Cast region with wrong size.",
"Cast a region whose size is not a multiple of the"
- " destination type size.");
+ " destination type size."));
RangedBugReport *R = new RangedBugReport(*BT, BT->getDescription(),
errorNode);
R->addRange(CE->getSourceRange());
@@ -86,6 +81,6 @@ void CastSizeChecker::PreVisitCastExpr(CheckerContext &C, const CastExpr *CE) {
}
-void ento::RegisterCastSizeChecker(ExprEngine &Eng) {
- Eng.registerCheck(new CastSizeChecker());
+void ento::registerCastSizeChecker(CheckerManager &mgr) {
+ mgr.registerChecker<CastSizeChecker>();
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp
index 8ec226a..04cc253 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp
@@ -14,31 +14,25 @@
//===----------------------------------------------------------------------===//
#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerV2.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
using namespace clang;
using namespace ento;
namespace {
-class CastToStructChecker
- : public CheckerVisitor<CastToStructChecker> {
- BuiltinBug *BT;
+class CastToStructChecker : public CheckerV2< check::PreStmt<CastExpr> > {
+ mutable llvm::OwningPtr<BuiltinBug> BT;
+
public:
- CastToStructChecker() : BT(0) {}
- static void *getTag();
- void PreVisitCastExpr(CheckerContext &C, const CastExpr *B);
+ void checkPreStmt(const CastExpr *CE, CheckerContext &C) const;
};
}
-void *CastToStructChecker::getTag() {
- static int x;
- return &x;
-}
-
-void CastToStructChecker::PreVisitCastExpr(CheckerContext &C,
- const CastExpr *CE) {
+void CastToStructChecker::checkPreStmt(const CastExpr *CE,
+ CheckerContext &C) const {
const Expr *E = CE->getSubExpr();
ASTContext &Ctx = C.getASTContext();
QualType OrigTy = Ctx.getCanonicalType(E->getType());
@@ -64,10 +58,10 @@ void CastToStructChecker::PreVisitCastExpr(CheckerContext &C,
if (!OrigPointeeTy->isRecordType()) {
if (ExplodedNode *N = C.generateNode()) {
if (!BT)
- BT = new BuiltinBug("Cast from non-struct type to struct type",
+ BT.reset(new BuiltinBug("Cast from non-struct type to struct type",
"Casting a non-structure type to a structure type "
"and accessing a field can lead to memory access "
- "errors or data corruption.");
+ "errors or data corruption."));
RangedBugReport *R = new RangedBugReport(*BT,BT->getDescription(), N);
R->addRange(CE->getSourceRange());
C.EmitReport(R);
@@ -75,10 +69,6 @@ void CastToStructChecker::PreVisitCastExpr(CheckerContext &C,
}
}
-static void RegisterCastToStructChecker(ExprEngine &Eng) {
- Eng.registerCheck(new CastToStructChecker());
-}
-
void ento::registerCastToStructChecker(CheckerManager &mgr) {
- mgr.addCheckerRegisterFunction(RegisterCastToStructChecker);
+ mgr.registerChecker<CastToStructChecker>();
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/Checkers.td b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/Checkers.td
index 1dc7486..894b961 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/Checkers.td
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/Checkers.td
@@ -71,16 +71,16 @@ def ObjCUnusedIvarsChecker : Checker<"UnusedIvars">,
HelpText<"Warn about private ivars that are never used">,
DescFile<"ObjCUnusedIVarsChecker.cpp">;
-}
+} // end "cocoa"
-def StackAddrLeakChecker : Checker<"StackAddrLeak">,
+def StackAddrEscapeChecker : Checker<"StackAddrEscape">,
InPackage<Core>,
- HelpText<"Check that addresses to stack memory are not leaked outside the function">,
- DescFile<"StackAddrLeakChecker.cpp">;
+ HelpText<"Check that addresses to stack memory do not escape the function">,
+ DescFile<"StackAddrEscapeChecker.cpp">;
def DeadStoresChecker : Checker<"DeadStores">,
InPackage<Core>,
- HelpText<"Check for stores to dead variables">,
+ HelpText<"Check for values stored to a variables that are never read afterwards">,
DescFile<"DeadStoresChecker.cpp">;
def UnixAPIChecker : Checker<"API">,
@@ -90,12 +90,12 @@ def UnixAPIChecker : Checker<"API">,
def MacOSXAPIChecker : Checker<"API">,
InPackage<MacOSX>,
- HelpText<"Check calls to various MacOSXAPIChecker">,
+ HelpText<"Check for proper uses of various Mac OS X APIs">,
DescFile<"MacOSXAPIChecker.cpp">;
def CFNumberCreateChecker : Checker<"CFNumber">,
InPackage<MacOSX>,
- HelpText<"Check for CFNumberCreate">,
+ HelpText<"Check for proper uses of CFNumberCreate">,
DescFile<"BasicObjCFoundationChecks.cpp">;
def CFRetainReleaseChecker : Checker<"CFRetainRelease">,
@@ -137,7 +137,8 @@ def CStringChecker : Checker<"CString">,
def UnreachableCodeChecker : Checker<"UnreachableCode">,
InPackage<CoreExperimental>,
HelpText<"Check unreachable code">,
- DescFile<"UnreachableCodeChecker.cpp">;
+ DescFile<"UnreachableCodeChecker.cpp">,
+ Hidden; // Must be specified explicitly in order to run.
def IdempotentOperationChecker : Checker<"IdempotentOps">,
InPackage<CoreExperimental>,
@@ -174,6 +175,21 @@ def SecuritySyntaxChecker : Checker<"SecuritySyntactic">,
HelpText<"Perform quick security checks that require no data flow">,
DescFile<"CheckSecuritySyntaxOnly.cpp">;
+def ReturnPointerRangeChecker : Checker<"ReturnPtrRange">,
+ InPackage<CoreExperimental>,
+ HelpText<"Check for an out-of-bound pointer being returned to callers">,
+ DescFile<"ReturnPointerRangeChecker.cpp">;
+
+def ArrayBoundChecker : Checker<"ArrayBound">,
+ InPackage<CoreExperimental>,
+ HelpText<"Check for an out-of-bound pointer being returned to callers">,
+ DescFile<"ArrayBoundChecker.cpp">;
+
+def CastSizeChecker : Checker<"CastSize">,
+ InPackage<CoreExperimental>,
+ HelpText<"Check when casting a malloc'ed type T, whether the size is a multiple of the size of T">,
+ DescFile<"CastSizeChecker.cpp">;
+
def ObjCDeallocChecker : Checker<"Dealloc">,
InPackage<CocoaExperimental>,
HelpText<"Warn about Objective-C classes that lack a correct implementation of -dealloc">,
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp
index 36e76d0..b6eef6d 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp
@@ -12,9 +12,10 @@
//===----------------------------------------------------------------------===//
#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerV2.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
@@ -37,38 +38,30 @@ bool isRootChanged(intptr_t k) { return k == ROOT_CHANGED; }
// ROOT_CHANGED<--chdir(..)-- JAIL_ENTERED<--chdir(..)--
// | |
// bug<--foo()-- JAIL_ENTERED<--foo()--
-class ChrootChecker : public CheckerVisitor<ChrootChecker> {
- IdentifierInfo *II_chroot, *II_chdir;
+class ChrootChecker : public CheckerV2<eval::Call, check::PreStmt<CallExpr> > {
+ mutable IdentifierInfo *II_chroot, *II_chdir;
// This bug refers to possibly break out of a chroot() jail.
- BuiltinBug *BT_BreakJail;
+ mutable llvm::OwningPtr<BuiltinBug> BT_BreakJail;
public:
- ChrootChecker() : II_chroot(0), II_chdir(0), BT_BreakJail(0) {}
+ ChrootChecker() : II_chroot(0), II_chdir(0) {}
static void *getTag() {
static int x;
return &x;
}
- virtual bool evalCallExpr(CheckerContext &C, const CallExpr *CE);
- virtual void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
+ bool evalCall(const CallExpr *CE, CheckerContext &C) const;
+ void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
private:
- void Chroot(CheckerContext &C, const CallExpr *CE);
- void Chdir(CheckerContext &C, const CallExpr *CE);
+ void Chroot(CheckerContext &C, const CallExpr *CE) const;
+ void Chdir(CheckerContext &C, const CallExpr *CE) const;
};
} // end anonymous namespace
-static void RegisterChrootChecker(ExprEngine &Eng) {
- Eng.registerCheck(new ChrootChecker());
-}
-
-void ento::registerChrootChecker(CheckerManager &mgr) {
- mgr.addCheckerRegisterFunction(RegisterChrootChecker);
-}
-
-bool ChrootChecker::evalCallExpr(CheckerContext &C, const CallExpr *CE) {
+bool ChrootChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
const GRState *state = C.getState();
const Expr *Callee = CE->getCallee();
SVal L = state->getSVal(Callee);
@@ -94,7 +87,7 @@ bool ChrootChecker::evalCallExpr(CheckerContext &C, const CallExpr *CE) {
return false;
}
-void ChrootChecker::Chroot(CheckerContext &C, const CallExpr *CE) {
+void ChrootChecker::Chroot(CheckerContext &C, const CallExpr *CE) const {
const GRState *state = C.getState();
GRStateManager &Mgr = state->getStateManager();
@@ -104,7 +97,7 @@ void ChrootChecker::Chroot(CheckerContext &C, const CallExpr *CE) {
C.addTransition(state);
}
-void ChrootChecker::Chdir(CheckerContext &C, const CallExpr *CE) {
+void ChrootChecker::Chdir(CheckerContext &C, const CallExpr *CE) const {
const GRState *state = C.getState();
GRStateManager &Mgr = state->getStateManager();
@@ -131,7 +124,7 @@ void ChrootChecker::Chdir(CheckerContext &C, const CallExpr *CE) {
}
// Check the jail state before any function call except chroot and chdir().
-void ChrootChecker::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) {
+void ChrootChecker::checkPreStmt(const CallExpr *CE, CheckerContext &C) const {
const GRState *state = C.getState();
const Expr *Callee = CE->getCallee();
SVal L = state->getSVal(Callee);
@@ -155,9 +148,9 @@ void ChrootChecker::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) {
if (isRootChanged((intptr_t) *k))
if (ExplodedNode *N = C.generateNode()) {
if (!BT_BreakJail)
- BT_BreakJail = new BuiltinBug("Break out of jail",
+ BT_BreakJail.reset(new BuiltinBug("Break out of jail",
"No call of chdir(\"/\") immediately "
- "after chroot");
+ "after chroot"));
BugReport *R = new BugReport(*BT_BreakJail,
BT_BreakJail->getDescription(), N);
C.EmitReport(R);
@@ -165,3 +158,7 @@ void ChrootChecker::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) {
return;
}
+
+void ento::registerChrootChecker(CheckerManager &mgr) {
+ mgr.registerChecker<ChrootChecker>();
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ClangSACheckerProvider.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ClangSACheckerProvider.cpp
index 94f200f..5c0c950 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ClangSACheckerProvider.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ClangSACheckerProvider.cpp
@@ -16,7 +16,9 @@
#include "ClangSACheckers.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/CheckerProvider.h"
+#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/DenseSet.h"
+#include "map"
using namespace clang;
using namespace ento;
@@ -28,6 +30,7 @@ class ClangSACheckerProvider : public CheckerProvider {
public:
virtual void registerCheckers(CheckerManager &checkerMgr,
CheckerOptInfo *checkOpts, unsigned numCheckOpts);
+ virtual void printHelp(llvm::raw_ostream &OS);
};
}
@@ -41,6 +44,7 @@ namespace {
struct StaticCheckerInfoRec {
const char *FullName;
void (*RegFunc)(CheckerManager &mgr);
+ const char *HelpText;
bool Hidden;
};
@@ -49,13 +53,16 @@ struct StaticCheckerInfoRec {
static const StaticCheckerInfoRec StaticCheckerInfo[] = {
#define GET_CHECKERS
#define CHECKER(FULLNAME,CLASS,DESCFILE,HELPTEXT,HIDDEN) \
- { FULLNAME, register##CLASS, HIDDEN },
+ { FULLNAME, register##CLASS, HELPTEXT, HIDDEN },
#include "Checkers.inc"
- { 0, 0, 0}
+ { 0, 0, 0, 0}
#undef CHECKER
#undef GET_CHECKERS
};
+static const unsigned NumCheckers = sizeof(StaticCheckerInfo)
+ / sizeof(StaticCheckerInfoRec) - 1;
+
namespace {
struct CheckNameOption {
@@ -104,9 +111,10 @@ static void collectCheckers(const CheckNameOption *checkName,
// Enable/disable all subgroups along with this one.
if (const short *subGroups = checkName->SubGroups) {
- for (; *subGroups != -1; ++subGroups)
- collectCheckers(&CheckNameTable[*subGroups], enable, checkers,
- collectHidden && checkName->Hidden);
+ for (; *subGroups != -1; ++subGroups) {
+ const CheckNameOption *sub = &CheckNameTable[*subGroups];
+ collectCheckers(sub, enable, checkers, collectHidden && !sub->Hidden);
+ }
}
}
@@ -135,3 +143,41 @@ void ClangSACheckerProvider::registerCheckers(CheckerManager &checkerMgr,
(*I)->RegFunc(checkerMgr);
}
}
+
+typedef std::map<std::string, const StaticCheckerInfoRec *> SortedCheckers;
+
+static void printCheckerOption(llvm::raw_ostream &OS,SortedCheckers &checkers) {
+ // Find the maximum option length.
+ unsigned OptionFieldWidth = 0;
+ for (SortedCheckers::iterator
+ I = checkers.begin(), E = checkers.end(); I != E; ++I) {
+ // Limit the amount of padding we are willing to give up for alignment.
+ unsigned Length = strlen(I->second->FullName);
+ if (Length <= 30)
+ OptionFieldWidth = std::max(OptionFieldWidth, Length);
+ }
+
+ const unsigned InitialPad = 2;
+ for (SortedCheckers::iterator
+ I = checkers.begin(), E = checkers.end(); I != E; ++I) {
+ const std::string &Option = I->first;
+ int Pad = OptionFieldWidth - int(Option.size());
+ OS.indent(InitialPad) << Option;
+
+ // Break on long option names.
+ if (Pad < 0) {
+ OS << "\n";
+ Pad = OptionFieldWidth + InitialPad;
+ }
+ OS.indent(Pad + 1) << I->second->HelpText << '\n';
+ }
+}
+
+void ClangSACheckerProvider::printHelp(llvm::raw_ostream &OS) {
+ // Sort checkers according to their full name.
+ SortedCheckers checkers;
+ for (unsigned i = 0; i != NumCheckers; ++i)
+ checkers[StaticCheckerInfo[i].FullName] = &StaticCheckerInfo[i];
+
+ printCheckerOption(OS, checkers);
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExperimentalChecks.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExperimentalChecks.cpp
index d9bb480..990ba1c0 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExperimentalChecks.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExperimentalChecks.cpp
@@ -24,14 +24,3 @@ void ento::RegisterExperimentalChecks(ExprEngine &Eng) {
// within ExprEngine.
RegisterMallocChecker(Eng); // ArrayBoundChecker depends on this.
}
-
-void ento::RegisterExperimentalInternalChecks(ExprEngine &Eng) {
- // These are internal checks that should eventually migrate to
- // RegisterInternalChecks() once they have been further tested.
-
- // Note that this must be registered after ReturnStackAddresEngsChecker.
- RegisterReturnPointerRangeChecker(Eng);
-
- RegisterArrayBoundChecker(Eng);
- RegisterCastSizeChecker(Eng);
-}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExprEngine.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExprEngine.cpp
index ab8d564..c1b1e65 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExprEngine.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExprEngine.cpp
@@ -92,12 +92,13 @@ void ExprEngine::CheckerVisit(const Stmt *S, ExplodedNodeSet &Dst,
}
if (CO->empty()) {
- // If there are no checkers, return early without doing any
- // more work.
- Dst.insert(Src);
+ // If there are no checkers, just delegate to the checker manager.
+ getCheckerManager().runCheckersForStmt(Kind == PreVisitStmtCallback,
+ Dst, Src, S, *this);
return;
}
+ ExplodedNodeSet CheckersV1Dst;
ExplodedNodeSet Tmp;
ExplodedNodeSet *PrevSet = &Src;
unsigned checkersEvaluated = 0;
@@ -108,7 +109,7 @@ void ExprEngine::CheckerVisit(const Stmt *S, ExplodedNodeSet &Dst,
break;
ExplodedNodeSet *CurrSet = 0;
if (I+1 == E)
- CurrSet = &Dst;
+ CurrSet = &CheckersV1Dst;
else {
CurrSet = (PrevSet == &Tmp) ? &Src : &Tmp;
CurrSet->clear();
@@ -144,6 +145,9 @@ void ExprEngine::CheckerVisit(const Stmt *S, ExplodedNodeSet &Dst,
// Don't autotransition. The CheckerContext objects should do this
// automatically.
+
+ getCheckerManager().runCheckersForStmt(Kind == PreVisitStmtCallback,
+ Dst, CheckersV1Dst, S, *this);
}
void ExprEngine::CheckerVisitObjCMessage(const ObjCMessage &msg,
@@ -152,10 +156,12 @@ void ExprEngine::CheckerVisitObjCMessage(const ObjCMessage &msg,
bool isPrevisit) {
if (Checkers.empty()) {
- Dst.insert(Src);
+ getCheckerManager().runCheckersForObjCMessage(isPrevisit, Dst, Src, msg,
+ *this);
return;
}
+ ExplodedNodeSet CheckersV1Dst;
ExplodedNodeSet Tmp;
ExplodedNodeSet *PrevSet = &Src;
@@ -163,7 +169,7 @@ void ExprEngine::CheckerVisitObjCMessage(const ObjCMessage &msg,
{
ExplodedNodeSet *CurrSet = 0;
if (I+1 == E)
- CurrSet = &Dst;
+ CurrSet = &CheckersV1Dst;
else {
CurrSet = (PrevSet == &Tmp) ? &Src : &Tmp;
CurrSet->clear();
@@ -181,8 +187,8 @@ void ExprEngine::CheckerVisitObjCMessage(const ObjCMessage &msg,
PrevSet = CurrSet;
}
- // Don't autotransition. The CheckerContext objects should do this
- // automatically.
+ getCheckerManager().runCheckersForObjCMessage(isPrevisit, Dst, CheckersV1Dst,
+ msg, *this);
}
void ExprEngine::CheckerEvalNilReceiver(const ObjCMessage &msg,
@@ -232,11 +238,25 @@ bool ExprEngine::CheckerEvalCall(const CallExpr *CE,
DstTmp.clear();
}
- if (evaluated)
+ if (evaluated) {
Dst.insert(DstTmp);
- else
- Dst.insert(Pred);
+ return evaluated;
+ }
+
+ class DefaultEval : public GraphExpander {
+ bool &Evaluated;
+ public:
+ DefaultEval(bool &evaluated) : Evaluated(evaluated) { }
+ virtual void expandGraph(ExplodedNodeSet &Dst, ExplodedNode *Pred) {
+ Evaluated = false;
+ Dst.insert(Pred);
+ }
+ };
+ evaluated = true;
+ DefaultEval defaultEval(evaluated);
+ getCheckerManager().runCheckersForEvalCall(Dst, Pred, CE, *this,
+ &defaultEval);
return evaluated;
}
@@ -335,8 +355,6 @@ ExprEngine::ExprEngine(AnalysisManager &mgr, TransferFuncs *tf)
// FIXME: Eventually remove the TF object entirely.
TF->RegisterChecks(*this);
TF->RegisterPrinters(getStateManager().Printers);
-
- mgr.getCheckerManager()->registerCheckersToEngine(*this);
if (mgr.shouldEagerlyTrimExplodedGraph()) {
// Enable eager node reclaimation when constructing the ExplodedGraph.
@@ -495,7 +513,7 @@ bool ExprEngine::wantsRegionChangeUpdate(const GRState* state) {
return true;
}
- return false;
+ return getCheckerManager().wantsRegionChangeUpdate(state);
}
const GRState *
@@ -523,9 +541,9 @@ ExprEngine::processRegionChanges(const GRState *state,
CO = CO_Ref;
}
- // If there are no checkers, just return the state as is.
+ // If there are no checkers, just delegate to the checker manager.
if (CO->empty())
- return state;
+ return getCheckerManager().runCheckersForRegionChanges(state, Begin, End);
for (CheckersOrdered::iterator I = CO->begin(), E = CO->end(); I != E; ++I) {
// If any checker declares the state infeasible (or if it starts that way),
@@ -548,7 +566,7 @@ ExprEngine::processRegionChanges(const GRState *state,
if (NewCO.get())
CO_Ref = NewCO.take();
- return state;
+ return getCheckerManager().runCheckersForRegionChanges(state, Begin, End);
}
void ExprEngine::processEndWorklist(bool hasWorkRemaining) {
@@ -556,6 +574,7 @@ void ExprEngine::processEndWorklist(bool hasWorkRemaining) {
I != E; ++I) {
I->second->VisitEndAnalysis(G, BR, *this);
}
+ getCheckerManager().runCheckersForEndAnalysis(G, BR, *this);
}
void ExprEngine::processCFGElement(const CFGElement E,
@@ -603,6 +622,8 @@ void ExprEngine::ProcessStmt(const CFGStmt S, StmtNodeBuilder& builder) {
checker->MarkLiveSymbols(St, SymReaper);
}
+ getCheckerManager().runCheckersForLiveSymbols(St, SymReaper);
+
const StackFrameContext *SFC = LC->getCurrentStackFrame();
CleanedState = StateMgr.removeDeadBindings(St, SFC, SymReaper);
} else {
@@ -626,8 +647,9 @@ void ExprEngine::ProcessStmt(const CFGStmt S, StmtNodeBuilder& builder) {
getTF().evalDeadSymbols(Tmp2, *this, *Builder, EntryNode,
CleanedState, SymReaper);
+ ExplodedNodeSet checkersV1Tmp;
if (Checkers.empty())
- Tmp.insert(Tmp2);
+ checkersV1Tmp.insert(Tmp2);
else {
ExplodedNodeSet Tmp3;
ExplodedNodeSet *SrcSet = &Tmp2;
@@ -635,7 +657,7 @@ void ExprEngine::ProcessStmt(const CFGStmt S, StmtNodeBuilder& builder) {
I != E; ++I) {
ExplodedNodeSet *DstSet = 0;
if (I+1 == E)
- DstSet = &Tmp;
+ DstSet = &checkersV1Tmp;
else {
DstSet = (SrcSet == &Tmp2) ? &Tmp3 : &Tmp2;
DstSet->clear();
@@ -651,6 +673,9 @@ void ExprEngine::ProcessStmt(const CFGStmt S, StmtNodeBuilder& builder) {
}
}
+ getCheckerManager().runCheckersForDeadSymbols(Tmp, checkersV1Tmp,
+ SymReaper, currentStmt, *this);
+
if (!Builder->BuildSinks && !Builder->hasGeneratedNode)
Tmp.Add(EntryNode);
}
@@ -1419,8 +1444,10 @@ void ExprEngine::processEndOfFunction(EndOfFunctionNodeBuilder& builder) {
for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end(); I!=E;++I){
void *tag = I->first;
Checker *checker = I->second;
- checker->evalEndPath(builder, tag, *this);
+ EndOfFunctionNodeBuilder B = builder.withCheckerTag(tag);
+ checker->evalEndPath(B, tag, *this);
}
+ getCheckerManager().runCheckersForEndPath(builder, *this);
}
/// ProcessSwitch - Called by CoreEngine. Used to generate successor
@@ -1923,20 +1950,35 @@ void ExprEngine::evalLocation(ExplodedNodeSet &Dst, const Stmt *S,
const GRState* state, SVal location,
const void *tag, bool isLoad) {
// Early checks for performance reason.
- if (location.isUnknown() || Checkers.empty()) {
+ if (location.isUnknown()) {
Dst.Add(Pred);
return;
}
- ExplodedNodeSet Src, Tmp;
+ if (Checkers.empty()) {
+ ExplodedNodeSet Src;
+ if (Builder->GetState(Pred) == state) {
+ Src.Add(Pred);
+ } else {
+ // Associate this new state with an ExplodedNode.
+ Src.Add(Builder->generateNode(S, state, Pred));
+ }
+ getCheckerManager().runCheckersForLocation(Dst, Src, location, isLoad, S,
+ *this);
+ return;
+ }
+
+ ExplodedNodeSet Src;
Src.Add(Pred);
+ ExplodedNodeSet CheckersV1Dst;
+ ExplodedNodeSet Tmp;
ExplodedNodeSet *PrevSet = &Src;
for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end(); I!=E; ++I)
{
ExplodedNodeSet *CurrSet = 0;
if (I+1 == E)
- CurrSet = &Dst;
+ CurrSet = &CheckersV1Dst;
else {
CurrSet = (PrevSet == &Tmp) ? &Src : &Tmp;
CurrSet->clear();
@@ -1957,6 +1999,9 @@ void ExprEngine::evalLocation(ExplodedNodeSet &Dst, const Stmt *S,
// Update which NodeSet is the current one.
PrevSet = CurrSet;
}
+
+ getCheckerManager().runCheckersForLocation(Dst, CheckersV1Dst, location,
+ isLoad, S, *this);
}
bool ExprEngine::InlineCall(ExplodedNodeSet &Dst, const CallExpr *CE,
@@ -3613,14 +3658,12 @@ void ExprEngine::ViewGraph(bool trim) {
const_cast<BugType*>(*I)->FlushReports(BR);
// Iterate through the reports and get their nodes.
- for (BugReporter::iterator I=BR.begin(), E=BR.end(); I!=E; ++I) {
- for (BugType::const_iterator I2=(*I)->begin(), E2=(*I)->end();
- I2!=E2; ++I2) {
- const BugReportEquivClass& EQ = *I2;
- const BugReport &R = **EQ.begin();
- ExplodedNode *N = const_cast<ExplodedNode*>(R.getErrorNode());
- if (N) Src.push_back(N);
- }
+ for (BugReporter::EQClasses_iterator
+ EI = BR.EQClasses_begin(), EE = BR.EQClasses_end(); EI != EE; ++EI) {
+ BugReportEquivClass& EQ = *EI;
+ const BugReport &R = **EQ.begin();
+ ExplodedNode *N = const_cast<ExplodedNode*>(R.getErrorNode());
+ if (N) Src.push_back(N);
}
ViewGraph(&Src[0], &Src[0]+Src.size());
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp
index fe628a2..d7b27b5 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp
@@ -14,31 +14,26 @@
//===----------------------------------------------------------------------===//
#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerV2.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
using namespace clang;
using namespace ento;
namespace {
class FixedAddressChecker
- : public CheckerVisitor<FixedAddressChecker> {
- BuiltinBug *BT;
+ : public CheckerV2< check::PreStmt<BinaryOperator> > {
+ mutable llvm::OwningPtr<BuiltinBug> BT;
+
public:
- FixedAddressChecker() : BT(0) {}
- static void *getTag();
- void PreVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B);
+ void checkPreStmt(const BinaryOperator *B, CheckerContext &C) const;
};
}
-void *FixedAddressChecker::getTag() {
- static int x;
- return &x;
-}
-
-void FixedAddressChecker::PreVisitBinaryOperator(CheckerContext &C,
- const BinaryOperator *B) {
+void FixedAddressChecker::checkPreStmt(const BinaryOperator *B,
+ CheckerContext &C) const {
// Using a fixed address is not portable because that address will probably
// not be valid in all environments or platforms.
@@ -58,20 +53,16 @@ void FixedAddressChecker::PreVisitBinaryOperator(CheckerContext &C,
if (ExplodedNode *N = C.generateNode()) {
if (!BT)
- BT = new BuiltinBug("Use fixed address",
+ BT.reset(new BuiltinBug("Use fixed address",
"Using a fixed address is not portable because that "
"address will probably not be valid in all "
- "environments or platforms.");
+ "environments or platforms."));
RangedBugReport *R = new RangedBugReport(*BT, BT->getDescription(), N);
R->addRange(B->getRHS()->getSourceRange());
C.EmitReport(R);
}
}
-static void RegisterFixedAddressChecker(ExprEngine &Eng) {
- Eng.registerCheck(new FixedAddressChecker());
-}
-
void ento::registerFixedAddressChecker(CheckerManager &mgr) {
- mgr.addCheckerRegisterFunction(RegisterFixedAddressChecker);
+ mgr.registerChecker<FixedAddressChecker>();
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp
index f49b125..83d9668 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp
@@ -45,11 +45,13 @@
#include "ClangSACheckers.h"
#include "clang/Analysis/CFGStmtMap.h"
#include "clang/Analysis/Analyses/PseudoConstantAnalysis.h"
+#include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h"
+#include "clang/StaticAnalyzer/Core/CheckerV2.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
#include "clang/AST/Stmt.h"
@@ -64,29 +66,29 @@ using namespace ento;
namespace {
class IdempotentOperationChecker
- : public CheckerVisitor<IdempotentOperationChecker> {
+ : public CheckerV2<check::PreStmt<BinaryOperator>,
+ check::PostStmt<BinaryOperator>,
+ check::EndAnalysis> {
public:
- static void *getTag();
- void PreVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B);
- void PostVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B);
- void VisitEndAnalysis(ExplodedGraph &G, BugReporter &B, ExprEngine &Eng);
+ void checkPreStmt(const BinaryOperator *B, CheckerContext &C) const;
+ void checkPostStmt(const BinaryOperator *B, CheckerContext &C) const;
+ void checkEndAnalysis(ExplodedGraph &G, BugReporter &B,ExprEngine &Eng) const;
private:
// Our assumption about a particular operation.
enum Assumption { Possible = 0, Impossible, Equal, LHSis1, RHSis1, LHSis0,
RHSis0 };
- void UpdateAssumption(Assumption &A, const Assumption &New);
+ static void UpdateAssumption(Assumption &A, const Assumption &New);
// False positive reduction methods
static bool isSelfAssign(const Expr *LHS, const Expr *RHS);
static bool isUnused(const Expr *E, AnalysisContext *AC);
static bool isTruncationExtensionAssignment(const Expr *LHS,
const Expr *RHS);
- bool pathWasCompletelyAnalyzed(const CFG *cfg,
- const CFGBlock *CB,
- const CFGStmtMap *CBM,
- const CoreEngine &CE);
+ static bool pathWasCompletelyAnalyzed(AnalysisContext *AC,
+ const CFGBlock *CB,
+ const CoreEngine &CE);
static bool CanVary(const Expr *Ex,
AnalysisContext *AC);
static bool isConstantOrPseudoConstant(const DeclRefExpr *DR,
@@ -104,46 +106,12 @@ private:
};
typedef llvm::DenseMap<const BinaryOperator *, BinaryOperatorData>
AssumptionMap;
- AssumptionMap hash;
-
- // A class that performs reachability queries for CFGBlocks. Several internal
- // checks in this checker require reachability information. The requests all
- // tend to have a common destination, so we lazily do a predecessor search
- // from the destination node and cache the results to prevent work
- // duplication.
- class CFGReachabilityAnalysis {
- typedef llvm::BitVector ReachableSet;
- typedef llvm::DenseMap<unsigned, ReachableSet> ReachableMap;
- ReachableSet analyzed;
- ReachableMap reachable;
- public:
- CFGReachabilityAnalysis(const CFG &cfg)
- : analyzed(cfg.getNumBlockIDs(), false) {}
-
- inline bool isReachable(const CFGBlock *Src, const CFGBlock *Dst);
- private:
- void MapReachability(const CFGBlock *Dst);
- };
- llvm::OwningPtr<CFGReachabilityAnalysis> CRA;
+ mutable AssumptionMap hash;
};
}
-void *IdempotentOperationChecker::getTag() {
- static int x = 0;
- return &x;
-}
-
-static void RegisterIdempotentOperationChecker(ExprEngine &Eng) {
- Eng.registerCheck(new IdempotentOperationChecker());
-}
-
-void ento::registerIdempotentOperationChecker(CheckerManager &mgr) {
- mgr.addCheckerRegisterFunction(RegisterIdempotentOperationChecker);
-}
-
-void IdempotentOperationChecker::PreVisitBinaryOperator(
- CheckerContext &C,
- const BinaryOperator *B) {
+void IdempotentOperationChecker::checkPreStmt(const BinaryOperator *B,
+ CheckerContext &C) const {
// Find or create an entry in the hash for this BinaryOperator instance.
// If we haven't done a lookup before, it will get default initialized to
// 'Possible'. At this stage we do not store the ExplodedNode, as it has not
@@ -359,9 +327,8 @@ void IdempotentOperationChecker::PreVisitBinaryOperator(
// At the post visit stage, the predecessor ExplodedNode will be the
// BinaryOperator that was just created. We use this hook to collect the
// ExplodedNode.
-void IdempotentOperationChecker::PostVisitBinaryOperator(
- CheckerContext &C,
- const BinaryOperator *B) {
+void IdempotentOperationChecker::checkPostStmt(const BinaryOperator *B,
+ CheckerContext &C) const {
// Add the ExplodedNode we just visited
BinaryOperatorData &Data = hash[B];
@@ -376,9 +343,9 @@ void IdempotentOperationChecker::PostVisitBinaryOperator(
Data.explodedNodes.Add(C.getPredecessor());
}
-void IdempotentOperationChecker::VisitEndAnalysis(ExplodedGraph &G,
+void IdempotentOperationChecker::checkEndAnalysis(ExplodedGraph &G,
BugReporter &BR,
- ExprEngine &Eng) {
+ ExprEngine &Eng) const {
BugType *BT = new BugType("Idempotent operation", "Dead code");
// Iterate over the hash to see if we have any paths with definite
// idempotent operations.
@@ -397,16 +364,11 @@ void IdempotentOperationChecker::VisitEndAnalysis(ExplodedGraph &G,
// If the analyzer did not finish, check to see if we can still emit this
// warning
if (Eng.hasWorkRemaining()) {
- const CFGStmtMap *CBM = CFGStmtMap::Build(AC->getCFG(),
- &AC->getParentMap());
-
// If we can trace back
- if (!pathWasCompletelyAnalyzed(AC->getCFG(),
- CBM->getBlock(B), CBM,
+ if (!pathWasCompletelyAnalyzed(AC,
+ AC->getCFGStmtMap()->getBlock(B),
Eng.getCoreEngine()))
continue;
-
- delete CBM;
}
// Select the error message and SourceRanges to report.
@@ -464,6 +426,8 @@ void IdempotentOperationChecker::VisitEndAnalysis(ExplodedGraph &G,
BR.EmitReport(report);
}
}
+
+ hash.clear();
}
// Updates the current assumption given the new assumption
@@ -564,13 +528,11 @@ bool IdempotentOperationChecker::isTruncationExtensionAssignment(
// Returns false if a path to this block was not completely analyzed, or true
// otherwise.
bool
-IdempotentOperationChecker::pathWasCompletelyAnalyzed(const CFG *cfg,
+IdempotentOperationChecker::pathWasCompletelyAnalyzed(AnalysisContext *AC,
const CFGBlock *CB,
- const CFGStmtMap *CBM,
const CoreEngine &CE) {
- if (!CRA.get())
- CRA.reset(new CFGReachabilityAnalysis(*cfg));
+ CFGReachabilityAnalysis *CRA = AC->getCFGReachablityAnalysis();
// Test for reachability from any aborted blocks to this block
typedef CoreEngine::BlocksAborted::const_iterator AbortedIterator;
@@ -621,14 +583,14 @@ IdempotentOperationChecker::pathWasCompletelyAnalyzed(const CFG *cfg,
return CRA.isReachable(B, TargetBlock);
}
};
- VisitWL visitWL(CBM, CB, *CRA.get());
+ VisitWL visitWL(AC->getCFGStmtMap(), CB, *CRA);
// Were there any items in the worklist that could potentially reach
// this block?
if (CE.getWorkList()->visitItemsInWorkList(visitWL))
return false;
// Verify that this block is reachable from the entry block
- if (!CRA->isReachable(&cfg->getEntry(), CB))
+ if (!CRA->isReachable(&AC->getCFG()->getEntry(), CB))
return false;
// If we get to this point, there is no connection to the entry block or an
@@ -766,57 +728,7 @@ bool IdempotentOperationChecker::containsNonLocalVarDecl(const Stmt *S) {
return false;
}
-bool IdempotentOperationChecker::CFGReachabilityAnalysis::isReachable(
- const CFGBlock *Src,
- const CFGBlock *Dst) {
- const unsigned DstBlockID = Dst->getBlockID();
- // If we haven't analyzed the destination node, run the analysis now
- if (!analyzed[DstBlockID]) {
- MapReachability(Dst);
- analyzed[DstBlockID] = true;
- }
-
- // Return the cached result
- return reachable[DstBlockID][Src->getBlockID()];
-}
-
-// Maps reachability to a common node by walking the predecessors of the
-// destination node.
-void IdempotentOperationChecker::CFGReachabilityAnalysis::MapReachability(
- const CFGBlock *Dst) {
-
- llvm::SmallVector<const CFGBlock *, 11> worklist;
- llvm::BitVector visited(analyzed.size());
-
- ReachableSet &DstReachability = reachable[Dst->getBlockID()];
- DstReachability.resize(analyzed.size(), false);
-
- // Start searching from the destination node, since we commonly will perform
- // multiple queries relating to a destination node.
- worklist.push_back(Dst);
- bool firstRun = true;
-
- while (!worklist.empty()) {
- const CFGBlock *block = worklist.back();
- worklist.pop_back();
-
- if (visited[block->getBlockID()])
- continue;
- visited[block->getBlockID()] = true;
-
- // Update reachability information for this node -> Dst
- if (!firstRun) {
- // Don't insert Dst -> Dst unless it was a predecessor of itself
- DstReachability[block->getBlockID()] = true;
- }
- else
- firstRun = false;
-
- // Add the predecessors to the worklist.
- for (CFGBlock::const_pred_iterator i = block->pred_begin(),
- e = block->pred_end(); i != e; ++i) {
- worklist.push_back(*i);
- }
- }
+void ento::registerIdempotentOperationChecker(CheckerManager &mgr) {
+ mgr.registerChecker<IdempotentOperationChecker>();
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/InternalChecks.h b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/InternalChecks.h
index e855386..e7c38ee 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/InternalChecks.h
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/InternalChecks.h
@@ -23,16 +23,13 @@ class ExprEngine;
// Foundational checks that handle basic semantics.
void RegisterAdjustedReturnValueChecker(ExprEngine &Eng);
-void RegisterArrayBoundChecker(ExprEngine &Eng);
void RegisterArrayBoundCheckerV2(ExprEngine &Eng);
void RegisterAttrNonNullChecker(ExprEngine &Eng);
void RegisterBuiltinFunctionChecker(ExprEngine &Eng);
void RegisterCallAndMessageChecker(ExprEngine &Eng);
-void RegisterCastSizeChecker(ExprEngine &Eng);
void RegisterDereferenceChecker(ExprEngine &Eng);
void RegisterDivZeroChecker(ExprEngine &Eng);
void RegisterNoReturnFunctionChecker(ExprEngine &Eng);
-void RegisterReturnPointerRangeChecker(ExprEngine &Eng);
void RegisterReturnUndefChecker(ExprEngine &Eng);
void RegisterUndefBranchChecker(ExprEngine &Eng);
void RegisterUndefCapturedBlockVarChecker(ExprEngine &Eng);
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp
index 358be12..d70c65a 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp
@@ -16,11 +16,12 @@
//===----------------------------------------------------------------------===//
#include "ClangSACheckers.h"
-#include "clang/Basic/TargetInfo.h"
+#include "clang/StaticAnalyzer/Core/CheckerV2.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h"
+#include "clang/Basic/TargetInfo.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/raw_ostream.h"
@@ -29,31 +30,26 @@ using namespace clang;
using namespace ento;
namespace {
-class MacOSXAPIChecker : public CheckerVisitor<MacOSXAPIChecker> {
+class MacOSXAPIChecker : public CheckerV2< check::PreStmt<CallExpr> > {
enum SubChecks {
DispatchOnce = 0,
DispatchOnceF,
NumChecks
};
- BugType *BTypes[NumChecks];
+ mutable BugType *BTypes[NumChecks];
public:
MacOSXAPIChecker() { memset(BTypes, 0, sizeof(*BTypes) * NumChecks); }
- static void *getTag() { static unsigned tag = 0; return &tag; }
+ ~MacOSXAPIChecker() {
+ for (unsigned i=0; i != NumChecks; ++i)
+ delete BTypes[i];
+ }
- void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
+ void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
};
} //end anonymous namespace
-static void RegisterMacOSXAPIChecker(ExprEngine &Eng) {
- Eng.registerCheck(new MacOSXAPIChecker());
-}
-
-void ento::registerMacOSXAPIChecker(CheckerManager &mgr) {
- mgr.addCheckerRegisterFunction(RegisterMacOSXAPIChecker);
-}
-
//===----------------------------------------------------------------------===//
// dispatch_once and dispatch_once_f
//===----------------------------------------------------------------------===//
@@ -121,7 +117,8 @@ namespace {
};
} // end anonymous namespace
-void MacOSXAPIChecker::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) {
+void MacOSXAPIChecker::checkPreStmt(const CallExpr *CE,
+ CheckerContext &C) const {
// FIXME: Mostly copy and paste from UnixAPIChecker. Should refactor.
const GRState *state = C.getState();
const Expr *Callee = CE->getCallee();
@@ -144,3 +141,11 @@ void MacOSXAPIChecker::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) {
SC.run(C, CE, FI);
}
+
+//===----------------------------------------------------------------------===//
+// Registration.
+//===----------------------------------------------------------------------===//
+
+void ento::registerMacOSXAPIChecker(CheckerManager &mgr) {
+ mgr.registerChecker<MacOSXAPIChecker>();
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
index 9d3a887..794740a 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -599,7 +599,7 @@ void MallocChecker::evalEndPath(EndOfFunctionNodeBuilder &B, void *tag,
for (RegionStateTy::iterator I = M.begin(), E = M.end(); I != E; ++I) {
RefState RS = I->second;
if (RS.isAllocated()) {
- ExplodedNode *N = B.generateNode(state, tag, B.getPredecessor());
+ ExplodedNode *N = B.generateNode(state);
if (N) {
if (!BT_Leak)
BT_Leak = new BuiltinBug("Memory leak",
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp
index 9fb89d7..fed6a99 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp
@@ -16,10 +16,11 @@
//===----------------------------------------------------------------------===//
#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerV2.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Decl.h"
@@ -28,39 +29,18 @@ using namespace ento;
namespace {
class NSAutoreleasePoolChecker
- : public CheckerVisitor<NSAutoreleasePoolChecker> {
+ : public CheckerV2<check::PreObjCMessage> {
- Selector releaseS;
+ mutable Selector releaseS;
public:
- NSAutoreleasePoolChecker(Selector release_s) : releaseS(release_s) {}
-
- static void *getTag() {
- static int x = 0;
- return &x;
- }
-
- void preVisitObjCMessage(CheckerContext &C, ObjCMessage msg);
+ void checkPreObjCMessage(ObjCMessage msg, CheckerContext &C) const;
};
} // end anonymous namespace
-
-static void RegisterNSAutoreleasePoolChecker(ExprEngine &Eng) {
- ASTContext &Ctx = Eng.getContext();
- if (Ctx.getLangOptions().getGCMode() != LangOptions::NonGC) {
- Eng.registerCheck(new NSAutoreleasePoolChecker(GetNullarySelector("release",
- Ctx)));
- }
-}
-
-void ento::registerNSAutoreleasePoolChecker(CheckerManager &mgr) {
- mgr.addCheckerRegisterFunction(RegisterNSAutoreleasePoolChecker);
-}
-
-void
-NSAutoreleasePoolChecker::preVisitObjCMessage(CheckerContext &C,
- ObjCMessage msg) {
+void NSAutoreleasePoolChecker::checkPreObjCMessage(ObjCMessage msg,
+ CheckerContext &C) const {
const Expr *receiver = msg.getInstanceReceiver();
if (!receiver)
@@ -78,7 +58,9 @@ NSAutoreleasePoolChecker::preVisitObjCMessage(CheckerContext &C,
return;
if (!OD->getIdentifier()->getName().equals("NSAutoreleasePool"))
return;
-
+
+ if (releaseS.isNull())
+ releaseS = GetNullarySelector("release", C.getASTContext());
// Sending 'release' message?
if (msg.getSelector() != releaseS)
return;
@@ -90,3 +72,8 @@ NSAutoreleasePoolChecker::preVisitObjCMessage(CheckerContext &C,
"Use -drain instead of -release when using NSAutoreleasePool "
"and garbage collection", R.getBegin(), &R, 1);
}
+
+void ento::registerNSAutoreleasePoolChecker(CheckerManager &mgr) {
+ if (mgr.getLangOptions().getGCMode() != LangOptions::NonGC)
+ mgr.registerChecker<NSAutoreleasePoolChecker>();
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp
index 7d440ab..7746719 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp
@@ -13,39 +13,29 @@
//===----------------------------------------------------------------------===//
#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerV2.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Checkers/DereferenceChecker.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
using namespace clang;
using namespace ento;
namespace {
-class ObjCAtSyncChecker : public CheckerVisitor<ObjCAtSyncChecker> {
- BuiltinBug *BT_null;
- BuiltinBug *BT_undef;
+class ObjCAtSyncChecker
+ : public CheckerV2< check::PreStmt<ObjCAtSynchronizedStmt> > {
+ mutable llvm::OwningPtr<BuiltinBug> BT_null;
+ mutable llvm::OwningPtr<BuiltinBug> BT_undef;
+
public:
- ObjCAtSyncChecker() : BT_null(0), BT_undef(0) {}
- static void *getTag() { static int tag = 0; return &tag; }
- void PreVisitObjCAtSynchronizedStmt(CheckerContext &C,
- const ObjCAtSynchronizedStmt *S);
+ void checkPreStmt(const ObjCAtSynchronizedStmt *S, CheckerContext &C) const;
};
} // end anonymous namespace
-static void RegisterObjCAtSyncChecker(ExprEngine &Eng) {
- // @synchronized is an Objective-C 2 feature.
- if (Eng.getContext().getLangOptions().ObjC2)
- Eng.registerCheck(new ObjCAtSyncChecker());
-}
-
-void ento::registerObjCAtSyncChecker(CheckerManager &mgr) {
- mgr.addCheckerRegisterFunction(RegisterObjCAtSyncChecker);
-}
-
-void ObjCAtSyncChecker::PreVisitObjCAtSynchronizedStmt(CheckerContext &C,
- const ObjCAtSynchronizedStmt *S) {
+void ObjCAtSyncChecker::checkPreStmt(const ObjCAtSynchronizedStmt *S,
+ CheckerContext &C) const {
const Expr *Ex = S->getSynchExpr();
const GRState *state = C.getState();
@@ -55,8 +45,8 @@ void ObjCAtSyncChecker::PreVisitObjCAtSynchronizedStmt(CheckerContext &C,
if (isa<UndefinedVal>(V)) {
if (ExplodedNode *N = C.generateSink()) {
if (!BT_undef)
- BT_undef = new BuiltinBug("Uninitialized value used as mutex "
- "for @synchronized");
+ BT_undef.reset(new BuiltinBug("Uninitialized value used as mutex "
+ "for @synchronized"));
EnhancedBugReport *report =
new EnhancedBugReport(*BT_undef, BT_undef->getDescription(), N);
report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, Ex);
@@ -78,8 +68,8 @@ void ObjCAtSyncChecker::PreVisitObjCAtSynchronizedStmt(CheckerContext &C,
// a null mutex just means no synchronization occurs.
if (ExplodedNode *N = C.generateNode(nullState)) {
if (!BT_null)
- BT_null = new BuiltinBug("Nil value used as mutex for @synchronized() "
- "(no synchronization will occur)");
+ BT_null.reset(new BuiltinBug("Nil value used as mutex for @synchronized() "
+ "(no synchronization will occur)"));
EnhancedBugReport *report =
new EnhancedBugReport(*BT_null, BT_null->getDescription(), N);
report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
@@ -98,3 +88,7 @@ void ObjCAtSyncChecker::PreVisitObjCAtSynchronizedStmt(CheckerContext &C,
C.addTransition(notNullState);
}
+void ento::registerObjCAtSyncChecker(CheckerManager &mgr) {
+ if (mgr.getLangOptions().ObjC2)
+ mgr.registerChecker<ObjCAtSyncChecker>();
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
index 4f247ea..5f32bb8 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
@@ -47,8 +47,9 @@
// http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Articles/ocAllocInit.html
#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerV2.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/Analysis/DomainSpecific/CocoaConventions.h"
@@ -63,45 +64,23 @@ static bool isInitMessage(const ObjCMessage &msg);
static bool isSelfVar(SVal location, CheckerContext &C);
namespace {
-enum SelfFlagEnum {
- /// \brief No flag set.
- SelfFlag_None = 0x0,
- /// \brief Value came from 'self'.
- SelfFlag_Self = 0x1,
- /// \brief Value came from the result of an initializer (e.g. [super init]).
- SelfFlag_InitRes = 0x2
-};
-}
-
-namespace {
-class ObjCSelfInitChecker : public CheckerVisitor<ObjCSelfInitChecker> {
- /// \brief A call receiving a reference to 'self' invalidates the object that
- /// 'self' contains. This field keeps the "self flags" assigned to the 'self'
- /// object before the call and assign them to the new object that 'self'
- /// points to after the call.
- SelfFlagEnum preCallSelfFlags;
-
+class ObjCSelfInitChecker : public CheckerV2<
+ check::PostObjCMessage,
+ check::PostStmt<ObjCIvarRefExpr>,
+ check::PreStmt<ReturnStmt>,
+ check::PreStmt<CallExpr>,
+ check::PostStmt<CallExpr>,
+ check::Location > {
public:
- static void *getTag() { static int tag = 0; return &tag; }
- void postVisitObjCMessage(CheckerContext &C, ObjCMessage msg);
- void PostVisitObjCIvarRefExpr(CheckerContext &C, const ObjCIvarRefExpr *E);
- void PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *S);
- void PreVisitGenericCall(CheckerContext &C, const CallExpr *CE);
- void PostVisitGenericCall(CheckerContext &C, const CallExpr *CE);
- virtual void visitLocation(CheckerContext &C, const Stmt *S, SVal location,
- bool isLoad);
+ void checkPostObjCMessage(ObjCMessage msg, CheckerContext &C) const;
+ void checkPostStmt(const ObjCIvarRefExpr *E, CheckerContext &C) const;
+ void checkPreStmt(const ReturnStmt *S, CheckerContext &C) const;
+ void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
+ void checkPostStmt(const CallExpr *CE, CheckerContext &C) const;
+ void checkLocation(SVal location, bool isLoad, CheckerContext &C) const;
};
} // end anonymous namespace
-static void RegisterObjCSelfInitChecker(ExprEngine &Eng) {
- if (Eng.getContext().getLangOptions().ObjC1)
- Eng.registerCheck(new ObjCSelfInitChecker());
-}
-
-void ento::registerObjCSelfInitChecker(CheckerManager &mgr) {
- mgr.addCheckerRegisterFunction(RegisterObjCSelfInitChecker);
-}
-
namespace {
class InitSelfBug : public BugType {
@@ -113,22 +92,40 @@ public:
} // end anonymous namespace
+namespace {
+enum SelfFlagEnum {
+ /// \brief No flag set.
+ SelfFlag_None = 0x0,
+ /// \brief Value came from 'self'.
+ SelfFlag_Self = 0x1,
+ /// \brief Value came from the result of an initializer (e.g. [super init]).
+ SelfFlag_InitRes = 0x2
+};
+}
+
typedef llvm::ImmutableMap<SymbolRef, unsigned> SelfFlag;
namespace { struct CalledInit {}; }
+namespace { struct PreCallSelfFlags {}; }
namespace clang {
namespace ento {
template<>
struct GRStateTrait<SelfFlag> : public GRStatePartialTrait<SelfFlag> {
- static void* GDMIndex() {
- static int index = 0;
- return &index;
- }
+ static void* GDMIndex() { static int index = 0; return &index; }
};
template <>
struct GRStateTrait<CalledInit> : public GRStatePartialTrait<bool> {
static void *GDMIndex() { static int index = 0; return &index; }
};
+
+ /// \brief A call receiving a reference to 'self' invalidates the object that
+ /// 'self' contains. This keeps the "self flags" assigned to the 'self'
+ /// object before the call so we can assign them to the new object that 'self'
+ /// points to after the call.
+ template <>
+ struct GRStateTrait<PreCallSelfFlags> : public GRStatePartialTrait<unsigned> {
+ static void *GDMIndex() { static int index = 0; return &index; }
+ };
}
}
@@ -188,8 +185,8 @@ static void checkForInvalidSelf(const Expr *E, CheckerContext &C,
C.EmitReport(report);
}
-void ObjCSelfInitChecker::postVisitObjCMessage(CheckerContext &C,
- ObjCMessage msg) {
+void ObjCSelfInitChecker::checkPostObjCMessage(ObjCMessage msg,
+ CheckerContext &C) const {
// When encountering a message that does initialization (init rule),
// tag the return value so that we know later on that if self has this value
// then it is properly initialized.
@@ -219,8 +216,8 @@ void ObjCSelfInitChecker::postVisitObjCMessage(CheckerContext &C,
// fails.
}
-void ObjCSelfInitChecker::PostVisitObjCIvarRefExpr(CheckerContext &C,
- const ObjCIvarRefExpr *E) {
+void ObjCSelfInitChecker::checkPostStmt(const ObjCIvarRefExpr *E,
+ CheckerContext &C) const {
// FIXME: A callback should disable checkers at the start of functions.
if (!shouldRunOnFunctionOrMethod(dyn_cast<NamedDecl>(
C.getCurrentAnalysisContext()->getDecl())))
@@ -231,8 +228,8 @@ void ObjCSelfInitChecker::PostVisitObjCIvarRefExpr(CheckerContext &C,
"'[(super or self) init...]'");
}
-void ObjCSelfInitChecker::PreVisitReturnStmt(CheckerContext &C,
- const ReturnStmt *S) {
+void ObjCSelfInitChecker::checkPreStmt(const ReturnStmt *S,
+ CheckerContext &C) const {
// FIXME: A callback should disable checkers at the start of functions.
if (!shouldRunOnFunctionOrMethod(dyn_cast<NamedDecl>(
C.getCurrentAnalysisContext()->getDecl())))
@@ -259,40 +256,46 @@ void ObjCSelfInitChecker::PreVisitReturnStmt(CheckerContext &C,
// Until we can use inter-procedural analysis, in such a call, transfer the
// SelfFlags to the result of the call.
-void ObjCSelfInitChecker::PreVisitGenericCall(CheckerContext &C,
- const CallExpr *CE) {
+void ObjCSelfInitChecker::checkPreStmt(const CallExpr *CE,
+ CheckerContext &C) const {
const GRState *state = C.getState();
for (CallExpr::const_arg_iterator
I = CE->arg_begin(), E = CE->arg_end(); I != E; ++I) {
SVal argV = state->getSVal(*I);
if (isSelfVar(argV, C)) {
- preCallSelfFlags = getSelfFlags(state->getSVal(cast<Loc>(argV)), C);
+ unsigned selfFlags = getSelfFlags(state->getSVal(cast<Loc>(argV)), C);
+ C.addTransition(state->set<PreCallSelfFlags>(selfFlags));
return;
} else if (hasSelfFlag(argV, SelfFlag_Self, C)) {
- preCallSelfFlags = getSelfFlags(argV, C);
+ unsigned selfFlags = getSelfFlags(argV, C);
+ C.addTransition(state->set<PreCallSelfFlags>(selfFlags));
return;
}
}
}
-void ObjCSelfInitChecker::PostVisitGenericCall(CheckerContext &C,
- const CallExpr *CE) {
+void ObjCSelfInitChecker::checkPostStmt(const CallExpr *CE,
+ CheckerContext &C) const {
const GRState *state = C.getState();
for (CallExpr::const_arg_iterator
I = CE->arg_begin(), E = CE->arg_end(); I != E; ++I) {
SVal argV = state->getSVal(*I);
if (isSelfVar(argV, C)) {
- addSelfFlag(state, state->getSVal(cast<Loc>(argV)), preCallSelfFlags, C);
+ SelfFlagEnum prevFlags = (SelfFlagEnum)state->get<PreCallSelfFlags>();
+ state = state->remove<PreCallSelfFlags>();
+ addSelfFlag(state, state->getSVal(cast<Loc>(argV)), prevFlags, C);
return;
} else if (hasSelfFlag(argV, SelfFlag_Self, C)) {
- addSelfFlag(state, state->getSVal(CE), preCallSelfFlags, C);
+ SelfFlagEnum prevFlags = (SelfFlagEnum)state->get<PreCallSelfFlags>();
+ state = state->remove<PreCallSelfFlags>();
+ addSelfFlag(state, state->getSVal(CE), prevFlags, C);
return;
}
}
}
-void ObjCSelfInitChecker::visitLocation(CheckerContext &C, const Stmt *S,
- SVal location, bool isLoad) {
+void ObjCSelfInitChecker::checkLocation(SVal location, bool isLoad,
+ CheckerContext &C) const {
// Tag the result of a load from 'self' so that we can easily know that the
// value is the object that 'self' points to.
const GRState *state = C.getState();
@@ -354,3 +357,11 @@ static bool isInitializationMethod(const ObjCMethodDecl *MD) {
static bool isInitMessage(const ObjCMessage &msg) {
return cocoa::deriveNamingConvention(msg.getSelector()) == cocoa::InitRule;
}
+
+//===----------------------------------------------------------------------===//
+// Registration.
+//===----------------------------------------------------------------------===//
+
+void ento::registerObjCSelfInitChecker(CheckerManager &mgr) {
+ mgr.registerChecker<ObjCSelfInitChecker>();
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp
index 741e48b..034a2aa 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp
@@ -13,31 +13,26 @@
//===----------------------------------------------------------------------===//
#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerV2.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
using namespace clang;
using namespace ento;
namespace {
class PointerArithChecker
- : public CheckerVisitor<PointerArithChecker> {
- BuiltinBug *BT;
+ : public CheckerV2< check::PreStmt<BinaryOperator> > {
+ mutable llvm::OwningPtr<BuiltinBug> BT;
+
public:
- PointerArithChecker() : BT(0) {}
- static void *getTag();
- void PreVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B);
+ void checkPreStmt(const BinaryOperator *B, CheckerContext &C) const;
};
}
-void *PointerArithChecker::getTag() {
- static int x;
- return &x;
-}
-
-void PointerArithChecker::PreVisitBinaryOperator(CheckerContext &C,
- const BinaryOperator *B) {
+void PointerArithChecker::checkPreStmt(const BinaryOperator *B,
+ CheckerContext &C) const {
if (B->getOpcode() != BO_Sub && B->getOpcode() != BO_Add)
return;
@@ -57,10 +52,10 @@ void PointerArithChecker::PreVisitBinaryOperator(CheckerContext &C,
if (ExplodedNode *N = C.generateNode()) {
if (!BT)
- BT = new BuiltinBug("Dangerous pointer arithmetic",
+ BT.reset(new BuiltinBug("Dangerous pointer arithmetic",
"Pointer arithmetic done on non-array variables "
"means reliance on memory layout, which is "
- "dangerous.");
+ "dangerous."));
RangedBugReport *R = new RangedBugReport(*BT, BT->getDescription(), N);
R->addRange(B->getSourceRange());
C.EmitReport(R);
@@ -68,10 +63,6 @@ void PointerArithChecker::PreVisitBinaryOperator(CheckerContext &C,
}
}
-static void RegisterPointerArithChecker(ExprEngine &Eng) {
- Eng.registerCheck(new PointerArithChecker());
-}
-
void ento::registerPointerArithChecker(CheckerManager &mgr) {
- mgr.addCheckerRegisterFunction(RegisterPointerArithChecker);
+ mgr.registerChecker<PointerArithChecker>();
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp
index f28fe9a..bf85b95 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp
@@ -14,31 +14,26 @@
//===----------------------------------------------------------------------===//
#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerV2.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
using namespace clang;
using namespace ento;
namespace {
class PointerSubChecker
- : public CheckerVisitor<PointerSubChecker> {
- BuiltinBug *BT;
+ : public CheckerV2< check::PreStmt<BinaryOperator> > {
+ mutable llvm::OwningPtr<BuiltinBug> BT;
+
public:
- PointerSubChecker() : BT(0) {}
- static void *getTag();
- void PreVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B);
+ void checkPreStmt(const BinaryOperator *B, CheckerContext &C) const;
};
}
-void *PointerSubChecker::getTag() {
- static int x;
- return &x;
-}
-
-void PointerSubChecker::PreVisitBinaryOperator(CheckerContext &C,
- const BinaryOperator *B) {
+void PointerSubChecker::checkPreStmt(const BinaryOperator *B,
+ CheckerContext &C) const {
// When doing pointer subtraction, if the two pointers do not point to the
// same memory chunk, emit a warning.
if (B->getOpcode() != BO_Sub)
@@ -66,19 +61,15 @@ void PointerSubChecker::PreVisitBinaryOperator(CheckerContext &C,
if (ExplodedNode *N = C.generateNode()) {
if (!BT)
- BT = new BuiltinBug("Pointer subtraction",
+ BT.reset(new BuiltinBug("Pointer subtraction",
"Subtraction of two pointers that do not point to "
- "the same memory chunk may cause incorrect result.");
+ "the same memory chunk may cause incorrect result."));
RangedBugReport *R = new RangedBugReport(*BT, BT->getDescription(), N);
R->addRange(B->getSourceRange());
C.EmitReport(R);
}
}
-static void RegisterPointerSubChecker(ExprEngine &Eng) {
- Eng.registerCheck(new PointerSubChecker());
-}
-
void ento::registerPointerSubChecker(CheckerManager &mgr) {
- mgr.addCheckerRegisterFunction(RegisterPointerSubChecker);
+ mgr.registerChecker<PointerSubChecker>();
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
index 34c095f..6c6901f 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
@@ -13,8 +13,9 @@
//===----------------------------------------------------------------------===//
#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerV2.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h"
#include "llvm/ADT/ImmutableSet.h"
@@ -24,21 +25,15 @@ using namespace ento;
namespace {
class PthreadLockChecker
- : public CheckerVisitor<PthreadLockChecker> {
- BugType *BT;
+ : public CheckerV2< check::PostStmt<CallExpr> > {
public:
- PthreadLockChecker() : BT(0) {}
- static void *getTag() {
- static int x = 0;
- return &x;
- }
- void PostVisitCallExpr(CheckerContext &C, const CallExpr *CE);
+ void checkPostStmt(const CallExpr *CE, CheckerContext &C) const;
void AcquireLock(CheckerContext &C, const CallExpr *CE,
- SVal lock, bool isTryLock);
+ SVal lock, bool isTryLock) const;
void ReleaseLock(CheckerContext &C, const CallExpr *CE,
- SVal lock);
+ SVal lock) const;
};
} // end anonymous namespace
@@ -49,22 +44,14 @@ namespace clang {
namespace ento {
template <> struct GRStateTrait<LockSet> :
public GRStatePartialTrait<llvm::ImmutableSet<const MemRegion*> > {
- static void* GDMIndex() { return PthreadLockChecker::getTag(); }
+ static void* GDMIndex() { static int x = 0; return &x; }
};
} // end GR namespace
} // end clang namespace
-static void RegisterPthreadLockChecker(ExprEngine &Eng) {
- Eng.registerCheck(new PthreadLockChecker());
-}
-
-void ento::registerPthreadLockChecker(CheckerManager &mgr) {
- mgr.addCheckerRegisterFunction(RegisterPthreadLockChecker);
-}
-
-void PthreadLockChecker::PostVisitCallExpr(CheckerContext &C,
- const CallExpr *CE) {
+void PthreadLockChecker::checkPostStmt(const CallExpr *CE,
+ CheckerContext &C) const {
const GRState *state = C.getState();
const Expr *Callee = CE->getCallee();
const FunctionTextRegion *R =
@@ -96,7 +83,7 @@ void PthreadLockChecker::PostVisitCallExpr(CheckerContext &C,
}
void PthreadLockChecker::AcquireLock(CheckerContext &C, const CallExpr *CE,
- SVal lock, bool isTryLock) {
+ SVal lock, bool isTryLock) const {
const MemRegion *lockR = lock.getAsRegion();
if (!lockR)
@@ -132,7 +119,7 @@ void PthreadLockChecker::AcquireLock(CheckerContext &C, const CallExpr *CE,
}
void PthreadLockChecker::ReleaseLock(CheckerContext &C, const CallExpr *CE,
- SVal lock) {
+ SVal lock) const {
const MemRegion *lockR = lock.getAsRegion();
if (!lockR)
@@ -150,3 +137,7 @@ void PthreadLockChecker::ReleaseLock(CheckerContext &C, const CallExpr *CE,
C.addTransition(C.generateNode(CE, unlockState));
}
+
+void ento::registerPthreadLockChecker(CheckerManager &mgr) {
+ mgr.registerChecker<PthreadLockChecker>();
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp
index 838a00f..2985156 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp
@@ -12,9 +12,11 @@
//
//===----------------------------------------------------------------------===//
-#include "InternalChecks.h"
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerV2.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
using namespace clang;
@@ -22,25 +24,15 @@ using namespace ento;
namespace {
class ReturnPointerRangeChecker :
- public CheckerVisitor<ReturnPointerRangeChecker> {
- BuiltinBug *BT;
+ public CheckerV2< check::PreStmt<ReturnStmt> > {
+ mutable llvm::OwningPtr<BuiltinBug> BT;
public:
- ReturnPointerRangeChecker() : BT(0) {}
- static void *getTag();
- void PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *RS);
+ void checkPreStmt(const ReturnStmt *RS, CheckerContext &C) const;
};
}
-void ento::RegisterReturnPointerRangeChecker(ExprEngine &Eng) {
- Eng.registerCheck(new ReturnPointerRangeChecker());
-}
-
-void *ReturnPointerRangeChecker::getTag() {
- static int x = 0; return &x;
-}
-
-void ReturnPointerRangeChecker::PreVisitReturnStmt(CheckerContext &C,
- const ReturnStmt *RS) {
+void ReturnPointerRangeChecker::checkPreStmt(const ReturnStmt *RS,
+ CheckerContext &C) const {
const GRState *state = C.getState();
const Expr *RetE = RS->getRetValue();
@@ -77,9 +69,9 @@ void ReturnPointerRangeChecker::PreVisitReturnStmt(CheckerContext &C,
// FIXME: This bug correspond to CWE-466. Eventually we should have bug
// types explicitly reference such exploit categories (when applicable).
if (!BT)
- BT = new BuiltinBug("Return of pointer value outside of expected range",
+ BT.reset(new BuiltinBug("Return of pointer value outside of expected range",
"Returned pointer value points outside the original object "
- "(potential buffer overflow)");
+ "(potential buffer overflow)"));
// FIXME: It would be nice to eventually make this diagnostic more clear,
// e.g., by referencing the original declaration or by saying *why* this
@@ -93,3 +85,7 @@ void ReturnPointerRangeChecker::PreVisitReturnStmt(CheckerContext &C,
C.EmitReport(report);
}
}
+
+void ento::registerReturnPointerRangeChecker(CheckerManager &mgr) {
+ mgr.registerChecker<ReturnPointerRangeChecker>();
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StackAddrLeakChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
index 363f404..6a9a37d 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StackAddrLeakChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
@@ -1,4 +1,4 @@
-//=== StackAddrLeakChecker.cpp ------------------------------------*- C++ -*--//
+//=== StackAddrEscapeChecker.cpp ----------------------------------*- C++ -*--//
//
// The LLVM Compiler Infrastructure
//
@@ -13,9 +13,10 @@
//===----------------------------------------------------------------------===//
#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerV2.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/ADT/SmallString.h"
@@ -23,34 +24,23 @@ using namespace clang;
using namespace ento;
namespace {
-class StackAddrLeakChecker : public CheckerVisitor<StackAddrLeakChecker> {
- BuiltinBug *BT_stackleak;
- BuiltinBug *BT_returnstack;
+class StackAddrEscapeChecker : public CheckerV2< check::PreStmt<ReturnStmt>,
+ check::EndPath > {
+ mutable llvm::OwningPtr<BuiltinBug> BT_stackleak;
+ mutable llvm::OwningPtr<BuiltinBug> BT_returnstack;
public:
- StackAddrLeakChecker() : BT_stackleak(0), BT_returnstack(0) {}
- static void *getTag() {
- static int x;
- return &x;
- }
- void PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *RS);
- void evalEndPath(EndOfFunctionNodeBuilder &B, void *tag, ExprEngine &Eng);
+ void checkPreStmt(const ReturnStmt *RS, CheckerContext &C) const;
+ void checkEndPath(EndOfFunctionNodeBuilder &B, ExprEngine &Eng) const;
private:
- void EmitStackError(CheckerContext &C, const MemRegion *R, const Expr *RetE);
- SourceRange GenName(llvm::raw_ostream &os, const MemRegion *R,
- SourceManager &SM);
+ void EmitStackError(CheckerContext &C, const MemRegion *R,
+ const Expr *RetE) const;
+ static SourceRange GenName(llvm::raw_ostream &os, const MemRegion *R,
+ SourceManager &SM);
};
}
-static void RegisterStackAddrLeakChecker(ExprEngine &Eng) {
- Eng.registerCheck(new StackAddrLeakChecker());
-}
-
-void ento::registerStackAddrLeakChecker(CheckerManager &mgr) {
- mgr.addCheckerRegisterFunction(RegisterStackAddrLeakChecker);
-}
-
-SourceRange StackAddrLeakChecker::GenName(llvm::raw_ostream &os,
+SourceRange StackAddrEscapeChecker::GenName(llvm::raw_ostream &os,
const MemRegion *R,
SourceManager &SM) {
// Get the base region, stripping away fields and elements.
@@ -93,15 +83,16 @@ SourceRange StackAddrLeakChecker::GenName(llvm::raw_ostream &os,
return range;
}
-void StackAddrLeakChecker::EmitStackError(CheckerContext &C, const MemRegion *R,
- const Expr *RetE) {
+void StackAddrEscapeChecker::EmitStackError(CheckerContext &C, const MemRegion *R,
+ const Expr *RetE) const {
ExplodedNode *N = C.generateSink();
if (!N)
return;
if (!BT_returnstack)
- BT_returnstack=new BuiltinBug("Return of address to stack-allocated memory");
+ BT_returnstack.reset(
+ new BuiltinBug("Return of address to stack-allocated memory"));
// Generate a report for this bug.
llvm::SmallString<512> buf;
@@ -116,8 +107,8 @@ void StackAddrLeakChecker::EmitStackError(CheckerContext &C, const MemRegion *R,
C.EmitReport(report);
}
-void StackAddrLeakChecker::PreVisitReturnStmt(CheckerContext &C,
- const ReturnStmt *RS) {
+void StackAddrEscapeChecker::checkPreStmt(const ReturnStmt *RS,
+ CheckerContext &C) const {
const Expr *RetE = RS->getRetValue();
if (!RetE)
@@ -135,8 +126,8 @@ void StackAddrLeakChecker::PreVisitReturnStmt(CheckerContext &C,
}
}
-void StackAddrLeakChecker::evalEndPath(EndOfFunctionNodeBuilder &B, void *tag,
- ExprEngine &Eng) {
+void StackAddrEscapeChecker::checkEndPath(EndOfFunctionNodeBuilder &B,
+ ExprEngine &Eng) const {
const GRState *state = B.getState();
@@ -180,16 +171,16 @@ void StackAddrLeakChecker::evalEndPath(EndOfFunctionNodeBuilder &B, void *tag,
return;
// Generate an error node.
- ExplodedNode *N = B.generateNode(state, tag, B.getPredecessor());
+ ExplodedNode *N = B.generateNode(state);
if (!N)
return;
if (!BT_stackleak)
- BT_stackleak =
+ BT_stackleak.reset(
new BuiltinBug("Stack address stored into global variable",
"Stack address was saved into a global variable. "
"This is dangerous because the address will become "
- "invalid after returning from the function");
+ "invalid after returning from the function"));
for (unsigned i = 0, e = cb.V.size(); i != e; ++i) {
// Generate a report for this bug.
@@ -208,3 +199,7 @@ void StackAddrLeakChecker::evalEndPath(EndOfFunctionNodeBuilder &B, void *tag,
Eng.getBugReporter().EmitReport(report);
}
}
+
+void ento::registerStackAddrEscapeChecker(CheckerManager &mgr) {
+ mgr.registerChecker<StackAddrEscapeChecker>();
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
index 2655be2..d0626b8 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
@@ -12,9 +12,10 @@
//===----------------------------------------------------------------------===//
#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerV2.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
@@ -55,52 +56,50 @@ struct StreamState {
}
};
-class StreamChecker : public CheckerVisitor<StreamChecker> {
- IdentifierInfo *II_fopen, *II_tmpfile, *II_fclose, *II_fread, *II_fwrite,
+class StreamChecker : public CheckerV2<eval::Call,
+ check::DeadSymbols,
+ check::EndPath,
+ check::PreStmt<ReturnStmt> > {
+ mutable IdentifierInfo *II_fopen, *II_tmpfile, *II_fclose, *II_fread,
+ *II_fwrite,
*II_fseek, *II_ftell, *II_rewind, *II_fgetpos, *II_fsetpos,
*II_clearerr, *II_feof, *II_ferror, *II_fileno;
- BuiltinBug *BT_nullfp, *BT_illegalwhence, *BT_doubleclose, *BT_ResourceLeak;
+ mutable llvm::OwningPtr<BuiltinBug> BT_nullfp, BT_illegalwhence,
+ BT_doubleclose, BT_ResourceLeak;
public:
StreamChecker()
: II_fopen(0), II_tmpfile(0) ,II_fclose(0), II_fread(0), II_fwrite(0),
II_fseek(0), II_ftell(0), II_rewind(0), II_fgetpos(0), II_fsetpos(0),
- II_clearerr(0), II_feof(0), II_ferror(0), II_fileno(0),
- BT_nullfp(0), BT_illegalwhence(0), BT_doubleclose(0),
- BT_ResourceLeak(0) {}
+ II_clearerr(0), II_feof(0), II_ferror(0), II_fileno(0) {}
- static void *getTag() {
- static int x;
- return &x;
- }
-
- virtual bool evalCallExpr(CheckerContext &C, const CallExpr *CE);
- void evalDeadSymbols(CheckerContext &C, SymbolReaper &SymReaper);
- void evalEndPath(EndOfFunctionNodeBuilder &B, void *tag, ExprEngine &Eng);
- void PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *S);
+ bool evalCall(const CallExpr *CE, CheckerContext &C) const;
+ void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
+ void checkEndPath(EndOfFunctionNodeBuilder &B, ExprEngine &Eng) const;
+ void checkPreStmt(const ReturnStmt *S, CheckerContext &C) const;
private:
- void Fopen(CheckerContext &C, const CallExpr *CE);
- void Tmpfile(CheckerContext &C, const CallExpr *CE);
- void Fclose(CheckerContext &C, const CallExpr *CE);
- void Fread(CheckerContext &C, const CallExpr *CE);
- void Fwrite(CheckerContext &C, const CallExpr *CE);
- void Fseek(CheckerContext &C, const CallExpr *CE);
- void Ftell(CheckerContext &C, const CallExpr *CE);
- void Rewind(CheckerContext &C, const CallExpr *CE);
- void Fgetpos(CheckerContext &C, const CallExpr *CE);
- void Fsetpos(CheckerContext &C, const CallExpr *CE);
- void Clearerr(CheckerContext &C, const CallExpr *CE);
- void Feof(CheckerContext &C, const CallExpr *CE);
- void Ferror(CheckerContext &C, const CallExpr *CE);
- void Fileno(CheckerContext &C, const CallExpr *CE);
-
- void OpenFileAux(CheckerContext &C, const CallExpr *CE);
+ void Fopen(CheckerContext &C, const CallExpr *CE) const;
+ void Tmpfile(CheckerContext &C, const CallExpr *CE) const;
+ void Fclose(CheckerContext &C, const CallExpr *CE) const;
+ void Fread(CheckerContext &C, const CallExpr *CE) const;
+ void Fwrite(CheckerContext &C, const CallExpr *CE) const;
+ void Fseek(CheckerContext &C, const CallExpr *CE) const;
+ void Ftell(CheckerContext &C, const CallExpr *CE) const;
+ void Rewind(CheckerContext &C, const CallExpr *CE) const;
+ void Fgetpos(CheckerContext &C, const CallExpr *CE) const;
+ void Fsetpos(CheckerContext &C, const CallExpr *CE) const;
+ void Clearerr(CheckerContext &C, const CallExpr *CE) const;
+ void Feof(CheckerContext &C, const CallExpr *CE) const;
+ void Ferror(CheckerContext &C, const CallExpr *CE) const;
+ void Fileno(CheckerContext &C, const CallExpr *CE) const;
+
+ void OpenFileAux(CheckerContext &C, const CallExpr *CE) const;
const GRState *CheckNullStream(SVal SV, const GRState *state,
- CheckerContext &C);
+ CheckerContext &C) const;
const GRState *CheckDoubleClose(const CallExpr *CE, const GRState *state,
- CheckerContext &C);
+ CheckerContext &C) const;
};
} // end anonymous namespace
@@ -110,20 +109,12 @@ namespace ento {
template <>
struct GRStateTrait<StreamState>
: public GRStatePartialTrait<llvm::ImmutableMap<SymbolRef, StreamState> > {
- static void *GDMIndex() { return StreamChecker::getTag(); }
+ static void *GDMIndex() { static int x; return &x; }
};
}
}
-static void RegisterStreamChecker(ExprEngine &Eng) {
- Eng.registerCheck(new StreamChecker());
-}
-
-void ento::registerStreamChecker(CheckerManager &mgr) {
- mgr.addCheckerRegisterFunction(RegisterStreamChecker);
-}
-
-bool StreamChecker::evalCallExpr(CheckerContext &C, const CallExpr *CE) {
+bool StreamChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
const GRState *state = C.getState();
const Expr *Callee = CE->getCallee();
SVal L = state->getSVal(Callee);
@@ -221,15 +212,15 @@ bool StreamChecker::evalCallExpr(CheckerContext &C, const CallExpr *CE) {
return false;
}
-void StreamChecker::Fopen(CheckerContext &C, const CallExpr *CE) {
+void StreamChecker::Fopen(CheckerContext &C, const CallExpr *CE) const {
OpenFileAux(C, CE);
}
-void StreamChecker::Tmpfile(CheckerContext &C, const CallExpr *CE) {
+void StreamChecker::Tmpfile(CheckerContext &C, const CallExpr *CE) const {
OpenFileAux(C, CE);
}
-void StreamChecker::OpenFileAux(CheckerContext &C, const CallExpr *CE) {
+void StreamChecker::OpenFileAux(CheckerContext &C, const CallExpr *CE) const {
const GRState *state = C.getState();
unsigned Count = C.getNodeBuilder().getCurrentBlockCount();
SValBuilder &svalBuilder = C.getSValBuilder();
@@ -255,25 +246,25 @@ void StreamChecker::OpenFileAux(CheckerContext &C, const CallExpr *CE) {
}
}
-void StreamChecker::Fclose(CheckerContext &C, const CallExpr *CE) {
+void StreamChecker::Fclose(CheckerContext &C, const CallExpr *CE) const {
const GRState *state = CheckDoubleClose(CE, C.getState(), C);
if (state)
C.addTransition(state);
}
-void StreamChecker::Fread(CheckerContext &C, const CallExpr *CE) {
+void StreamChecker::Fread(CheckerContext &C, const CallExpr *CE) const {
const GRState *state = C.getState();
if (!CheckNullStream(state->getSVal(CE->getArg(3)), state, C))
return;
}
-void StreamChecker::Fwrite(CheckerContext &C, const CallExpr *CE) {
+void StreamChecker::Fwrite(CheckerContext &C, const CallExpr *CE) const {
const GRState *state = C.getState();
if (!CheckNullStream(state->getSVal(CE->getArg(3)), state, C))
return;
}
-void StreamChecker::Fseek(CheckerContext &C, const CallExpr *CE) {
+void StreamChecker::Fseek(CheckerContext &C, const CallExpr *CE) const {
const GRState *state = C.getState();
if (!(state = CheckNullStream(state->getSVal(CE->getArg(0)), state, C)))
return;
@@ -290,65 +281,65 @@ void StreamChecker::Fseek(CheckerContext &C, const CallExpr *CE) {
if (ExplodedNode *N = C.generateNode(state)) {
if (!BT_illegalwhence)
- BT_illegalwhence = new BuiltinBug("Illegal whence argument",
+ BT_illegalwhence.reset(new BuiltinBug("Illegal whence argument",
"The whence argument to fseek() should be "
- "SEEK_SET, SEEK_END, or SEEK_CUR.");
+ "SEEK_SET, SEEK_END, or SEEK_CUR."));
BugReport *R = new BugReport(*BT_illegalwhence,
BT_illegalwhence->getDescription(), N);
C.EmitReport(R);
}
}
-void StreamChecker::Ftell(CheckerContext &C, const CallExpr *CE) {
+void StreamChecker::Ftell(CheckerContext &C, const CallExpr *CE) const {
const GRState *state = C.getState();
if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
return;
}
-void StreamChecker::Rewind(CheckerContext &C, const CallExpr *CE) {
+void StreamChecker::Rewind(CheckerContext &C, const CallExpr *CE) const {
const GRState *state = C.getState();
if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
return;
}
-void StreamChecker::Fgetpos(CheckerContext &C, const CallExpr *CE) {
+void StreamChecker::Fgetpos(CheckerContext &C, const CallExpr *CE) const {
const GRState *state = C.getState();
if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
return;
}
-void StreamChecker::Fsetpos(CheckerContext &C, const CallExpr *CE) {
+void StreamChecker::Fsetpos(CheckerContext &C, const CallExpr *CE) const {
const GRState *state = C.getState();
if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
return;
}
-void StreamChecker::Clearerr(CheckerContext &C, const CallExpr *CE) {
+void StreamChecker::Clearerr(CheckerContext &C, const CallExpr *CE) const {
const GRState *state = C.getState();
if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
return;
}
-void StreamChecker::Feof(CheckerContext &C, const CallExpr *CE) {
+void StreamChecker::Feof(CheckerContext &C, const CallExpr *CE) const {
const GRState *state = C.getState();
if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
return;
}
-void StreamChecker::Ferror(CheckerContext &C, const CallExpr *CE) {
+void StreamChecker::Ferror(CheckerContext &C, const CallExpr *CE) const {
const GRState *state = C.getState();
if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
return;
}
-void StreamChecker::Fileno(CheckerContext &C, const CallExpr *CE) {
+void StreamChecker::Fileno(CheckerContext &C, const CallExpr *CE) const {
const GRState *state = C.getState();
if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
return;
}
const GRState *StreamChecker::CheckNullStream(SVal SV, const GRState *state,
- CheckerContext &C) {
+ CheckerContext &C) const {
const DefinedSVal *DV = dyn_cast<DefinedSVal>(&SV);
if (!DV)
return 0;
@@ -360,8 +351,8 @@ const GRState *StreamChecker::CheckNullStream(SVal SV, const GRState *state,
if (!stateNotNull && stateNull) {
if (ExplodedNode *N = C.generateSink(stateNull)) {
if (!BT_nullfp)
- BT_nullfp = new BuiltinBug("NULL stream pointer",
- "Stream pointer might be NULL.");
+ BT_nullfp.reset(new BuiltinBug("NULL stream pointer",
+ "Stream pointer might be NULL."));
BugReport *R =new BugReport(*BT_nullfp, BT_nullfp->getDescription(), N);
C.EmitReport(R);
}
@@ -372,7 +363,7 @@ const GRState *StreamChecker::CheckNullStream(SVal SV, const GRState *state,
const GRState *StreamChecker::CheckDoubleClose(const CallExpr *CE,
const GRState *state,
- CheckerContext &C) {
+ CheckerContext &C) const {
SymbolRef Sym = state->getSVal(CE->getArg(0)).getAsSymbol();
if (!Sym)
return state;
@@ -389,9 +380,9 @@ const GRState *StreamChecker::CheckDoubleClose(const CallExpr *CE,
ExplodedNode *N = C.generateSink();
if (N) {
if (!BT_doubleclose)
- BT_doubleclose = new BuiltinBug("Double fclose",
+ BT_doubleclose.reset(new BuiltinBug("Double fclose",
"Try to close a file Descriptor already"
- " closed. Cause undefined behaviour.");
+ " closed. Cause undefined behaviour."));
BugReport *R = new BugReport(*BT_doubleclose,
BT_doubleclose->getDescription(), N);
C.EmitReport(R);
@@ -403,7 +394,8 @@ const GRState *StreamChecker::CheckDoubleClose(const CallExpr *CE,
return state->set<StreamState>(Sym, StreamState::getClosed(CE));
}
-void StreamChecker::evalDeadSymbols(CheckerContext &C,SymbolReaper &SymReaper) {
+void StreamChecker::checkDeadSymbols(SymbolReaper &SymReaper,
+ CheckerContext &C) const {
for (SymbolReaper::dead_iterator I = SymReaper.dead_begin(),
E = SymReaper.dead_end(); I != E; ++I) {
SymbolRef Sym = *I;
@@ -416,8 +408,8 @@ void StreamChecker::evalDeadSymbols(CheckerContext &C,SymbolReaper &SymReaper) {
ExplodedNode *N = C.generateSink();
if (N) {
if (!BT_ResourceLeak)
- BT_ResourceLeak = new BuiltinBug("Resource Leak",
- "Opened File never closed. Potential Resource leak.");
+ BT_ResourceLeak.reset(new BuiltinBug("Resource Leak",
+ "Opened File never closed. Potential Resource leak."));
BugReport *R = new BugReport(*BT_ResourceLeak,
BT_ResourceLeak->getDescription(), N);
C.EmitReport(R);
@@ -426,8 +418,8 @@ void StreamChecker::evalDeadSymbols(CheckerContext &C,SymbolReaper &SymReaper) {
}
}
-void StreamChecker::evalEndPath(EndOfFunctionNodeBuilder &B, void *tag,
- ExprEngine &Eng) {
+void StreamChecker::checkEndPath(EndOfFunctionNodeBuilder &B,
+ ExprEngine &Eng) const {
const GRState *state = B.getState();
typedef llvm::ImmutableMap<SymbolRef, StreamState> SymMap;
SymMap M = state->get<StreamState>();
@@ -435,11 +427,11 @@ void StreamChecker::evalEndPath(EndOfFunctionNodeBuilder &B, void *tag,
for (SymMap::iterator I = M.begin(), E = M.end(); I != E; ++I) {
StreamState SS = I->second;
if (SS.isOpened()) {
- ExplodedNode *N = B.generateNode(state, tag, B.getPredecessor());
+ ExplodedNode *N = B.generateNode(state);
if (N) {
if (!BT_ResourceLeak)
- BT_ResourceLeak = new BuiltinBug("Resource Leak",
- "Opened File never closed. Potential Resource leak.");
+ BT_ResourceLeak.reset(new BuiltinBug("Resource Leak",
+ "Opened File never closed. Potential Resource leak."));
BugReport *R = new BugReport(*BT_ResourceLeak,
BT_ResourceLeak->getDescription(), N);
Eng.getBugReporter().EmitReport(R);
@@ -448,7 +440,7 @@ void StreamChecker::evalEndPath(EndOfFunctionNodeBuilder &B, void *tag,
}
}
-void StreamChecker::PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *S) {
+void StreamChecker::checkPreStmt(const ReturnStmt *S, CheckerContext &C) const {
const Expr *RetE = S->getRetValue();
if (!RetE)
return;
@@ -468,3 +460,7 @@ void StreamChecker::PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *S) {
C.addTransition(state);
}
+
+void ento::registerStreamChecker(CheckerManager &mgr) {
+ mgr.registerChecker<StreamChecker>();
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
index a53ebb5..be4fbf6 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
@@ -13,10 +13,11 @@
//===----------------------------------------------------------------------===//
#include "ClangSACheckers.h"
-#include "clang/Basic/TargetInfo.h"
+#include "clang/StaticAnalyzer/Core/CheckerV2.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
+#include "clang/Basic/TargetInfo.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringSwitch.h"
#include <fcntl.h>
@@ -26,7 +27,7 @@ using namespace ento;
using llvm::Optional;
namespace {
-class UnixAPIChecker : public CheckerVisitor<UnixAPIChecker> {
+class UnixAPIChecker : public CheckerV2< check::PreStmt<CallExpr> > {
enum SubChecks {
OpenFn = 0,
PthreadOnceFn = 1,
@@ -34,27 +35,22 @@ class UnixAPIChecker : public CheckerVisitor<UnixAPIChecker> {
NumChecks
};
- BugType *BTypes[NumChecks];
+ mutable BugType *BTypes[NumChecks];
public:
- Optional<uint64_t> Val_O_CREAT;
+ mutable Optional<uint64_t> Val_O_CREAT;
public:
UnixAPIChecker() { memset(BTypes, 0, sizeof(*BTypes) * NumChecks); }
- static void *getTag() { static unsigned tag = 0; return &tag; }
+ ~UnixAPIChecker() {
+ for (unsigned i=0; i != NumChecks; ++i)
+ delete BTypes[i];
+ }
- void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
+ void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
};
} //end anonymous namespace
-static void RegisterUnixAPIChecker(ExprEngine &Eng) {
- Eng.registerCheck(new UnixAPIChecker());
-}
-
-void ento::registerUnixAPIChecker(CheckerManager &mgr) {
- mgr.addCheckerRegisterFunction(RegisterUnixAPIChecker);
-}
-
//===----------------------------------------------------------------------===//
// Utility functions.
//===----------------------------------------------------------------------===//
@@ -69,7 +65,7 @@ static inline void LazyInitialize(BugType *&BT, const char *name) {
// "open" (man 2 open)
//===----------------------------------------------------------------------===//
-static void CheckOpen(CheckerContext &C, UnixAPIChecker &UC,
+static void CheckOpen(CheckerContext &C, const UnixAPIChecker &UC,
const CallExpr *CE, BugType *&BT) {
// The definition of O_CREAT is platform specific. We need a better way
// of querying this information from the checking environment.
@@ -141,7 +137,7 @@ static void CheckOpen(CheckerContext &C, UnixAPIChecker &UC,
// pthread_once
//===----------------------------------------------------------------------===//
-static void CheckPthreadOnce(CheckerContext &C, UnixAPIChecker &,
+static void CheckPthreadOnce(CheckerContext &C, const UnixAPIChecker &,
const CallExpr *CE, BugType *&BT) {
// This is similar to 'CheckDispatchOnce' in the MacOSXAPIChecker.
@@ -186,7 +182,7 @@ static void CheckPthreadOnce(CheckerContext &C, UnixAPIChecker &,
// FIXME: Eventually this should be rolled into the MallocChecker, but this
// check is more basic and is valuable for widespread use.
-static void CheckMallocZero(CheckerContext &C, UnixAPIChecker &UC,
+static void CheckMallocZero(CheckerContext &C, const UnixAPIChecker &UC,
const CallExpr *CE, BugType *&BT) {
// Sanity check that malloc takes one argument.
@@ -234,16 +230,16 @@ static void CheckMallocZero(CheckerContext &C, UnixAPIChecker &UC,
// Central dispatch function.
//===----------------------------------------------------------------------===//
-typedef void (*SubChecker)(CheckerContext &C, UnixAPIChecker &UC,
+typedef void (*SubChecker)(CheckerContext &C, const UnixAPIChecker &UC,
const CallExpr *CE, BugType *&BT);
namespace {
class SubCheck {
SubChecker SC;
- UnixAPIChecker *UC;
+ const UnixAPIChecker *UC;
BugType **BT;
public:
- SubCheck(SubChecker sc, UnixAPIChecker *uc, BugType *& bt) : SC(sc), UC(uc),
- BT(&bt) {}
+ SubCheck(SubChecker sc, const UnixAPIChecker *uc, BugType *& bt)
+ : SC(sc), UC(uc), BT(&bt) {}
SubCheck() : SC(NULL), UC(NULL), BT(NULL) {}
void run(CheckerContext &C, const CallExpr *CE) const {
@@ -253,7 +249,7 @@ namespace {
};
} // end anonymous namespace
-void UnixAPIChecker::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) {
+void UnixAPIChecker::checkPreStmt(const CallExpr *CE, CheckerContext &C) const {
// Get the callee. All the functions we care about are C functions
// with simple identifiers.
const GRState *state = C.getState();
@@ -280,3 +276,11 @@ void UnixAPIChecker::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) {
SC.run(C, CE);
}
+
+//===----------------------------------------------------------------------===//
+// Registration.
+//===----------------------------------------------------------------------===//
+
+void ento::registerUnixAPIChecker(CheckerManager &mgr) {
+ mgr.registerChecker<UnixAPIChecker>();
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp
index 3038e29..1bc487a 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp
@@ -14,15 +14,16 @@
//===----------------------------------------------------------------------===//
#include "ClangSACheckers.h"
-#include "clang/AST/ParentMap.h"
-#include "clang/Basic/Builtins.h"
-#include "clang/Basic/SourceManager.h"
+#include "clang/StaticAnalyzer/Core/CheckerV2.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
+#include "clang/AST/ParentMap.h"
+#include "clang/Basic/Builtins.h"
+#include "clang/Basic/SourceManager.h"
#include "llvm/ADT/SmallPtrSet.h"
// The number of CFGBlock pointers we want to reserve memory for. This is used
@@ -33,40 +34,27 @@ using namespace clang;
using namespace ento;
namespace {
-class UnreachableCodeChecker : public Checker {
+class UnreachableCodeChecker : public CheckerV2<check::EndAnalysis> {
public:
- static void *getTag();
- void VisitEndAnalysis(ExplodedGraph &G,
- BugReporter &B,
- ExprEngine &Eng);
+ void checkEndAnalysis(ExplodedGraph &G, BugReporter &B,
+ ExprEngine &Eng) const;
private:
+ typedef llvm::SmallSet<unsigned, DEFAULT_CFGBLOCKS> CFGBlocksSet;
+
static inline const Stmt *getUnreachableStmt(const CFGBlock *CB);
- void FindUnreachableEntryPoints(const CFGBlock *CB);
+ static void FindUnreachableEntryPoints(const CFGBlock *CB,
+ CFGBlocksSet &reachable,
+ CFGBlocksSet &visited);
static bool isInvalidPath(const CFGBlock *CB, const ParentMap &PM);
static inline bool isEmptyCFGBlock(const CFGBlock *CB);
-
- llvm::SmallSet<unsigned, DEFAULT_CFGBLOCKS> reachable;
- llvm::SmallSet<unsigned, DEFAULT_CFGBLOCKS> visited;
};
}
-void *UnreachableCodeChecker::getTag() {
- static int x = 0;
- return &x;
-}
-
-static void RegisterUnreachableCodeChecker(ExprEngine &Eng) {
- Eng.registerCheck(new UnreachableCodeChecker());
-}
-
-void ento::registerUnreachableCodeChecker(CheckerManager &mgr) {
- mgr.addCheckerRegisterFunction(RegisterUnreachableCodeChecker);
-}
-
-void UnreachableCodeChecker::VisitEndAnalysis(ExplodedGraph &G,
+void UnreachableCodeChecker::checkEndAnalysis(ExplodedGraph &G,
BugReporter &B,
- ExprEngine &Eng) {
- // Bail out if we didn't cover all paths
+ ExprEngine &Eng) const {
+ CFGBlocksSet reachable, visited;
+
if (Eng.hasWorkRemaining())
return;
@@ -109,7 +97,7 @@ void UnreachableCodeChecker::VisitEndAnalysis(ExplodedGraph &G,
// Find the entry points for this block
if (!visited.count(CB->getBlockID()))
- FindUnreachableEntryPoints(CB);
+ FindUnreachableEntryPoints(CB, reachable, visited);
// This block may have been pruned; check if we still want to report it
if (reachable.count(CB->getBlockID()))
@@ -155,7 +143,9 @@ void UnreachableCodeChecker::VisitEndAnalysis(ExplodedGraph &G,
}
// Recursively finds the entry point(s) for this dead CFGBlock.
-void UnreachableCodeChecker::FindUnreachableEntryPoints(const CFGBlock *CB) {
+void UnreachableCodeChecker::FindUnreachableEntryPoints(const CFGBlock *CB,
+ CFGBlocksSet &reachable,
+ CFGBlocksSet &visited) {
visited.insert(CB->getBlockID());
for (CFGBlock::const_pred_iterator I = CB->pred_begin(), E = CB->pred_end();
@@ -166,7 +156,7 @@ void UnreachableCodeChecker::FindUnreachableEntryPoints(const CFGBlock *CB) {
reachable.insert(CB->getBlockID());
if (!visited.count((*I)->getBlockID()))
// If we haven't previously visited the unreachable predecessor, recurse
- FindUnreachableEntryPoints(*I);
+ FindUnreachableEntryPoints(*I, reachable, visited);
}
}
}
@@ -226,3 +216,7 @@ bool UnreachableCodeChecker::isEmptyCFGBlock(const CFGBlock *CB) {
&& CB->size() == 0 // No statements
&& CB->getTerminator() == 0; // No terminator
}
+
+void ento::registerUnreachableCodeChecker(CheckerManager &mgr) {
+ mgr.registerChecker<UnreachableCodeChecker>();
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporter.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
index 9a84045..672982a 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -1202,16 +1202,8 @@ static void GenerateExtensivePathDiagnostic(PathDiagnostic& PD,
//===----------------------------------------------------------------------===//
// Methods for BugType and subclasses.
//===----------------------------------------------------------------------===//
-BugType::~BugType() {
- // Free up the equivalence class objects. Observe that we get a pointer to
- // the object first before incrementing the iterator, as destroying the
- // node before doing so means we will read from freed memory.
- for (iterator I = begin(), E = end(); I !=E; ) {
- BugReportEquivClass *EQ = &*I;
- ++I;
- delete EQ;
- }
-}
+BugType::~BugType() { }
+
void BugType::FlushReports(BugReporter &BR) {}
//===----------------------------------------------------------------------===//
@@ -1315,28 +1307,30 @@ void BugReporter::FlushReports() {
return;
// First flush the warnings for each BugType. This may end up creating new
- // warnings and new BugTypes. Because ImmutableSet is a functional data
- // structure, we do not need to worry about the iterators being invalidated.
+ // warnings and new BugTypes.
+ // FIXME: Only NSErrorChecker needs BugType's FlushReports.
+ // Turn NSErrorChecker into a proper checker and remove this.
+ llvm::SmallVector<const BugType*, 16> bugTypes;
for (BugTypesTy::iterator I=BugTypes.begin(), E=BugTypes.end(); I!=E; ++I)
+ bugTypes.push_back(*I);
+ for (llvm::SmallVector<const BugType*, 16>::iterator
+ I = bugTypes.begin(), E = bugTypes.end(); I != E; ++I)
const_cast<BugType*>(*I)->FlushReports(*this);
- // Iterate through BugTypes a second time. BugTypes may have been updated
- // with new BugType objects and new warnings.
- for (BugTypesTy::iterator I=BugTypes.begin(), E=BugTypes.end(); I!=E; ++I) {
- BugType *BT = const_cast<BugType*>(*I);
-
- typedef llvm::FoldingSet<BugReportEquivClass> SetTy;
- SetTy& EQClasses = BT->EQClasses;
-
- for (SetTy::iterator EI=EQClasses.begin(), EE=EQClasses.end(); EI!=EE;++EI){
- BugReportEquivClass& EQ = *EI;
- FlushReport(EQ);
- }
-
- // Delete the BugType object.
- delete BT;
+ typedef llvm::FoldingSet<BugReportEquivClass> SetTy;
+ for (SetTy::iterator EI=EQClasses.begin(), EE=EQClasses.end(); EI!=EE;++EI){
+ BugReportEquivClass& EQ = *EI;
+ FlushReport(EQ);
}
+ // BugReporter owns and deletes only BugTypes created implicitly through
+ // EmitBasicReport.
+ // FIXME: There are leaks from checkers that assume that the BugTypes they
+ // create will be destroyed by the BugReporter.
+ for (llvm::StringMap<BugType*>::iterator
+ I = StrBugTypes.begin(), E = StrBugTypes.end(); I != E; ++I)
+ delete I->second;
+
// Remove all references to the BugType objects.
BugTypes = F.getEmptySet();
}
@@ -1632,11 +1626,11 @@ void BugReporter::EmitReport(BugReport* R) {
BugType& BT = R->getBugType();
Register(&BT);
void *InsertPos;
- BugReportEquivClass* EQ = BT.EQClasses.FindNodeOrInsertPos(ID, InsertPos);
+ BugReportEquivClass* EQ = EQClasses.FindNodeOrInsertPos(ID, InsertPos);
if (!EQ) {
EQ = new BugReportEquivClass(R);
- BT.EQClasses.InsertNode(EQ, InsertPos);
+ EQClasses.InsertNode(EQ, InsertPos);
}
else
EQ->AddReport(R);
@@ -1887,10 +1881,24 @@ void BugReporter::EmitBasicReport(llvm::StringRef name,
llvm::StringRef str, SourceLocation Loc,
SourceRange* RBeg, unsigned NumRanges) {
- // 'BT' will be owned by BugReporter as soon as we call 'EmitReport'.
- BugType *BT = new BugType(name, category);
+ // 'BT' is owned by BugReporter.
+ BugType *BT = getBugTypeForName(name, category);
FullSourceLoc L = getContext().getFullLoc(Loc);
RangedBugReport *R = new DiagBugReport(*BT, str, L);
for ( ; NumRanges > 0 ; --NumRanges, ++RBeg) R->addRange(*RBeg);
EmitReport(R);
}
+
+BugType *BugReporter::getBugTypeForName(llvm::StringRef name,
+ llvm::StringRef category) {
+ llvm::SmallString<136> fullDesc;
+ llvm::raw_svector_ostream(fullDesc) << name << ":" << category;
+ llvm::StringMapEntry<BugType *> &
+ entry = StrBugTypes.GetOrCreateValue(fullDesc);
+ BugType *BT = entry.getValue();
+ if (!BT) {
+ BT = new BugType(name, category);
+ entry.setValue(BT);
+ }
+ return BT;
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
index 1989b82..75d331a 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
@@ -13,11 +13,17 @@
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/CheckerProvider.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/Analysis/ProgramPoint.h"
#include "clang/AST/DeclBase.h"
using namespace clang;
using namespace ento;
+//===----------------------------------------------------------------------===//
+// Functions for running checkers for AST traversing..
+//===----------------------------------------------------------------------===//
+
void CheckerManager::runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr,
BugReporter &BR) {
assert(D);
@@ -33,53 +39,398 @@ void CheckerManager::runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr,
for (unsigned i = 0, e = DeclCheckers.size(); i != e; ++i) {
DeclCheckerInfo &info = DeclCheckers[i];
if (info.IsForDeclFn(D))
- checkers->push_back(std::make_pair(info.Checker, info.CheckFn));
+ checkers->push_back(info.CheckFn);
}
}
assert(checkers);
for (CachedDeclCheckers::iterator
- I = checkers->begin(), E = checkers->end(); I != E; ++I) {
- CheckerRef checker = I->first;
- CheckDeclFunc fn = I->second;
- fn(checker, D, mgr, BR);
- }
+ I = checkers->begin(), E = checkers->end(); I != E; ++I)
+ (*I)(D, mgr, BR);
}
void CheckerManager::runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr,
BugReporter &BR) {
assert(D && D->hasBody());
- for (unsigned i = 0, e = BodyCheckers.size(); i != e; ++i) {
- CheckerRef checker = BodyCheckers[i].first;
- CheckDeclFunc fn = BodyCheckers[i].second;
- fn(checker, D, mgr, BR);
+ for (unsigned i = 0, e = BodyCheckers.size(); i != e; ++i)
+ BodyCheckers[i](D, mgr, BR);
+}
+
+//===----------------------------------------------------------------------===//
+// Functions for running checkers for path-sensitive checking.
+//===----------------------------------------------------------------------===//
+
+template <typename CHECK_CTX>
+static void expandGraphWithCheckers(CHECK_CTX checkCtx,
+ ExplodedNodeSet &Dst,
+ const ExplodedNodeSet &Src) {
+
+ typename CHECK_CTX::CheckersTy::const_iterator
+ I = checkCtx.checkers_begin(), E = checkCtx.checkers_end();
+ if (I == E) {
+ Dst.insert(Src);
+ return;
+ }
+
+ ExplodedNodeSet Tmp1, Tmp2;
+ const ExplodedNodeSet *PrevSet = &Src;
+
+ for (; I != E; ++I) {
+ ExplodedNodeSet *CurrSet = 0;
+ if (I+1 == E)
+ CurrSet = &Dst;
+ else {
+ CurrSet = (PrevSet == &Tmp1) ? &Tmp2 : &Tmp1;
+ CurrSet->clear();
+ }
+
+ for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end();
+ NI != NE; ++NI)
+ checkCtx.runChecker(*I, *CurrSet, *NI);
+
+ // Update which NodeSet is the current one.
+ PrevSet = CurrSet;
+ }
+}
+
+namespace {
+ struct CheckStmtContext {
+ typedef llvm::SmallVectorImpl<CheckerManager::CheckStmtFunc> CheckersTy;
+ bool IsPreVisit;
+ const CheckersTy &Checkers;
+ const Stmt *S;
+ ExprEngine &Eng;
+
+ CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
+ CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
+
+ CheckStmtContext(bool isPreVisit, const CheckersTy &checkers,
+ const Stmt *s, ExprEngine &eng)
+ : IsPreVisit(isPreVisit), Checkers(checkers), S(s), Eng(eng) { }
+
+ void runChecker(CheckerManager::CheckStmtFunc checkFn,
+ ExplodedNodeSet &Dst, ExplodedNode *Pred) {
+ // FIXME: Remove respondsToCallback from CheckerContext;
+ CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker,
+ IsPreVisit ? ProgramPoint::PreStmtKind :
+ ProgramPoint::PostStmtKind, 0, S);
+ checkFn(S, C);
+ }
+ };
+}
+
+/// \brief Run checkers for visiting Stmts.
+void CheckerManager::runCheckersForStmt(bool isPreVisit,
+ ExplodedNodeSet &Dst,
+ const ExplodedNodeSet &Src,
+ const Stmt *S,
+ ExprEngine &Eng) {
+ CheckStmtContext C(isPreVisit, *getCachedStmtCheckersFor(S, isPreVisit),
+ S, Eng);
+ expandGraphWithCheckers(C, Dst, Src);
+}
+
+namespace {
+ struct CheckObjCMessageContext {
+ typedef std::vector<CheckerManager::CheckObjCMessageFunc> CheckersTy;
+ bool IsPreVisit;
+ const CheckersTy &Checkers;
+ const ObjCMessage &Msg;
+ ExprEngine &Eng;
+
+ CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
+ CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
+
+ CheckObjCMessageContext(bool isPreVisit, const CheckersTy &checkers,
+ const ObjCMessage &msg, ExprEngine &eng)
+ : IsPreVisit(isPreVisit), Checkers(checkers), Msg(msg), Eng(eng) { }
+
+ void runChecker(CheckerManager::CheckObjCMessageFunc checkFn,
+ ExplodedNodeSet &Dst, ExplodedNode *Pred) {
+ CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker,
+ IsPreVisit ? ProgramPoint::PreStmtKind :
+ ProgramPoint::PostStmtKind, 0,
+ Msg.getOriginExpr());
+ checkFn(Msg, C);
+ }
+ };
+}
+
+/// \brief Run checkers for visiting obj-c messages.
+void CheckerManager::runCheckersForObjCMessage(bool isPreVisit,
+ ExplodedNodeSet &Dst,
+ const ExplodedNodeSet &Src,
+ const ObjCMessage &msg,
+ ExprEngine &Eng) {
+ CheckObjCMessageContext C(isPreVisit,
+ isPreVisit ? PreObjCMessageCheckers
+ : PostObjCMessageCheckers,
+ msg, Eng);
+ expandGraphWithCheckers(C, Dst, Src);
+}
+
+namespace {
+ struct CheckLocationContext {
+ typedef std::vector<CheckerManager::CheckLocationFunc> CheckersTy;
+ const CheckersTy &Checkers;
+ SVal Loc;
+ bool IsLoad;
+ const Stmt *S;
+ ExprEngine &Eng;
+
+ CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
+ CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
+
+ CheckLocationContext(const CheckersTy &checkers,
+ SVal loc, bool isLoad, const Stmt *s, ExprEngine &eng)
+ : Checkers(checkers), Loc(loc), IsLoad(isLoad), S(s), Eng(eng) { }
+
+ void runChecker(CheckerManager::CheckLocationFunc checkFn,
+ ExplodedNodeSet &Dst, ExplodedNode *Pred) {
+ CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker,
+ IsLoad ? ProgramPoint::PreLoadKind :
+ ProgramPoint::PreStoreKind, 0, S);
+ checkFn(Loc, IsLoad, C);
+ }
+ };
+}
+
+/// \brief Run checkers for load/store of a location.
+void CheckerManager::runCheckersForLocation(ExplodedNodeSet &Dst,
+ const ExplodedNodeSet &Src,
+ SVal location, bool isLoad,
+ const Stmt *S, ExprEngine &Eng) {
+ CheckLocationContext C(LocationCheckers, location, isLoad, S, Eng);
+ expandGraphWithCheckers(C, Dst, Src);
+}
+
+void CheckerManager::runCheckersForEndAnalysis(ExplodedGraph &G,
+ BugReporter &BR,
+ ExprEngine &Eng) {
+ for (unsigned i = 0, e = EndAnalysisCheckers.size(); i != e; ++i)
+ EndAnalysisCheckers[i](G, BR, Eng);
+}
+
+/// \brief Run checkers for end of path.
+void CheckerManager::runCheckersForEndPath(EndOfFunctionNodeBuilder &B,
+ ExprEngine &Eng) {
+ for (unsigned i = 0, e = EndPathCheckers.size(); i != e; ++i) {
+ CheckEndPathFunc fn = EndPathCheckers[i];
+ EndOfFunctionNodeBuilder specialB = B.withCheckerTag(fn.Checker);
+ fn(specialB, Eng);
+ }
+}
+
+/// \brief Run checkers for live symbols.
+void CheckerManager::runCheckersForLiveSymbols(const GRState *state,
+ SymbolReaper &SymReaper) {
+ for (unsigned i = 0, e = LiveSymbolsCheckers.size(); i != e; ++i)
+ LiveSymbolsCheckers[i](state, SymReaper);
+}
+
+namespace {
+ struct CheckDeadSymbolsContext {
+ typedef std::vector<CheckerManager::CheckDeadSymbolsFunc> CheckersTy;
+ const CheckersTy &Checkers;
+ SymbolReaper &SR;
+ const Stmt *S;
+ ExprEngine &Eng;
+
+ CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
+ CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
+
+ CheckDeadSymbolsContext(const CheckersTy &checkers, SymbolReaper &sr,
+ const Stmt *s, ExprEngine &eng)
+ : Checkers(checkers), SR(sr), S(s), Eng(eng) { }
+
+ void runChecker(CheckerManager::CheckDeadSymbolsFunc checkFn,
+ ExplodedNodeSet &Dst, ExplodedNode *Pred) {
+ CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker,
+ ProgramPoint::PostPurgeDeadSymbolsKind, 0, S);
+ checkFn(SR, C);
+ }
+ };
+}
+
+/// \brief Run checkers for dead symbols.
+void CheckerManager::runCheckersForDeadSymbols(ExplodedNodeSet &Dst,
+ const ExplodedNodeSet &Src,
+ SymbolReaper &SymReaper,
+ const Stmt *S,
+ ExprEngine &Eng) {
+ CheckDeadSymbolsContext C(DeadSymbolsCheckers, SymReaper, S, Eng);
+ expandGraphWithCheckers(C, Dst, Src);
+}
+
+/// \brief True if at least one checker wants to check region changes.
+bool CheckerManager::wantsRegionChangeUpdate(const GRState *state) {
+ for (unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i)
+ if (RegionChangesCheckers[i].WantUpdateFn(state))
+ return true;
+
+ return false;
+}
+
+/// \brief Run checkers for region changes.
+const GRState *
+CheckerManager::runCheckersForRegionChanges(const GRState *state,
+ const MemRegion * const *Begin,
+ const MemRegion * const *End) {
+ for (unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i) {
+ // If any checker declares the state infeasible (or if it starts that way),
+ // bail out.
+ if (!state)
+ return NULL;
+ state = RegionChangesCheckers[i].CheckFn(state, Begin, End);
}
+ return state;
}
-void CheckerManager::_registerForDecl(CheckerRef checker, CheckDeclFunc checkfn,
+/// \brief Run checkers for evaluating a call.
+/// Only one checker will evaluate the call.
+void CheckerManager::runCheckersForEvalCall(ExplodedNodeSet &Dst,
+ const ExplodedNodeSet &Src,
+ const CallExpr *CE,
+ ExprEngine &Eng,
+ GraphExpander *defaultEval) {
+ if (EvalCallCheckers.empty() && defaultEval == 0) {
+ Dst.insert(Src);
+ return;
+ }
+
+ for (ExplodedNodeSet::iterator
+ NI = Src.begin(), NE = Src.end(); NI != NE; ++NI) {
+
+ ExplodedNode *Pred = *NI;
+ bool anyEvaluated = false;
+ for (std::vector<EvalCallFunc>::iterator
+ EI = EvalCallCheckers.begin(), EE = EvalCallCheckers.end();
+ EI != EE; ++EI) {
+ ExplodedNodeSet checkDst;
+ CheckerContext C(checkDst, Eng.getBuilder(), Eng, Pred, EI->Checker,
+ ProgramPoint::PostStmtKind, 0, CE);
+ bool evaluated = (*EI)(CE, C);
+ assert(!(evaluated && anyEvaluated)
+ && "There are more than one checkers evaluating the call");
+ if (evaluated) {
+ anyEvaluated = true;
+ Dst.insert(checkDst);
+#ifdef NDEBUG
+ break; // on release don't check that no other checker also evals.
+#endif
+ }
+ }
+
+ if (!anyEvaluated) {
+ if (defaultEval)
+ defaultEval->expandGraph(Dst, Pred);
+ else
+ Dst.insert(Pred);
+ }
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Internal registration functions for AST traversing.
+//===----------------------------------------------------------------------===//
+
+void CheckerManager::_registerForDecl(CheckDeclFunc checkfn,
HandlesDeclFunc isForDeclFn) {
- DeclCheckerInfo info = { checker, checkfn, isForDeclFn };
+ DeclCheckerInfo info = { checkfn, isForDeclFn };
DeclCheckers.push_back(info);
}
-void CheckerManager::_registerForBody(CheckerRef checker,
- CheckDeclFunc checkfn) {
- BodyCheckers.push_back(std::make_pair(checker, checkfn));
+void CheckerManager::_registerForBody(CheckDeclFunc checkfn) {
+ BodyCheckers.push_back(checkfn);
}
-void CheckerManager::registerCheckersToEngine(ExprEngine &eng) {
- for (unsigned i = 0, e = Funcs.size(); i != e; ++i)
- Funcs[i](eng);
+//===----------------------------------------------------------------------===//
+// Internal registration functions for path-sensitive checking.
+//===----------------------------------------------------------------------===//
+
+void CheckerManager::_registerForPreStmt(CheckStmtFunc checkfn,
+ HandlesStmtFunc isForStmtFn) {
+ StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/true };
+ StmtCheckers.push_back(info);
+}
+void CheckerManager::_registerForPostStmt(CheckStmtFunc checkfn,
+ HandlesStmtFunc isForStmtFn) {
+ StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/false };
+ StmtCheckers.push_back(info);
}
-CheckerManager::~CheckerManager() {
- for (unsigned i = 0, e = Checkers.size(); i != e; ++i) {
- CheckerRef checker = Checkers[i].first;
- Dtor dtor = Checkers[i].second;
- dtor(checker);
+void CheckerManager::_registerForPreObjCMessage(CheckObjCMessageFunc checkfn) {
+ PreObjCMessageCheckers.push_back(checkfn);
+}
+void CheckerManager::_registerForPostObjCMessage(CheckObjCMessageFunc checkfn) {
+ PostObjCMessageCheckers.push_back(checkfn);
+}
+
+void CheckerManager::_registerForLocation(CheckLocationFunc checkfn) {
+ LocationCheckers.push_back(checkfn);
+}
+
+void CheckerManager::_registerForEndAnalysis(CheckEndAnalysisFunc checkfn) {
+ EndAnalysisCheckers.push_back(checkfn);
+}
+
+void CheckerManager::_registerForEndPath(CheckEndPathFunc checkfn) {
+ EndPathCheckers.push_back(checkfn);
+}
+
+void CheckerManager::_registerForLiveSymbols(CheckLiveSymbolsFunc checkfn) {
+ LiveSymbolsCheckers.push_back(checkfn);
+}
+
+void CheckerManager::_registerForDeadSymbols(CheckDeadSymbolsFunc checkfn) {
+ DeadSymbolsCheckers.push_back(checkfn);
+}
+
+void CheckerManager::_registerForRegionChanges(CheckRegionChangesFunc checkfn,
+ WantsRegionChangeUpdateFunc wantUpdateFn) {
+ RegionChangesCheckerInfo info = {checkfn, wantUpdateFn};
+ RegionChangesCheckers.push_back(info);
+}
+
+void CheckerManager::_registerForEvalCall(EvalCallFunc checkfn) {
+ EvalCallCheckers.push_back(checkfn);
+}
+
+//===----------------------------------------------------------------------===//
+// Implementation details.
+//===----------------------------------------------------------------------===//
+
+CheckerManager::CachedStmtCheckers *
+CheckerManager::getCachedStmtCheckersFor(const Stmt *S, bool isPreVisit) {
+ assert(S);
+
+ CachedStmtCheckersKey key(S->getStmtClass(), isPreVisit);
+ CachedStmtCheckers *checkers = 0;
+ CachedStmtCheckersMapTy::iterator CCI = CachedStmtCheckersMap.find(key);
+ if (CCI != CachedStmtCheckersMap.end()) {
+ checkers = &(CCI->second);
+ } else {
+ // Find the checkers that should run for this Stmt and cache them.
+ checkers = &CachedStmtCheckersMap[key];
+ for (unsigned i = 0, e = StmtCheckers.size(); i != e; ++i) {
+ StmtCheckerInfo &info = StmtCheckers[i];
+ if (info.IsPreVisit == isPreVisit && info.IsForStmtFn(S))
+ checkers->push_back(info.CheckFn);
+ }
}
+
+ assert(checkers);
+ return checkers;
+}
+
+CheckerManager::~CheckerManager() {
+ for (unsigned i = 0, e = CheckerDtors.size(); i != e; ++i)
+ CheckerDtors[i]();
}
// Anchor for the vtable.
CheckerProvider::~CheckerProvider() { }
+
+// Anchor for the vtable.
+GraphExpander::~GraphExpander() { }
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp
index 070042a..08a2068 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp
@@ -718,13 +718,14 @@ EndOfFunctionNodeBuilder::~EndOfFunctionNodeBuilder() {
}
ExplodedNode*
-EndOfFunctionNodeBuilder::generateNode(const GRState* State, const void *tag,
- ExplodedNode* P) {
+EndOfFunctionNodeBuilder::generateNode(const GRState* State,
+ ExplodedNode* P, const void *tag) {
hasGeneratedNode = true;
bool IsNew;
ExplodedNode* Node = Eng.G->getNode(BlockEntrance(&B,
- Pred->getLocationContext(), tag), State, &IsNew);
+ Pred->getLocationContext(), tag ? tag : Tag),
+ State, &IsNew);
Node->addPredecessor(P ? P : Pred, *Eng.G);
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Environment.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Environment.cpp
index ecaff29..1bffa30 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Environment.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Environment.cpp
@@ -32,6 +32,11 @@ SVal Environment::getSVal(const Stmt *E, SValBuilder& svalBuilder) const {
switch (E->getStmtClass()) {
case Stmt::AddrLabelExprClass:
return svalBuilder.makeLoc(cast<AddrLabelExpr>(E));
+ case Stmt::OpaqueValueExprClass: {
+ const OpaqueValueExpr *ope = cast<OpaqueValueExpr>(E);
+ E = ope->getSourceExpr();
+ continue;
+ }
case Stmt::ParenExprClass:
// ParenExprs are no-ops.
E = cast<ParenExpr>(E)->getSubExpr();
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
index dbfebcc..e3e7ee9 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
@@ -175,7 +175,8 @@ public:
virtual void Initialize(ASTContext &Context) {
Ctx = &Context;
- checkerMgr.reset(registerCheckers(Opts, PP.getDiagnostics()));
+ checkerMgr.reset(registerCheckers(Opts, PP.getLangOptions(),
+ PP.getDiagnostics()));
Mgr.reset(new AnalysisManager(*Ctx, PP.getDiagnostics(),
PP.getLangOptions(), PD,
CreateStoreMgr, CreateConstraintMgr,
@@ -339,9 +340,6 @@ static void ActionExprEngine(AnalysisConsumer &C, AnalysisManager& mgr,
return;
ExprEngine Eng(mgr, TF.take());
- if (C.Opts.EnableExperimentalInternalChecks)
- RegisterExperimentalInternalChecks(Eng);
-
RegisterNSErrorChecks(Eng.getBugReporter(), Eng, *D);
if (C.Opts.EnableExperimentalChecks)
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp
index 6625729..677e20c 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp
@@ -12,12 +12,14 @@
//===----------------------------------------------------------------------===//
#include "clang/StaticAnalyzer/Frontend/CheckerRegistration.h"
+#include "clang/StaticAnalyzer/Frontend/FrontendActions.h"
#include "../Checkers/ClangSACheckerProvider.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/CheckerProvider.h"
#include "clang/Frontend/AnalyzerOptions.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Basic/Diagnostic.h"
+#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/SmallVector.h"
@@ -25,8 +27,9 @@ using namespace clang;
using namespace ento;
CheckerManager *ento::registerCheckers(const AnalyzerOptions &opts,
+ const LangOptions &langOpts,
Diagnostic &diags) {
- llvm::OwningPtr<CheckerManager> checkerMgr(new CheckerManager());
+ llvm::OwningPtr<CheckerManager> checkerMgr(new CheckerManager(langOpts));
llvm::SmallVector<CheckerOptInfo, 8> checkerOpts;
for (unsigned i = 0, e = opts.CheckersControlList.size(); i != e; ++i) {
@@ -48,3 +51,16 @@ CheckerManager *ento::registerCheckers(const AnalyzerOptions &opts,
return checkerMgr.take();
}
+
+void ento::printCheckerHelp(llvm::raw_ostream &OS) {
+ OS << "OVERVIEW: Clang Static Analyzer Checkers List\n";
+ OS << '\n';
+ OS << "USAGE: -analyzer-checker <check1,check2,...>\n";
+ OS << '\n';
+ OS << "CHECKERS:\n";
+
+ llvm::OwningPtr<CheckerProvider> provider(createClangSACheckerProvider());
+ provider->printHelp(OS);
+
+ // FIXME: Load CheckerProviders from plugins.
+}
diff --git a/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp b/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp
index 448ebad..cd31e0c 100644
--- a/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp
@@ -542,7 +542,255 @@ void AsmWriterEmitter::EmitGetInstructionName(raw_ostream &O) {
<< "}\n\n#endif\n";
}
+void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
+ CodeGenTarget Target(Records);
+ Record *AsmWriter = Target.getAsmWriter();
+
+ O << "\n#ifdef PRINT_ALIAS_INSTR\n";
+ O << "#undef PRINT_ALIAS_INSTR\n\n";
+
+ // Enumerate the register classes.
+ const std::vector<CodeGenRegisterClass> &RegisterClasses =
+ Target.getRegisterClasses();
+
+ O << "namespace { // Register classes\n";
+ O << " enum RegClass {\n";
+
+ // Emit the register enum value for each RegisterClass.
+ for (unsigned I = 0, E = RegisterClasses.size(); I != E; ++I) {
+ if (I != 0) O << ",\n";
+ O << " RC_" << RegisterClasses[I].TheDef->getName();
+ }
+
+ O << "\n };\n";
+ O << "} // end anonymous namespace\n\n";
+
+ // Emit a function that returns 'true' if a regsiter is part of a particular
+ // register class. I.e., RAX is part of GR64 on X86.
+ O << "static bool regIsInRegisterClass"
+ << "(unsigned RegClass, unsigned Reg) {\n";
+
+ // Emit the switch that checks if a register belongs to a particular register
+ // class.
+ O << " switch (RegClass) {\n";
+ O << " default: break;\n";
+
+ for (unsigned I = 0, E = RegisterClasses.size(); I != E; ++I) {
+ const CodeGenRegisterClass &RC = RegisterClasses[I];
+
+ // Give the register class a legal C name if it's anonymous.
+ std::string Name = RC.TheDef->getName();
+ O << " case RC_" << Name << ":\n";
+
+ // Emit the register list now.
+ unsigned IE = RC.Elements.size();
+ if (IE == 1) {
+ O << " if (Reg == " << getQualifiedName(RC.Elements[0]) << ")\n";
+ O << " return true;\n";
+ } else {
+ O << " switch (Reg) {\n";
+ O << " default: break;\n";
+
+ for (unsigned II = 0; II != IE; ++II) {
+ Record *Reg = RC.Elements[II];
+ O << " case " << getQualifiedName(Reg) << ":\n";
+ }
+
+ O << " return true;\n";
+ O << " }\n";
+ }
+
+ O << " break;\n";
+ }
+
+ O << " }\n\n";
+ O << " return false;\n";
+ O << "}\n\n";
+
+ // Emit the method that prints the alias instruction.
+ std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName");
+ bool isMC = AsmWriter->getValueAsBit("isMCAsmWriter");
+ const char *MachineInstrClassName = isMC ? "MCInst" : "MachineInstr";
+
+ O << "bool " << Target.getName() << ClassName
+ << "::printAliasInstr(const " << MachineInstrClassName
+ << " *MI, raw_ostream &OS) {\n";
+
+ std::vector<Record*> AllInstAliases =
+ Records.getAllDerivedDefinitions("InstAlias");
+
+ // Create a map from the qualified name to a list of potential matches.
+ std::map<std::string, std::vector<CodeGenInstAlias*> > AliasMap;
+ for (std::vector<Record*>::iterator
+ I = AllInstAliases.begin(), E = AllInstAliases.end(); I != E; ++I) {
+ CodeGenInstAlias *Alias = new CodeGenInstAlias(*I, Target);
+ const Record *R = *I;
+ const DagInit *DI = R->getValueAsDag("ResultInst");
+ const DefInit *Op = dynamic_cast<const DefInit*>(DI->getOperator());
+ AliasMap[getQualifiedName(Op->getDef())].push_back(Alias);
+ }
+
+ if (AliasMap.empty() || !isMC) {
+ // FIXME: Support MachineInstr InstAliases?
+ O << " return true;\n";
+ O << "}\n\n";
+ O << "#endif // PRINT_ALIAS_INSTR\n";
+ return;
+ }
+
+ O << " StringRef AsmString;\n";
+ O << " std::map<StringRef, unsigned> OpMap;\n";
+ O << " switch (MI->getOpcode()) {\n";
+ O << " default: return true;\n";
+
+ for (std::map<std::string, std::vector<CodeGenInstAlias*> >::iterator
+ I = AliasMap.begin(), E = AliasMap.end(); I != E; ++I) {
+ std::vector<CodeGenInstAlias*> &Aliases = I->second;
+
+ std::map<std::string, unsigned> CondCount;
+ std::map<std::string, std::string> BodyMap;
+
+ std::string AsmString = "";
+
+ for (std::vector<CodeGenInstAlias*>::iterator
+ II = Aliases.begin(), IE = Aliases.end(); II != IE; ++II) {
+ const CodeGenInstAlias *CGA = *II;
+ AsmString = CGA->AsmString;
+ unsigned Indent = 8;
+ unsigned LastOpNo = CGA->ResultInstOperandIndex.size();
+
+ std::string Cond;
+ raw_string_ostream CondO(Cond);
+
+ CondO << "if (MI->getNumOperands() == " << LastOpNo;
+
+ std::map<StringRef, unsigned> OpMap;
+ bool CantHandle = false;
+
+ for (unsigned i = 0, e = LastOpNo; i != e; ++i) {
+ const CodeGenInstAlias::ResultOperand &RO = CGA->ResultOperands[i];
+
+ switch (RO.Kind) {
+ default: assert(0 && "unexpected InstAlias operand kind");
+ case CodeGenInstAlias::ResultOperand::K_Record: {
+ const Record *Rec = RO.getRecord();
+ StringRef ROName = RO.getName();
+
+ if (Rec->isSubClassOf("RegisterClass")) {
+ CondO << " &&\n";
+ CondO.indent(Indent) << "MI->getOperand(" << i << ").isReg() &&\n";
+ if (OpMap.find(ROName) == OpMap.end()) {
+ OpMap[ROName] = i;
+ CondO.indent(Indent)
+ << "regIsInRegisterClass(RC_"
+ << CGA->ResultOperands[i].getRecord()->getName()
+ << ", MI->getOperand(" << i << ").getReg())";
+ } else {
+ CondO.indent(Indent)
+ << "MI->getOperand(" << i
+ << ").getReg() == MI->getOperand("
+ << OpMap[ROName] << ").getReg()";
+ }
+ } else {
+ assert(Rec->isSubClassOf("Operand") && "Unexpected operand!");
+ // FIXME: We need to handle these situations.
+ CantHandle = true;
+ break;
+ }
+
+ break;
+ }
+ case CodeGenInstAlias::ResultOperand::K_Imm:
+ CondO << " &&\n";
+ CondO.indent(Indent) << "MI->getOperand(" << i << ").getImm() == ";
+ CondO << CGA->ResultOperands[i].getImm();
+ break;
+ case CodeGenInstAlias::ResultOperand::K_Reg:
+ CondO << " &&\n";
+ CondO.indent(Indent) << "MI->getOperand(" << i << ").getReg() == ";
+ CondO << Target.getName() << "::"
+ << CGA->ResultOperands[i].getRegister()->getName();
+ break;
+ }
+
+ if (CantHandle) break;
+ }
+
+ if (CantHandle) continue;
+
+ CondO << ")";
+
+ std::string Body;
+ raw_string_ostream BodyO(Body);
+
+ BodyO << " // " << CGA->Result->getAsString() << "\n";
+ BodyO << " AsmString = \"" << AsmString << "\";\n";
+
+ for (std::map<StringRef, unsigned>::iterator
+ III = OpMap.begin(), IIE = OpMap.end(); III != IIE; ++III)
+ BodyO << " OpMap[\"" << III->first << "\"] = "
+ << III->second << ";\n";
+
+ ++CondCount[CondO.str()];
+ BodyMap[CondO.str()] = BodyO.str();
+ }
+
+ std::string Code;
+ raw_string_ostream CodeO(Code);
+
+ bool EmitElse = false;
+ for (std::map<std::string, unsigned>::iterator
+ II = CondCount.begin(), IE = CondCount.end(); II != IE; ++II) {
+ if (II->second != 1) continue;
+ CodeO << " ";
+ if (EmitElse) CodeO << "} else ";
+ CodeO << II->first << " {\n";
+ CodeO << BodyMap[II->first];
+ EmitElse = true;
+ }
+
+ if (CodeO.str().empty()) continue;
+
+ O << " case " << I->first << ":\n";
+ O << CodeO.str();
+ O << " }\n";
+ O << " break;\n";
+ }
+
+ O << " }\n\n";
+
+ // Code that prints the alias, replacing the operands with the ones from the
+ // MCInst.
+ O << " if (AsmString.empty()) return true;\n";
+ O << " std::pair<StringRef, StringRef> ASM = AsmString.split(' ');\n";
+ O << " OS << '\\t' << ASM.first;\n";
+
+ O << " if (!ASM.second.empty()) {\n";
+ O << " OS << '\\t';\n";
+ O << " for (StringRef::iterator\n";
+ O << " I = ASM.second.begin(), E = ASM.second.end(); I != E; ) {\n";
+ O << " if (*I == '$') {\n";
+ O << " StringRef::iterator Start = ++I;\n";
+ O << " while (I != E &&\n";
+ O << " ((*I >= 'a' && *I <= 'z') ||\n";
+ O << " (*I >= 'A' && *I <= 'Z') ||\n";
+ O << " (*I >= '0' && *I <= '9') ||\n";
+ O << " *I == '_'))\n";
+ O << " ++I;\n";
+ O << " StringRef Name(Start, I - Start);\n";
+ O << " printOperand(MI, OpMap[Name], OS);\n";
+ O << " } else {\n";
+ O << " OS << *I++;\n";
+ O << " }\n";
+ O << " }\n";
+ O << " }\n\n";
+
+ O << " return false;\n";
+ O << "}\n\n";
+
+ O << "#endif // PRINT_ALIAS_INSTR\n";
+}
void AsmWriterEmitter::run(raw_ostream &O) {
EmitSourceFileHeader("Assembly Writer Source Fragment", O);
@@ -550,5 +798,6 @@ void AsmWriterEmitter::run(raw_ostream &O) {
EmitPrintInstruction(O);
EmitGetRegisterName(O);
EmitGetInstructionName(O);
+ EmitPrintAliasInstruction(O);
}
diff --git a/contrib/llvm/utils/TableGen/AsmWriterEmitter.h b/contrib/llvm/utils/TableGen/AsmWriterEmitter.h
index 9f7d776..5e8d6f5 100644
--- a/contrib/llvm/utils/TableGen/AsmWriterEmitter.h
+++ b/contrib/llvm/utils/TableGen/AsmWriterEmitter.h
@@ -38,6 +38,7 @@ private:
void EmitPrintInstruction(raw_ostream &o);
void EmitGetRegisterName(raw_ostream &o);
void EmitGetInstructionName(raw_ostream &o);
+ void EmitPrintAliasInstruction(raw_ostream &O);
AsmWriterInst *getAsmWriterInstByID(unsigned ID) const {
assert(ID < NumberedInstructions.size());
diff --git a/contrib/llvm/utils/TableGen/ClangSACheckersEmitter.cpp b/contrib/llvm/utils/TableGen/ClangSACheckersEmitter.cpp
index 3e49ab1..8865db3 100644
--- a/contrib/llvm/utils/TableGen/ClangSACheckersEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/ClangSACheckersEmitter.cpp
@@ -148,6 +148,7 @@ void ClangSACheckersEmitter::run(raw_ostream &OS) {
// Create a pseudo-group to hold this checker.
std::string fullName = getCheckerFullName(R);
GroupInfo &info = groupInfoByName[fullName];
+ info.Hidden = R->getValueAsBit("Hidden");
recordGroupMap[R] = &info;
info.Checkers.push_back(R);
} else {
diff --git a/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp b/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp
index ccd3efd..b0839c3 100644
--- a/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp
+++ b/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp
@@ -34,7 +34,9 @@ using namespace llvm;
MAP(E8, 39) \
MAP(F0, 40) \
MAP(F8, 41) \
- MAP(F9, 42)
+ MAP(F9, 42) \
+ MAP(D0, 45) \
+ MAP(D1, 46)
// A clone of X86 since we can't depend on something that is generated.
namespace X86Local {
diff --git a/lib/clang/include/clang/Basic/Version.inc b/lib/clang/include/clang/Basic/Version.inc
index 053c13b..1d6509c 100644
--- a/lib/clang/include/clang/Basic/Version.inc
+++ b/lib/clang/include/clang/Basic/Version.inc
@@ -5,6 +5,6 @@
#define CLANG_VERSION_MINOR 9
#define CLANG_VENDOR "FreeBSD "
-#define CLANG_VENDOR_SUFFIX " 20110220"
+#define CLANG_VENDOR_SUFFIX " 20110226"
-#define SVN_REVISION "126079"
+#define SVN_REVISION "126547"
diff --git a/lib/clang/libclanganalysis/Makefile b/lib/clang/libclanganalysis/Makefile
index 9f482e3..e122469 100644
--- a/lib/clang/libclanganalysis/Makefile
+++ b/lib/clang/libclanganalysis/Makefile
@@ -5,6 +5,7 @@ LIB= clanganalysis
SRCDIR= tools/clang/lib/Analysis
SRCS= AnalysisContext.cpp \
CFG.cpp \
+ CFGReachabilityAnalysis.cpp \
CFGStmtMap.cpp \
CocoaConventions.cpp \
FormatString.cpp \
diff --git a/lib/clang/libclangstaticanalyzercheckers/Makefile b/lib/clang/libclangstaticanalyzercheckers/Makefile
index 8dca68e..496d107 100644
--- a/lib/clang/libclangstaticanalyzercheckers/Makefile
+++ b/lib/clang/libclangstaticanalyzercheckers/Makefile
@@ -43,7 +43,7 @@ SRCS= AdjustedReturnValueChecker.cpp \
PthreadLockChecker.cpp \
ReturnPointerRangeChecker.cpp \
ReturnUndefChecker.cpp \
- StackAddrLeakChecker.cpp \
+ StackAddrEscapeChecker.cpp \
StreamChecker.cpp \
UndefBranchChecker.cpp \
UndefCapturedBlockVarChecker.cpp \
OpenPOWER on IntegriCloud