diff options
373 files changed, 8461 insertions, 4580 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 0d923b91e123..b1ab11de72df 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,9 +51,6 @@ if( CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR ) set( CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib ) set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib ) - add_definitions( -D__STDC_LIMIT_MACROS ) - add_definitions( -D__STDC_CONSTANT_MACROS ) - set( CLANG_BUILT_STANDALONE 1 ) endif() @@ -121,6 +118,37 @@ configure_file( ${CLANG_SOURCE_DIR}/include/clang/Config/config.h.cmake ${CLANG_BINARY_DIR}/include/clang/Config/config.h) +include(LLVMParseArguments) + +function(clang_tablegen) + # Syntax: + # clang_tablegen output-file [tablegen-arg ...] SOURCE source-file + # [[TARGET cmake-target-name] [DEPENDS extra-dependency ...]] + # + # Generates a custom command for invoking tblgen as + # + # tblgen source-file -o=output-file tablegen-arg ... + # + # and, if cmake-target-name is provided, creates a custom target for + # executing the custom command depending on output-file. It is + # possible to list more files to depend after DEPENDS. + + parse_arguments( CTG "SOURCE;TARGET;DEPENDS" "" ${ARGN} ) + + if( NOT CTG_SOURCE ) + message(FATAL_ERROR "SOURCE source-file required by clang_tablegen") + endif() + + set( LLVM_TARGET_DEFINITIONS ${CTG_SOURCE} ) + tablegen( ${CTG_DEFAULT_ARGS} ) + + list( GET CTG_DEFAULT_ARGS 0 output_file ) + if( CTG_TARGET ) + add_custom_target( ${CTG_TARGET} DEPENDS ${output_file} ${CTG_DEPENDS} ) + set_target_properties( ${CTG_TARGET} PROPERTIES FOLDER "Clang tablegenning") + endif() +endfunction(clang_tablegen) + macro(add_clang_library name) llvm_process_sources(srcs ${ARGN}) if(MSVC_IDE OR XCODE) @@ -175,10 +203,12 @@ macro(add_clang_library name) install(TARGETS ${name} LIBRARY DESTINATION lib${LLVM_LIBDIR_SUFFIX} ARCHIVE DESTINATION lib${LLVM_LIBDIR_SUFFIX}) + set_target_properties(${name} PROPERTIES FOLDER "Clang libraries") endmacro(add_clang_library) macro(add_clang_executable name) add_llvm_executable( ${name} ${ARGN} ) + set_target_properties(${name} PROPERTIES FOLDER "Clang executables") endmacro(add_clang_executable) include_directories( @@ -204,6 +234,16 @@ install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/include/ add_definitions( -D_GNU_SOURCE -DHAVE_CLANG_CONFIG_H ) +# Clang version information +set(CLANG_EXECUTABLE_VERSION + "${CLANG_VERSION_MAJOR}.${CLANG_VERSION_MINOR}" CACHE STRING + "Version number that will be placed into the clang executable, in the form XX.YY") +set(LIBCLANG_LIBRARY_VERSION + "${CLANG_VERSION_MAJOR}.${CLANG_VERSION_MINOR}" CACHE STRING + "Version number that will be placed into the libclang library , in the form XX.YY") +mark_as_advanced(CLANG_EXECUTABLE_VERSION LIBCLANG_LIBRARY_VERSION) + + option(CLANG_BUILD_EXAMPLES "Build CLANG example programs." OFF) if(CLANG_BUILD_EXAMPLES) add_subdirectory(examples) @@ -215,13 +255,12 @@ add_subdirectory(tools) add_subdirectory(runtime) # TODO: docs. -if( LLVM_INCLUDE_TESTS ) add_subdirectory(test) -endif() -# FIXME: unittests require gtest. -if( NOT CLANG_BUILT_STANDALONE ) - add_subdirectory(unittests) +if( LLVM_INCLUDE_TESTS ) + if( NOT CLANG_BUILT_STANDALONE ) + add_subdirectory(unittests) + endif() endif() # Workaround for MSVS10 to avoid the Dialog Hell diff --git a/clang.xcodeproj/project.pbxproj b/clang.xcodeproj/project.pbxproj index 8356aac544ae..e14448cdb141 100644 --- a/clang.xcodeproj/project.pbxproj +++ b/clang.xcodeproj/project.pbxproj @@ -6,454 +6,6 @@ objectVersion = 42; objects = { -/* Begin PBXBuildFile section */ - 03F50AC60D416EAA00B9CF60 /* Targets.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 03F50AC50D416EAA00B9CF60 /* Targets.cpp */; }; - 1A2193CE0F45EEB700C0713D /* Mangle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A2193CC0F45EEB700C0713D /* Mangle.cpp */; }; - 1A2A54B60FD1DD1C00F4CE45 /* ASTConsumers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A2A54A50FD1DD1C00F4CE45 /* ASTConsumers.cpp */; }; - 1A2A54B80FD1DD1C00F4CE45 /* CacheTokens.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A2A54A70FD1DD1C00F4CE45 /* CacheTokens.cpp */; }; - 1A2A54B90FD1DD1C00F4CE45 /* DependencyFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A2A54A80FD1DD1C00F4CE45 /* DependencyFile.cpp */; }; - 1A2A54BA0FD1DD1C00F4CE45 /* DiagChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A2A54A90FD1DD1C00F4CE45 /* DiagChecker.cpp */; }; - 1A2A54BB0FD1DD1C00F4CE45 /* DocumentXML.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A2A54AA0FD1DD1C00F4CE45 /* DocumentXML.cpp */; }; - 1A2A54BF0FD1DD1C00F4CE45 /* PrintPreprocessedOutput.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A2A54AE0FD1DD1C00F4CE45 /* PrintPreprocessedOutput.cpp */; }; - 1A2A54C40FD1DD1C00F4CE45 /* StmtXML.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A2A54B30FD1DD1C00F4CE45 /* StmtXML.cpp */; }; - 1A2A54C50FD1DD1C00F4CE45 /* Warnings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A2A54B40FD1DD1C00F4CE45 /* Warnings.cpp */; }; - 1A30A9E90B93A4C800201A91 /* ExprCXX.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 1A30A9E80B93A4C800201A91 /* ExprCXX.h */; }; - 1A376A2D0D4AED9B002A1C52 /* CGExprConstant.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A376A2C0D4AED9B002A1C52 /* CGExprConstant.cpp */; }; - 1A3D2C4E12A2CD3D0088C44A /* CGCXXABI.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A3D2C4D12A2CD3D0088C44A /* CGCXXABI.cpp */; }; - 1A471AB50F437BC500753CE8 /* CGBlocks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A471AB40F437BC500753CE8 /* CGBlocks.cpp */; }; - 1A4C41BF105B4C0B0047B5E7 /* CGClass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A4C41BE105B4C0B0047B5E7 /* CGClass.cpp */; }; - 1A5D5E580E5E81010023C059 /* CGCXX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A5D5E570E5E81010023C059 /* CGCXX.cpp */; }; - 1A621BB7110FE6AA009E6834 /* TargetInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A621BB5110FE6AA009E6834 /* TargetInfo.cpp */; }; - 1A621C4211111D61009E6834 /* CIndexCodeCompletion.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A621C3A11111D61009E6834 /* CIndexCodeCompletion.cpp */; }; - 1A621C4311111D61009E6834 /* CIndexer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A621C3B11111D61009E6834 /* CIndexer.cpp */; }; - 1A621C4411111D61009E6834 /* CIndexInclusionStack.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A621C3D11111D61009E6834 /* CIndexInclusionStack.cpp */; }; - 1A621C4511111D61009E6834 /* CIndexUSRs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A621C3E11111D61009E6834 /* CIndexUSRs.cpp */; }; - 1A621C4611111D61009E6834 /* CXCursor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A621C3F11111D61009E6834 /* CXCursor.cpp */; }; - 1A6B6CD410693FC900BB4A8F /* CodeCompleteConsumer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A6B6CD110693FC900BB4A8F /* CodeCompleteConsumer.cpp */; }; - 1A6B6CD510693FC900BB4A8F /* SemaCodeComplete.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A6B6CD210693FC900BB4A8F /* SemaCodeComplete.cpp */; }; - 1A6B6E9A1069833600BB4A8F /* CGExprCXX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A6B6E991069833600BB4A8F /* CGExprCXX.cpp */; }; - 1A6C01F7108128710072DEE4 /* CGRTTI.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A6C01F6108128710072DEE4 /* CGRTTI.cpp */; }; - 1A6FE7090FD6F85800E00CA9 /* CGTemporaries.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A6FE7080FD6F85800E00CA9 /* CGTemporaries.cpp */; }; - 1A701B640F7C8FE400FEC4D1 /* SemaAccess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A701B630F7C8FE400FEC4D1 /* SemaAccess.cpp */; }; - 1A7342480C7B57D500122F56 /* CGObjC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A7342470C7B57D500122F56 /* CGObjC.cpp */; }; - 1A81AA19108144F40094E50B /* CGVTables.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A81AA18108144F40094E50B /* CGVTables.cpp */; }; - 1A869A700BA2164C008DA07A /* LiteralSupport.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 1A869A6E0BA2164C008DA07A /* LiteralSupport.h */; }; - 1A869AA80BA21ABA008DA07A /* LiteralSupport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A869AA70BA21ABA008DA07A /* LiteralSupport.cpp */; }; - 1A97825B1108BA18002B98FC /* CGVTT.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A97825A1108BA18002B98FC /* CGVTT.cpp */; }; - 1A986AB710D0746D00A8EA9E /* CGDeclCXX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A986AB610D0746D00A8EA9E /* CGDeclCXX.cpp */; }; - 1ABC36940C7A4BDC006DB0AB /* CGBuiltin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ABC36930C7A4BDC006DB0AB /* CGBuiltin.cpp */; }; - 1ABD23D61182449800A48E65 /* APValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ABD23B11182449800A48E65 /* APValue.cpp */; }; - 1ABD23D71182449800A48E65 /* ASTConsumer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ABD23B21182449800A48E65 /* ASTConsumer.cpp */; }; - 1ABD23D81182449800A48E65 /* ASTContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ABD23B31182449800A48E65 /* ASTContext.cpp */; }; - 1ABD23D91182449800A48E65 /* ASTDiagnostic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ABD23B41182449800A48E65 /* ASTDiagnostic.cpp */; }; - 1ABD23DA1182449800A48E65 /* ASTImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ABD23B51182449800A48E65 /* ASTImporter.cpp */; }; - 1ABD23DB1182449800A48E65 /* AttrImpl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ABD23B61182449800A48E65 /* AttrImpl.cpp */; }; - 1ABD23DC1182449800A48E65 /* CXXInheritance.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ABD23B71182449800A48E65 /* CXXInheritance.cpp */; }; - 1ABD23DD1182449800A48E65 /* Decl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ABD23B81182449800A48E65 /* Decl.cpp */; }; - 1ABD23DE1182449800A48E65 /* DeclarationName.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ABD23B91182449800A48E65 /* DeclarationName.cpp */; }; - 1ABD23DF1182449800A48E65 /* DeclBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ABD23BA1182449800A48E65 /* DeclBase.cpp */; }; - 1ABD23E01182449800A48E65 /* DeclCXX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ABD23BB1182449800A48E65 /* DeclCXX.cpp */; }; - 1ABD23E11182449800A48E65 /* DeclFriend.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ABD23BC1182449800A48E65 /* DeclFriend.cpp */; }; - 1ABD23E21182449800A48E65 /* DeclGroup.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ABD23BD1182449800A48E65 /* DeclGroup.cpp */; }; - 1ABD23E31182449800A48E65 /* DeclObjC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ABD23BE1182449800A48E65 /* DeclObjC.cpp */; }; - 1ABD23E41182449800A48E65 /* DeclPrinter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ABD23BF1182449800A48E65 /* DeclPrinter.cpp */; }; - 1ABD23E51182449800A48E65 /* DeclTemplate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ABD23C01182449800A48E65 /* DeclTemplate.cpp */; }; - 1ABD23E61182449800A48E65 /* Expr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ABD23C11182449800A48E65 /* Expr.cpp */; }; - 1ABD23E71182449800A48E65 /* ExprConstant.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ABD23C21182449800A48E65 /* ExprConstant.cpp */; }; - 1ABD23E81182449800A48E65 /* ExprCXX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ABD23C31182449800A48E65 /* ExprCXX.cpp */; }; - 1ABD23E91182449800A48E65 /* FullExpr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ABD23C41182449800A48E65 /* FullExpr.cpp */; }; - 1ABD23EA1182449800A48E65 /* InheritViz.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ABD23C51182449800A48E65 /* InheritViz.cpp */; }; - 1ABD23EB1182449800A48E65 /* NestedNameSpecifier.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ABD23C61182449800A48E65 /* NestedNameSpecifier.cpp */; }; - 1ABD23EC1182449800A48E65 /* ParentMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ABD23C71182449800A48E65 /* ParentMap.cpp */; }; - 1ABD23ED1182449800A48E65 /* RecordLayout.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ABD23C81182449800A48E65 /* RecordLayout.cpp */; }; - 1ABD23EE1182449800A48E65 /* RecordLayoutBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ABD23C91182449800A48E65 /* RecordLayoutBuilder.cpp */; }; - 1ABD23EF1182449800A48E65 /* Stmt.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ABD23CB1182449800A48E65 /* Stmt.cpp */; }; - 1ABD23F01182449800A48E65 /* StmtDumper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ABD23CC1182449800A48E65 /* StmtDumper.cpp */; }; - 1ABD23F11182449800A48E65 /* StmtIterator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ABD23CD1182449800A48E65 /* StmtIterator.cpp */; }; - 1ABD23F21182449800A48E65 /* StmtPrinter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ABD23CE1182449800A48E65 /* StmtPrinter.cpp */; }; - 1ABD23F31182449800A48E65 /* StmtProfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ABD23CF1182449800A48E65 /* StmtProfile.cpp */; }; - 1ABD23F41182449800A48E65 /* StmtViz.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ABD23D01182449800A48E65 /* StmtViz.cpp */; }; - 1ABD23F51182449800A48E65 /* TemplateBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ABD23D11182449800A48E65 /* TemplateBase.cpp */; }; - 1ABD23F61182449800A48E65 /* TemplateName.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ABD23D21182449800A48E65 /* TemplateName.cpp */; }; - 1ABD23F71182449800A48E65 /* Type.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ABD23D31182449800A48E65 /* Type.cpp */; }; - 1ABD23F81182449800A48E65 /* TypeLoc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ABD23D41182449800A48E65 /* TypeLoc.cpp */; }; - 1ABD23F91182449800A48E65 /* TypePrinter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ABD23D51182449800A48E65 /* TypePrinter.cpp */; }; - 1AC1A67D12999D8E006FBC77 /* AnalysisContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A67212999D8E006FBC77 /* AnalysisContext.cpp */; }; - 1AC1A67E12999D8E006FBC77 /* CFG.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A67312999D8E006FBC77 /* CFG.cpp */; }; - 1AC1A67F12999D8E006FBC77 /* CFGStmtMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A67412999D8E006FBC77 /* CFGStmtMap.cpp */; }; - 1AC1A68012999D8E006FBC77 /* FormatString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A67512999D8E006FBC77 /* FormatString.cpp */; }; - 1AC1A68112999D8E006FBC77 /* LiveVariables.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A67712999D8E006FBC77 /* LiveVariables.cpp */; }; - 1AC1A68212999D8E006FBC77 /* PrintfFormatString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A67812999D8E006FBC77 /* PrintfFormatString.cpp */; }; - 1AC1A68312999D8E006FBC77 /* PseudoConstantAnalysis.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A67912999D8E006FBC77 /* PseudoConstantAnalysis.cpp */; }; - 1AC1A68412999D8E006FBC77 /* ReachableCode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A67A12999D8E006FBC77 /* ReachableCode.cpp */; }; - 1AC1A68512999D8E006FBC77 /* ScanfFormatString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A67B12999D8E006FBC77 /* ScanfFormatString.cpp */; }; - 1AC1A68612999D8E006FBC77 /* UninitializedValues.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A67C12999D8E006FBC77 /* UninitializedValues.cpp */; }; - 1AC1A9EF1299A287006FBC77 /* AdjustedReturnValueChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A6881299A284006FBC77 /* AdjustedReturnValueChecker.cpp */; }; - 1AC1A9F01299A287006FBC77 /* AggExprVisitor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A6891299A284006FBC77 /* AggExprVisitor.cpp */; }; - 1AC1A9F11299A287006FBC77 /* AnalysisConsumer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A68A1299A284006FBC77 /* AnalysisConsumer.cpp */; }; - 1AC1A9F21299A287006FBC77 /* AnalysisManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A68B1299A284006FBC77 /* AnalysisManager.cpp */; }; - 1AC1A9F31299A287006FBC77 /* AnalyzerStatsChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A68C1299A284006FBC77 /* AnalyzerStatsChecker.cpp */; }; - 1AC1A9F41299A287006FBC77 /* ArrayBoundChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A68D1299A284006FBC77 /* ArrayBoundChecker.cpp */; }; - 1AC1A9F51299A287006FBC77 /* AttrNonNullChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A68E1299A284006FBC77 /* AttrNonNullChecker.cpp */; }; - 1AC1A9F61299A287006FBC77 /* BasicConstraintManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A68F1299A284006FBC77 /* BasicConstraintManager.cpp */; }; - 1AC1A9F71299A287006FBC77 /* BasicObjCFoundationChecks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A6901299A284006FBC77 /* BasicObjCFoundationChecks.cpp */; }; - 1AC1A9F81299A287006FBC77 /* BasicStore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A6921299A284006FBC77 /* BasicStore.cpp */; }; - 1AC1A9F91299A287006FBC77 /* BasicValueFactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A6931299A284006FBC77 /* BasicValueFactory.cpp */; }; - 1AC1A9FA1299A287006FBC77 /* BugReporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A6941299A284006FBC77 /* BugReporter.cpp */; }; - 1AC1A9FB1299A287006FBC77 /* BugReporterVisitors.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A6951299A284006FBC77 /* BugReporterVisitors.cpp */; }; - 1AC1A9FC1299A287006FBC77 /* BuiltinFunctionChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A6961299A284006FBC77 /* BuiltinFunctionChecker.cpp */; }; - 1AC1A9FD1299A287006FBC77 /* CallAndMessageChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A6971299A284006FBC77 /* CallAndMessageChecker.cpp */; }; - 1AC1A9FE1299A287006FBC77 /* CastSizeChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A6981299A284006FBC77 /* CastSizeChecker.cpp */; }; - 1AC1A9FF1299A287006FBC77 /* CastToStructChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A6991299A284006FBC77 /* CastToStructChecker.cpp */; }; - 1AC1AA001299A287006FBC77 /* CFRefCount.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A69A1299A284006FBC77 /* CFRefCount.cpp */; }; - 1AC1AA011299A287006FBC77 /* CheckDeadStores.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A69B1299A284006FBC77 /* CheckDeadStores.cpp */; }; - 1AC1AA021299A287006FBC77 /* Checker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A69C1299A284006FBC77 /* Checker.cpp */; }; - 1AC1AA031299A287006FBC77 /* CheckerHelpers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A69D1299A284006FBC77 /* CheckerHelpers.cpp */; }; - 1AC1AA041299A287006FBC77 /* CheckObjCDealloc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A69E1299A284006FBC77 /* CheckObjCDealloc.cpp */; }; - 1AC1AA051299A287006FBC77 /* CheckObjCInstMethSignature.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A69F1299A284006FBC77 /* CheckObjCInstMethSignature.cpp */; }; - 1AC1AA061299A287006FBC77 /* CheckSecuritySyntaxOnly.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A6A01299A284006FBC77 /* CheckSecuritySyntaxOnly.cpp */; }; - 1AC1AA071299A287006FBC77 /* CheckSizeofPointer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A6A11299A284006FBC77 /* CheckSizeofPointer.cpp */; }; - 1AC1AA081299A287006FBC77 /* ChrootChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A6A21299A284006FBC77 /* ChrootChecker.cpp */; }; - 1AC1AA091299A287006FBC77 /* CocoaConventions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A6A41299A284006FBC77 /* CocoaConventions.cpp */; }; - 1AC1AA0A1299A287006FBC77 /* CStringChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A6A51299A284006FBC77 /* CStringChecker.cpp */; }; - 1AC1AB3D1299A287006FBC77 /* DereferenceChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A7DC1299A285006FBC77 /* DereferenceChecker.cpp */; }; - 1AC1AB3E1299A287006FBC77 /* DivZeroChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A7DD1299A285006FBC77 /* DivZeroChecker.cpp */; }; - 1AC1AB3F1299A287006FBC77 /* Environment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A7DE1299A285006FBC77 /* Environment.cpp */; }; - 1AC1AB401299A287006FBC77 /* ExplodedGraph.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A7DF1299A285006FBC77 /* ExplodedGraph.cpp */; }; - 1AC1AB411299A287006FBC77 /* FixedAddressChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A7E01299A285006FBC77 /* FixedAddressChecker.cpp */; }; - 1AC1AB421299A287006FBC77 /* FlatStore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A7E11299A285006FBC77 /* FlatStore.cpp */; }; - 1AC1AB431299A287006FBC77 /* FrontendActions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A7E21299A285006FBC77 /* FrontendActions.cpp */; }; - 1AC1AB441299A287006FBC77 /* GRBlockCounter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A7E31299A285006FBC77 /* GRBlockCounter.cpp */; }; - 1AC1AB451299A287006FBC77 /* GRCoreEngine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A7E41299A285006FBC77 /* GRCoreEngine.cpp */; }; - 1AC1AB461299A287006FBC77 /* GRCXXExprEngine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A7E51299A285006FBC77 /* GRCXXExprEngine.cpp */; }; - 1AC1AB471299A287006FBC77 /* GRExprEngine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A7E61299A285006FBC77 /* GRExprEngine.cpp */; }; - 1AC1AB481299A287006FBC77 /* GRExprEngineExperimentalChecks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A7E71299A285006FBC77 /* GRExprEngineExperimentalChecks.cpp */; }; - 1AC1AB491299A287006FBC77 /* GRState.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A7EA1299A285006FBC77 /* GRState.cpp */; }; - 1AC1AB4A1299A287006FBC77 /* HTMLDiagnostics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A7EB1299A285006FBC77 /* HTMLDiagnostics.cpp */; }; - 1AC1AB4B1299A287006FBC77 /* IdempotentOperationChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A7EC1299A285006FBC77 /* IdempotentOperationChecker.cpp */; }; - 1AC1AB4C1299A287006FBC77 /* LLVMConventionsChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A7ED1299A285006FBC77 /* LLVMConventionsChecker.cpp */; }; - 1AC1AB4D1299A287006FBC77 /* MacOSXAPIChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A7EE1299A285006FBC77 /* MacOSXAPIChecker.cpp */; }; - 1AC1AB4F1299A287006FBC77 /* MallocChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A7F01299A285006FBC77 /* MallocChecker.cpp */; }; - 1AC1AB501299A287006FBC77 /* ManagerRegistry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A7F11299A285006FBC77 /* ManagerRegistry.cpp */; }; - 1AC1AB511299A287006FBC77 /* MemRegion.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A7F21299A285006FBC77 /* MemRegion.cpp */; }; - 1AC1AB521299A287006FBC77 /* NoReturnFunctionChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A7F31299A285006FBC77 /* NoReturnFunctionChecker.cpp */; }; - 1AC1AB531299A287006FBC77 /* NSAutoreleasePoolChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A7F41299A285006FBC77 /* NSAutoreleasePoolChecker.cpp */; }; - 1AC1AB541299A287006FBC77 /* NSErrorChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A7F51299A285006FBC77 /* NSErrorChecker.cpp */; }; - 1AC1AB551299A287006FBC77 /* ObjCAtSyncChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A7F61299A285006FBC77 /* ObjCAtSyncChecker.cpp */; }; - 1AC1AB561299A287006FBC77 /* ObjCUnusedIVarsChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A7F71299A285006FBC77 /* ObjCUnusedIVarsChecker.cpp */; }; - 1AC1AB571299A287006FBC77 /* OSAtomicChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A7F81299A285006FBC77 /* OSAtomicChecker.cpp */; }; - 1AC1AB581299A287006FBC77 /* PathDiagnostic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A7F91299A285006FBC77 /* PathDiagnostic.cpp */; }; - 1AC1AB591299A287006FBC77 /* PlistDiagnostics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A7FA1299A285006FBC77 /* PlistDiagnostics.cpp */; }; - 1AC1AB5A1299A287006FBC77 /* PointerArithChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A7FB1299A285006FBC77 /* PointerArithChecker.cpp */; }; - 1AC1AB5B1299A287006FBC77 /* PointerSubChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A7FC1299A285006FBC77 /* PointerSubChecker.cpp */; }; - 1AC1AB5C1299A287006FBC77 /* PthreadLockChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A7FD1299A285006FBC77 /* PthreadLockChecker.cpp */; }; - 1AC1AB5D1299A287006FBC77 /* RangeConstraintManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A7FE1299A285006FBC77 /* RangeConstraintManager.cpp */; }; - 1AC1AB5E1299A287006FBC77 /* RegionStore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A8001299A285006FBC77 /* RegionStore.cpp */; }; - 1AC1AD331299A287006FBC77 /* ReturnPointerRangeChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A9DB1299A287006FBC77 /* ReturnPointerRangeChecker.cpp */; }; - 1AC1AD341299A287006FBC77 /* ReturnUndefChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A9DC1299A287006FBC77 /* ReturnUndefChecker.cpp */; }; - 1AC1AD351299A287006FBC77 /* SimpleConstraintManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A9DD1299A287006FBC77 /* SimpleConstraintManager.cpp */; }; - 1AC1AD361299A287006FBC77 /* SimpleSValuator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A9DF1299A287006FBC77 /* SimpleSValuator.cpp */; }; - 1AC1AD371299A287006FBC77 /* StackAddrLeakChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A9E01299A287006FBC77 /* StackAddrLeakChecker.cpp */; }; - 1AC1AD381299A287006FBC77 /* Store.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A9E11299A287006FBC77 /* Store.cpp */; }; - 1AC1AD391299A287006FBC77 /* StreamChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A9E21299A287006FBC77 /* StreamChecker.cpp */; }; - 1AC1AD3A1299A287006FBC77 /* SVals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A9E31299A287006FBC77 /* SVals.cpp */; }; - 1AC1AD3B1299A287006FBC77 /* SValuator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A9E41299A287006FBC77 /* SValuator.cpp */; }; - 1AC1AD3C1299A287006FBC77 /* SymbolManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A9E51299A287006FBC77 /* SymbolManager.cpp */; }; - 1AC1AD3D1299A287006FBC77 /* UndefBranchChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A9E61299A287006FBC77 /* UndefBranchChecker.cpp */; }; - 1AC1AD3E1299A287006FBC77 /* UndefCapturedBlockVarChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A9E71299A287006FBC77 /* UndefCapturedBlockVarChecker.cpp */; }; - 1AC1AD3F1299A287006FBC77 /* UndefinedArraySubscriptChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A9E81299A287006FBC77 /* UndefinedArraySubscriptChecker.cpp */; }; - 1AC1AD401299A287006FBC77 /* UndefinedAssignmentChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A9E91299A287006FBC77 /* UndefinedAssignmentChecker.cpp */; }; - 1AC1AD411299A287006FBC77 /* UndefResultChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A9EA1299A287006FBC77 /* UndefResultChecker.cpp */; }; - 1AC1AD421299A287006FBC77 /* UnixAPIChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A9EB1299A287006FBC77 /* UnixAPIChecker.cpp */; }; - 1AC1AD431299A287006FBC77 /* UnreachableCodeChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A9EC1299A287006FBC77 /* UnreachableCodeChecker.cpp */; }; - 1AC1AD441299A287006FBC77 /* ValueManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A9ED1299A287006FBC77 /* ValueManager.cpp */; }; - 1AC1AD451299A287006FBC77 /* VLASizeChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC1A9EE1299A287006FBC77 /* VLASizeChecker.cpp */; }; - 1ACB57E41105820D0047B991 /* CompilerInstance.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ACB57DB1105820D0047B991 /* CompilerInstance.cpp */; }; - 1ACB57E51105820D0047B991 /* CompilerInvocation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ACB57DC1105820D0047B991 /* CompilerInvocation.cpp */; }; - 1ACB57E61105820D0047B991 /* DeclXML.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ACB57DD1105820D0047B991 /* DeclXML.cpp */; }; - 1ACB57E71105820D0047B991 /* FrontendAction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ACB57DE1105820D0047B991 /* FrontendAction.cpp */; }; - 1ACB57E81105820D0047B991 /* FrontendActions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ACB57DF1105820D0047B991 /* FrontendActions.cpp */; }; - 1ACB57E91105820D0047B991 /* FrontendOptions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ACB57E01105820D0047B991 /* FrontendOptions.cpp */; }; - 1ACB57EA1105820D0047B991 /* LangStandards.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ACB57E11105820D0047B991 /* LangStandards.cpp */; }; - 1ACB57EB1105820D0047B991 /* TypeXML.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ACB57E21105820D0047B991 /* TypeXML.cpp */; }; - 1ACB57EC1105820D0047B991 /* VerifyDiagnosticsClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ACB57E31105820D0047B991 /* VerifyDiagnosticsClient.cpp */; }; - 1ADF47AF0F782C3200E48A8A /* SemaTemplateInstantiateDecl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ADF47AE0F782C3200E48A8A /* SemaTemplateInstantiateDecl.cpp */; }; - 1AF1B50F109A4FB800AFAFAC /* CGException.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AF1B50E109A4FB800AFAFAC /* CGException.cpp */; }; - 1AFDD8721161085D00AE030A /* ASTMerge.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AFDD8701161085D00AE030A /* ASTMerge.cpp */; }; - 1AFF8AE31012BFC900D248DA /* CGRecordLayoutBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AFF8AE11012BFC900D248DA /* CGRecordLayoutBuilder.cpp */; }; - 352246E80F5C6BE000D0D279 /* InitHeaderSearch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 352246E20F5C6BE000D0D279 /* InitHeaderSearch.cpp */; }; - 352246EB0F5C6BE000D0D279 /* TextDiagnosticBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 352246E50F5C6BE000D0D279 /* TextDiagnosticBuffer.cpp */; }; - 352246EC0F5C6BE000D0D279 /* TextDiagnosticPrinter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 352246E60F5C6BE000D0D279 /* TextDiagnosticPrinter.cpp */; }; - 352712510DAFE54700C76352 /* IdentifierResolver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 352712500DAFE54700C76352 /* IdentifierResolver.cpp */; }; - 3534A01D0E129849002709B2 /* ParseCXXInlineMethods.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3534A01C0E129849002709B2 /* ParseCXXInlineMethods.cpp */; }; - 3537AA0E0ECD08A4008F7CDC /* PreprocessorLexer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3537AA0D0ECD08A4008F7CDC /* PreprocessorLexer.cpp */; }; - 353959D50EE5F88A00E82461 /* ParseTemplate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 353959D40EE5F88A00E82461 /* ParseTemplate.cpp */; }; - 35475B200E79973F0000BFE4 /* CGCall.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 35475B1F0E79973F0000BFE4 /* CGCall.cpp */; }; - 3551068C0E9A8546006A4E44 /* ParsePragma.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3551068A0E9A8546006A4E44 /* ParsePragma.cpp */; }; - 3551068D0E9A8546006A4E44 /* ParseTentative.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3551068B0E9A8546006A4E44 /* ParseTentative.cpp */; }; - 3552E7550E520D80003A8CA5 /* PPCaching.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3552E7540E520D80003A8CA5 /* PPCaching.cpp */; }; - 3552E7590E520DD7003A8CA5 /* CGObjCMac.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3552E7580E520DD7003A8CA5 /* CGObjCMac.cpp */; }; - 35544B8C0F5C803200D92AA9 /* SemaTemplateInstantiate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 35544B8B0F5C803200D92AA9 /* SemaTemplateInstantiate.cpp */; }; - 35585DC00EAFBC4500D0A97A /* SemaOverload.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 35585DBE0EAFBC4500D0A97A /* SemaOverload.cpp */; }; - 35707EFE0CD0F5CC000B2204 /* SourceLocation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 35707EFD0CD0F5CC000B2204 /* SourceLocation.cpp */; }; - 357EA27D0F2526F300439B60 /* SemaLookup.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 357EA27C0F2526F300439B60 /* SemaLookup.cpp */; }; - 3591853F0EFB1088000039AF /* SemaTemplate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3591853E0EFB1088000039AF /* SemaTemplate.cpp */; }; - 3599299B0DE2425300A8A33E /* SemaInit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3599299A0DE2425300A8A33E /* SemaInit.cpp */; }; - 35A3E7020DD3874400757F74 /* CGDebugInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 35A3E7000DD3874400757F74 /* CGDebugInfo.cpp */; }; - 35E194690ECB82FB00F21733 /* SemaCXXScopeSpec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 35E194670ECB82FB00F21733 /* SemaCXXScopeSpec.cpp */; }; - 35E1946A0ECB82FB00F21733 /* SemaCXXCast.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 35E194680ECB82FB00F21733 /* SemaCXXCast.cpp */; }; - 35E1946D0ECB83C100F21733 /* PTHLexer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 35E1946C0ECB83C100F21733 /* PTHLexer.cpp */; }; - 35EF67700DAD1D2C00B19414 /* SemaDeclCXX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 35EF676F0DAD1D2C00B19414 /* SemaDeclCXX.cpp */; }; - 57AA9250121C8B9400B4AA6C /* ASTReader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 57AA924D121C8B9400B4AA6C /* ASTReader.cpp */; }; - 57AA9251121C8B9400B4AA6C /* ASTReaderDecl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 57AA924E121C8B9400B4AA6C /* ASTReaderDecl.cpp */; }; - 57AA9252121C8B9400B4AA6C /* ASTReaderStmt.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 57AA924F121C8B9400B4AA6C /* ASTReaderStmt.cpp */; }; - 57F66612121B4DE600DCE3B7 /* ASTWriter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 57F6660F121B4DE600DCE3B7 /* ASTWriter.cpp */; }; - 57F66613121B4DE600DCE3B7 /* ASTWriterDecl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 57F66610121B4DE600DCE3B7 /* ASTWriterDecl.cpp */; }; - 57F66614121B4DE600DCE3B7 /* ASTWriterStmt.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 57F66611121B4DE600DCE3B7 /* ASTWriterStmt.cpp */; }; - 72D16C1F0D9975C400E6DA4A /* HTMLRewrite.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 72D16C1E0D9975C400E6DA4A /* HTMLRewrite.cpp */; }; - 84AF36A10CB17A3B00C820A5 /* DeclObjC.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 84AF36A00CB17A3B00C820A5 /* DeclObjC.h */; }; - 9012911D1048068D0083456D /* ASTUnit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9012911C1048068D0083456D /* ASTUnit.cpp */; }; - 90129121104812F90083456D /* CIndex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9012911F104812F90083456D /* CIndex.cpp */; }; - 906BF4B00F83BA2E001071FA /* ConvertUTF.c in Sources */ = {isa = PBXBuildFile; fileRef = 906BF4AF0F83BA2E001071FA /* ConvertUTF.c */; }; - 90F9EFAA104ABDED00D09A15 /* c-index-test.c in Sources */ = {isa = PBXBuildFile; fileRef = 90F9EFA9104ABDED00D09A15 /* c-index-test.c */; }; - 90FD6D7B103C3D49005F5B73 /* Analyzer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 90FD6D6D103C3D49005F5B73 /* Analyzer.cpp */; }; - 90FD6D7C103C3D49005F5B73 /* ASTLocation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 90FD6D6E103C3D49005F5B73 /* ASTLocation.cpp */; }; - 90FD6D7D103C3D49005F5B73 /* DeclReferenceMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 90FD6D70103C3D49005F5B73 /* DeclReferenceMap.cpp */; }; - 90FD6D7E103C3D49005F5B73 /* Entity.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 90FD6D71103C3D49005F5B73 /* Entity.cpp */; }; - 90FD6D7F103C3D49005F5B73 /* GlobalSelector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 90FD6D73103C3D49005F5B73 /* GlobalSelector.cpp */; }; - 90FD6D80103C3D49005F5B73 /* Handlers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 90FD6D74103C3D49005F5B73 /* Handlers.cpp */; }; - 90FD6D81103C3D49005F5B73 /* Indexer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 90FD6D75103C3D49005F5B73 /* Indexer.cpp */; }; - 90FD6D82103C3D49005F5B73 /* IndexProvider.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 90FD6D76103C3D49005F5B73 /* IndexProvider.cpp */; }; - 90FD6D83103C3D49005F5B73 /* Program.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 90FD6D77103C3D49005F5B73 /* Program.cpp */; }; - 90FD6D85103C3D49005F5B73 /* SelectorMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 90FD6D7A103C3D49005F5B73 /* SelectorMap.cpp */; }; - 90FD6DB6103D977E005F5B73 /* index-test.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 90FD6DB5103D977E005F5B73 /* index-test.cpp */; }; - BB5C372912A5057500259F53 /* DumpXML.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB5C372812A5057500259F53 /* DumpXML.cpp */; }; - BBA5AB7E1309C2FA000B38F1 /* AdjustedReturnValueChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB141309C2FA000B38F1 /* AdjustedReturnValueChecker.cpp */; }; - BBA5AB7F1309C2FA000B38F1 /* AnalyzerStatsChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB151309C2FA000B38F1 /* AnalyzerStatsChecker.cpp */; }; - BBA5AB801309C2FA000B38F1 /* ArrayBoundChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB161309C2FA000B38F1 /* ArrayBoundChecker.cpp */; }; - BBA5AB811309C2FA000B38F1 /* ArrayBoundCheckerV2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB171309C2FA000B38F1 /* ArrayBoundCheckerV2.cpp */; }; - BBA5AB821309C2FA000B38F1 /* AttrNonNullChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB181309C2FA000B38F1 /* AttrNonNullChecker.cpp */; }; - BBA5AB831309C2FA000B38F1 /* BasicObjCFoundationChecks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB191309C2FA000B38F1 /* BasicObjCFoundationChecks.cpp */; }; - BBA5AB841309C2FA000B38F1 /* BuiltinFunctionChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB1B1309C2FA000B38F1 /* BuiltinFunctionChecker.cpp */; }; - BBA5AB851309C2FA000B38F1 /* CallAndMessageChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB1C1309C2FA000B38F1 /* CallAndMessageChecker.cpp */; }; - BBA5AB861309C2FA000B38F1 /* CastSizeChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB1D1309C2FA000B38F1 /* CastSizeChecker.cpp */; }; - BBA5AB871309C2FA000B38F1 /* CastToStructChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB1E1309C2FA000B38F1 /* CastToStructChecker.cpp */; }; - BBA5AB881309C2FA000B38F1 /* CheckObjCDealloc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB201309C2FA000B38F1 /* CheckObjCDealloc.cpp */; }; - BBA5AB891309C2FA000B38F1 /* CheckObjCInstMethSignature.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB211309C2FA000B38F1 /* CheckObjCInstMethSignature.cpp */; }; - BBA5AB8A1309C2FA000B38F1 /* CheckSecuritySyntaxOnly.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB221309C2FA000B38F1 /* CheckSecuritySyntaxOnly.cpp */; }; - BBA5AB8B1309C2FA000B38F1 /* CheckSizeofPointer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB231309C2FA000B38F1 /* CheckSizeofPointer.cpp */; }; - BBA5AB8C1309C2FA000B38F1 /* ChrootChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB241309C2FA000B38F1 /* ChrootChecker.cpp */; }; - BBA5AB8D1309C2FA000B38F1 /* ClangSACheckerProvider.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB251309C2FA000B38F1 /* ClangSACheckerProvider.cpp */; }; - BBA5AB8E1309C2FA000B38F1 /* CStringChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB291309C2FA000B38F1 /* CStringChecker.cpp */; }; - BBA5AB8F1309C2FA000B38F1 /* DeadStoresChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB2A1309C2FA000B38F1 /* DeadStoresChecker.cpp */; }; - BBA5AB901309C2FA000B38F1 /* DereferenceChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB2B1309C2FA000B38F1 /* DereferenceChecker.cpp */; }; - BBA5AB911309C2FA000B38F1 /* DivZeroChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB2C1309C2FA000B38F1 /* DivZeroChecker.cpp */; }; - BBA5AB921309C2FA000B38F1 /* ExperimentalChecks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB2D1309C2FA000B38F1 /* ExperimentalChecks.cpp */; }; - BBA5AB931309C2FA000B38F1 /* ExprEngine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB2F1309C2FA000B38F1 /* ExprEngine.cpp */; }; - BBA5AB941309C2FA000B38F1 /* FixedAddressChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB301309C2FA000B38F1 /* FixedAddressChecker.cpp */; }; - BBA5AB951309C2FA000B38F1 /* IdempotentOperationChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB311309C2FA000B38F1 /* IdempotentOperationChecker.cpp */; }; - BBA5AB961309C2FA000B38F1 /* LLVMConventionsChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB331309C2FA000B38F1 /* LLVMConventionsChecker.cpp */; }; - BBA5AB971309C2FA000B38F1 /* MacOSXAPIChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB341309C2FA000B38F1 /* MacOSXAPIChecker.cpp */; }; - BBA5AB991309C2FA000B38F1 /* MallocChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB361309C2FA000B38F1 /* MallocChecker.cpp */; }; - BBA5AB9A1309C2FA000B38F1 /* NoReturnFunctionChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB371309C2FA000B38F1 /* NoReturnFunctionChecker.cpp */; }; - BBA5AB9B1309C2FA000B38F1 /* NSAutoreleasePoolChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB381309C2FA000B38F1 /* NSAutoreleasePoolChecker.cpp */; }; - BBA5AB9C1309C2FA000B38F1 /* NSErrorChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB3A1309C2FA000B38F1 /* NSErrorChecker.cpp */; }; - BBA5AB9D1309C2FA000B38F1 /* ObjCAtSyncChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB3B1309C2FA000B38F1 /* ObjCAtSyncChecker.cpp */; }; - BBA5AB9E1309C2FA000B38F1 /* ObjCSelfInitChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB3D1309C2FA000B38F1 /* ObjCSelfInitChecker.cpp */; }; - BBA5AB9F1309C2FA000B38F1 /* ObjCUnusedIVarsChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB3F1309C2FA000B38F1 /* ObjCUnusedIVarsChecker.cpp */; }; - BBA5ABA01309C2FA000B38F1 /* OSAtomicChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB401309C2FA000B38F1 /* OSAtomicChecker.cpp */; }; - BBA5ABA11309C2FA000B38F1 /* PointerArithChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB411309C2FA000B38F1 /* PointerArithChecker.cpp */; }; - BBA5ABA21309C2FA000B38F1 /* PointerSubChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB421309C2FA000B38F1 /* PointerSubChecker.cpp */; }; - BBA5ABA31309C2FA000B38F1 /* PthreadLockChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB431309C2FA000B38F1 /* PthreadLockChecker.cpp */; }; - BBA5ABA41309C2FA000B38F1 /* ReturnPointerRangeChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB441309C2FA000B38F1 /* ReturnPointerRangeChecker.cpp */; }; - BBA5ABA51309C2FA000B38F1 /* ReturnUndefChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB451309C2FA000B38F1 /* ReturnUndefChecker.cpp */; }; - BBA5ABA61309C2FA000B38F1 /* StackAddrLeakChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB461309C2FA000B38F1 /* StackAddrLeakChecker.cpp */; }; - BBA5ABA71309C2FA000B38F1 /* StreamChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB471309C2FA000B38F1 /* StreamChecker.cpp */; }; - BBA5ABA81309C2FA000B38F1 /* UndefBranchChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB481309C2FA000B38F1 /* UndefBranchChecker.cpp */; }; - BBA5ABA91309C2FA000B38F1 /* UndefCapturedBlockVarChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB491309C2FA000B38F1 /* UndefCapturedBlockVarChecker.cpp */; }; - BBA5ABAA1309C2FA000B38F1 /* UndefinedArraySubscriptChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB4A1309C2FA000B38F1 /* UndefinedArraySubscriptChecker.cpp */; }; - BBA5ABAB1309C2FA000B38F1 /* UndefinedAssignmentChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB4B1309C2FA000B38F1 /* UndefinedAssignmentChecker.cpp */; }; - BBA5ABAC1309C2FA000B38F1 /* UndefResultChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB4C1309C2FA000B38F1 /* UndefResultChecker.cpp */; }; - BBA5ABAD1309C2FA000B38F1 /* UnixAPIChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB4D1309C2FA000B38F1 /* UnixAPIChecker.cpp */; }; - BBA5ABAE1309C2FA000B38F1 /* UnreachableCodeChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB4E1309C2FA000B38F1 /* UnreachableCodeChecker.cpp */; }; - BBA5ABAF1309C2FA000B38F1 /* VLASizeChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB4F1309C2FA000B38F1 /* VLASizeChecker.cpp */; }; - BBA5ABB01309C2FA000B38F1 /* AggExprVisitor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB521309C2FA000B38F1 /* AggExprVisitor.cpp */; }; - BBA5ABB11309C2FA000B38F1 /* AnalysisManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB531309C2FA000B38F1 /* AnalysisManager.cpp */; }; - BBA5ABB21309C2FA000B38F1 /* BasicConstraintManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB541309C2FA000B38F1 /* BasicConstraintManager.cpp */; }; - BBA5ABB31309C2FA000B38F1 /* BasicStore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB551309C2FA000B38F1 /* BasicStore.cpp */; }; - BBA5ABB41309C2FA000B38F1 /* BasicValueFactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB561309C2FA000B38F1 /* BasicValueFactory.cpp */; }; - BBA5ABB51309C2FA000B38F1 /* BlockCounter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB571309C2FA000B38F1 /* BlockCounter.cpp */; }; - BBA5ABB61309C2FA000B38F1 /* BugReporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB581309C2FA000B38F1 /* BugReporter.cpp */; }; - BBA5ABB71309C2FA000B38F1 /* BugReporterVisitors.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB591309C2FA000B38F1 /* BugReporterVisitors.cpp */; }; - BBA5ABB81309C2FA000B38F1 /* CFRefCount.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB5A1309C2FA000B38F1 /* CFRefCount.cpp */; }; - BBA5ABB91309C2FA000B38F1 /* Checker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB5B1309C2FA000B38F1 /* Checker.cpp */; }; - BBA5ABBA1309C2FA000B38F1 /* CheckerHelpers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB5C1309C2FA000B38F1 /* CheckerHelpers.cpp */; }; - BBA5ABBB1309C2FA000B38F1 /* CheckerManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB5D1309C2FA000B38F1 /* CheckerManager.cpp */; }; - BBA5ABBC1309C2FA000B38F1 /* CoreEngine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB5F1309C2FA000B38F1 /* CoreEngine.cpp */; }; - BBA5ABBD1309C2FA000B38F1 /* CXXExprEngine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB601309C2FA000B38F1 /* CXXExprEngine.cpp */; }; - BBA5ABBE1309C2FA000B38F1 /* Environment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB611309C2FA000B38F1 /* Environment.cpp */; }; - BBA5ABBF1309C2FA000B38F1 /* ExplodedGraph.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB621309C2FA000B38F1 /* ExplodedGraph.cpp */; }; - BBA5ABC01309C2FA000B38F1 /* FlatStore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB631309C2FA000B38F1 /* FlatStore.cpp */; }; - BBA5ABC11309C2FA000B38F1 /* GRState.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB641309C2FA000B38F1 /* GRState.cpp */; }; - BBA5ABC21309C2FA000B38F1 /* HTMLDiagnostics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB651309C2FA000B38F1 /* HTMLDiagnostics.cpp */; }; - BBA5ABC41309C2FA000B38F1 /* MemRegion.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB671309C2FA000B38F1 /* MemRegion.cpp */; }; - BBA5ABC51309C2FA000B38F1 /* ObjCMessage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB681309C2FA000B38F1 /* ObjCMessage.cpp */; }; - BBA5ABC61309C2FA000B38F1 /* PathDiagnostic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB691309C2FA000B38F1 /* PathDiagnostic.cpp */; }; - BBA5ABC71309C2FA000B38F1 /* PlistDiagnostics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB6A1309C2FA000B38F1 /* PlistDiagnostics.cpp */; }; - BBA5ABC81309C2FA000B38F1 /* RangeConstraintManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB6B1309C2FA000B38F1 /* RangeConstraintManager.cpp */; }; - BBA5ABC91309C2FA000B38F1 /* RegionStore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB6C1309C2FA000B38F1 /* RegionStore.cpp */; }; - BBA5ABCA1309C2FA000B38F1 /* SimpleConstraintManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB6D1309C2FA000B38F1 /* SimpleConstraintManager.cpp */; }; - BBA5ABCB1309C2FA000B38F1 /* SimpleSValBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB6F1309C2FA000B38F1 /* SimpleSValBuilder.cpp */; }; - BBA5ABCC1309C2FA000B38F1 /* Store.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB701309C2FA000B38F1 /* Store.cpp */; }; - BBA5ABCD1309C2FA000B38F1 /* SValBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB711309C2FA000B38F1 /* SValBuilder.cpp */; }; - BBA5ABCE1309C2FA000B38F1 /* SVals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB721309C2FA000B38F1 /* SVals.cpp */; }; - BBA5ABCF1309C2FA000B38F1 /* SymbolManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB731309C2FA000B38F1 /* SymbolManager.cpp */; }; - BBA5ABD01309C2FA000B38F1 /* TextPathDiagnostics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB741309C2FA000B38F1 /* TextPathDiagnostics.cpp */; }; - BBA5ABD11309C2FA000B38F1 /* AnalysisConsumer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB761309C2FA000B38F1 /* AnalysisConsumer.cpp */; }; - BBA5ABD21309C2FA000B38F1 /* CheckerRegistration.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB781309C2FA000B38F1 /* CheckerRegistration.cpp */; }; - BBA5ABD31309C2FA000B38F1 /* FrontendActions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBA5AB7A1309C2FA000B38F1 /* FrontendActions.cpp */; }; - BDF87CF70FD746F300BBF872 /* SemaTemplateDeduction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BDF87CF60FD746F300BBF872 /* SemaTemplateDeduction.cpp */; }; - BF89C3E211595818001C2D68 /* AnalysisBasedWarnings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BF89C3E111595818001C2D68 /* AnalysisBasedWarnings.cpp */; }; - BF89C3E91159594A001C2D68 /* SemaObjCProperty.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BF89C3E81159594A001C2D68 /* SemaObjCProperty.cpp */; }; - BF89C3F911595A01001C2D68 /* SemaType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BF89C3F811595A01001C2D68 /* SemaType.cpp */; }; - BF89C3FB11595A37001C2D68 /* SemaCodeComplete.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BF89C3FA11595A37001C2D68 /* SemaCodeComplete.cpp */; }; - BF89C3FD11595A5D001C2D68 /* SemaExceptionSpec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BF89C3FC11595A5D001C2D68 /* SemaExceptionSpec.cpp */; }; - BF9FEDFB1225E6A9003A8B71 /* AttributeList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BF9FEDFA1225E6A9003A8B71 /* AttributeList.cpp */; }; - BF9FEDFD1225E6C6003A8B71 /* DeclSpec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BF9FEDFC1225E6C6003A8B71 /* DeclSpec.cpp */; }; - BF9FEDFF1225E6DD003A8B71 /* TargetAttributesSema.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BF9FEDFE1225E6DD003A8B71 /* TargetAttributesSema.cpp */; }; - BF9FEE021225E73F003A8B71 /* ExprClassification.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BF9FEE011225E73F003A8B71 /* ExprClassification.cpp */; }; - BF9FEE041225E759003A8B71 /* ItaniumCXXABI.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BF9FEE031225E759003A8B71 /* ItaniumCXXABI.cpp */; }; - BF9FEE061225E770003A8B71 /* MicrosoftCXXABI.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BF9FEE051225E770003A8B71 /* MicrosoftCXXABI.cpp */; }; - BF9FEE2C1225E7EA003A8B71 /* BackendUtil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BF9FEE2B1225E7EA003A8B71 /* BackendUtil.cpp */; }; - BF9FEE311225E86C003A8B71 /* CodeGenAction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BF9FEE301225E86C003A8B71 /* CodeGenAction.cpp */; }; - BF9FEE331225E898003A8B71 /* ItaniumCXXABI.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BF9FEE321225E898003A8B71 /* ItaniumCXXABI.cpp */; }; - BF9FEE351225E8B1003A8B71 /* MicrosoftCXXABI.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BF9FEE341225E8B1003A8B71 /* MicrosoftCXXABI.cpp */; }; - BF9FEE381225E925003A8B71 /* BoostConAction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BF9FEE371225E925003A8B71 /* BoostConAction.cpp */; }; - BF9FEE521226FE9F003A8B71 /* ParseAST.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BF9FEE511226FE9F003A8B71 /* ParseAST.cpp */; }; - BF9FEEF2122D8068003A8B71 /* PreprocessingRecord.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BF9FEEF1122D8068003A8B71 /* PreprocessingRecord.cpp */; }; - BFE2F6C111DA955A0007EDC0 /* DeltaTree.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFE2F69311DA955A0007EDC0 /* DeltaTree.cpp */; }; - BFE2F6C211DA955A0007EDC0 /* FixItRewriter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFE2F69411DA955A0007EDC0 /* FixItRewriter.cpp */; }; - BFE2F6C311DA955A0007EDC0 /* FrontendActions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFE2F69511DA955A0007EDC0 /* FrontendActions.cpp */; }; - BFE2F6C411DA955A0007EDC0 /* HTMLPrint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFE2F69611DA955A0007EDC0 /* HTMLPrint.cpp */; }; - BFE2F6C511DA955A0007EDC0 /* HTMLRewrite.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFE2F69711DA955A0007EDC0 /* HTMLRewrite.cpp */; }; - BFE2F6D111DA955A0007EDC0 /* RewriteMacros.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFE2F6A511DA955A0007EDC0 /* RewriteMacros.cpp */; }; - BFE2F6D211DA955A0007EDC0 /* RewriteObjC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFE2F6A611DA955A0007EDC0 /* RewriteObjC.cpp */; }; - BFE2F6D311DA955A0007EDC0 /* Rewriter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFE2F6A711DA955A0007EDC0 /* Rewriter.cpp */; }; - BFE2F6D411DA955A0007EDC0 /* RewriteRope.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFE2F6A811DA955A0007EDC0 /* RewriteRope.cpp */; }; - BFE2F6D511DA955A0007EDC0 /* RewriteTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFE2F6A911DA955A0007EDC0 /* RewriteTest.cpp */; }; - BFE2F6D611DA955A0007EDC0 /* TokenRewriter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFE2F6AA11DA955A0007EDC0 /* TokenRewriter.cpp */; }; - DE01DA490B12ADA300AC22CE /* PPCallbacks.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE01DA480B12ADA300AC22CE /* PPCallbacks.h */; }; - DE06756C0C051CFE00EBBFD8 /* ParseExprCXX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE06756B0C051CFE00EBBFD8 /* ParseExprCXX.cpp */; }; - DE06B73E0A8307640050E87E /* LangOptions.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE06B73D0A8307640050E87E /* LangOptions.h */; }; - DE06D4310A8BB52D0050E87E /* Parser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE06D42F0A8BB52D0050E87E /* Parser.cpp */; }; - DE0FCA630A95859D00248FD5 /* Expr.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE0FCA620A95859D00248FD5 /* Expr.h */; }; - DE1F22030A7D852A00FBF588 /* Parser.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE1F22020A7D852A00FBF588 /* Parser.h */; }; - DE224FF80C7AA98800D370A5 /* CGExprComplex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE224FF70C7AA98800D370A5 /* CGExprComplex.cpp */; }; - DE2252700C7E82D000D370A5 /* CGExprScalar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE22526F0C7E82D000D370A5 /* CGExprScalar.cpp */; }; - DE2255FC0C8004E600D370A5 /* ParseDeclCXX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE2255FB0C8004E600D370A5 /* ParseDeclCXX.cpp */; }; - DE22BCF20E14197E0094DC60 /* SemaDeclAttr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE22BCF10E14197E0094DC60 /* SemaDeclAttr.cpp */; }; - DE344AB80AE5DF6D00DBC861 /* HeaderSearch.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE344AB70AE5DF6D00DBC861 /* HeaderSearch.h */; }; - DE344B540AE5E46C00DBC861 /* HeaderSearch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE344B530AE5E46C00DBC861 /* HeaderSearch.cpp */; }; - DE3450D70AEB543100DBC861 /* DirectoryLookup.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE3450D60AEB543100DBC861 /* DirectoryLookup.h */; }; - DE3452810AEF1B1800DBC861 /* Stmt.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE3452800AEF1B1800DBC861 /* Stmt.h */; }; - DE345C1A0AFC658B00DBC861 /* StmtVisitor.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE345C190AFC658B00DBC861 /* StmtVisitor.h */; }; - DE3460000AFDCC1900DBC861 /* ParseObjc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE345FFF0AFDCC1900DBC861 /* ParseObjc.cpp */; }; - DE3460050AFDCC6500DBC861 /* ParseInit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE3460040AFDCC6500DBC861 /* ParseInit.cpp */; }; - DE34600B0AFDCCBF00DBC861 /* ParseStmt.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE34600A0AFDCCBF00DBC861 /* ParseStmt.cpp */; }; - DE34600F0AFDCCCE00DBC861 /* ParseDecl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE34600E0AFDCCCE00DBC861 /* ParseDecl.cpp */; }; - DE3460130AFDCCDA00DBC861 /* ParseExpr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE3460120AFDCCDA00DBC861 /* ParseExpr.cpp */; }; - DE3464220B03040900DBC861 /* Type.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE3464210B03040900DBC861 /* Type.h */; }; - DE37252E0FE481AD00CF2CC2 /* Builtins.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE37252D0FE481AD00CF2CC2 /* Builtins.cpp */; }; - DE38CD500D794D0100A273B6 /* CGObjCGNU.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE38CD4F0D794D0100A273B6 /* CGObjCGNU.cpp */; }; - DE3986F00CB8D4B300223765 /* IdentifierTable.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE3986EF0CB8D4B300223765 /* IdentifierTable.h */; }; - DE3986F40CB8D50C00223765 /* IdentifierTable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE3986F30CB8D50C00223765 /* IdentifierTable.cpp */; }; - DE4264FC0C113592005A861D /* CGDecl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE4264FB0C113592005A861D /* CGDecl.cpp */; }; - DE46BF280AE0A82D00CC047C /* TargetInfo.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE46BF270AE0A82D00CC047C /* TargetInfo.h */; }; - DE4772FA0C10EAE5002239E8 /* CGStmt.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE4772F90C10EAE5002239E8 /* CGStmt.cpp */; }; - DE4772FC0C10EAEC002239E8 /* CGExpr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE4772FB0C10EAEC002239E8 /* CGExpr.cpp */; }; - DE47999C0D2EBE1A00706D2D /* SemaExprObjC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE47999B0D2EBE1A00706D2D /* SemaExprObjC.cpp */; }; - DE4DC7A30EA1C33E00069E5A /* TokenRewriter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE4DC7A20EA1C33E00069E5A /* TokenRewriter.cpp */; }; - DE67E70D0C020ECA00F66BC5 /* SemaStmt.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE67E70C0C020ECA00F66BC5 /* SemaStmt.cpp */; }; - DE67E70F0C020ECF00F66BC5 /* SemaExprCXX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE67E70E0C020ECF00F66BC5 /* SemaExprCXX.cpp */; }; - DE67E7110C020ED400F66BC5 /* SemaExpr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE67E7100C020ED400F66BC5 /* SemaExpr.cpp */; }; - DE67E7130C020ED900F66BC5 /* SemaDecl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE67E7120C020ED900F66BC5 /* SemaDecl.cpp */; }; - DE67E7170C020EE400F66BC5 /* Sema.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE67E7160C020EE400F66BC5 /* Sema.cpp */; }; - DE6951C70C4D1F5D00A5826B /* RecordLayout.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE6951C60C4D1F5D00A5826B /* RecordLayout.h */; }; - DE6954640C5121BD00A5826B /* Token.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE6954630C5121BD00A5826B /* Token.h */; }; - DE704B260D0FBEBE009C7762 /* SemaDeclObjC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE704B250D0FBEBE009C7762 /* SemaDeclObjC.cpp */; }; - DE704DD20D1668A4009C7762 /* HeaderMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE704DD10D1668A4009C7762 /* HeaderMap.cpp */; }; - DE75ED290B044DC90020CF81 /* ASTContext.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE75ED280B044DC90020CF81 /* ASTContext.h */; }; - DE85CD810D8380B10070E26E /* TokenLexer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE85CD800D8380B10070E26E /* TokenLexer.cpp */; }; - DE85CDA30D8383B20070E26E /* MacroArgs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE85CDA20D8383B20070E26E /* MacroArgs.cpp */; }; - DE85CDAC0D838C120070E26E /* PPMacroExpansion.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE85CDAB0D838C120070E26E /* PPMacroExpansion.cpp */; }; - DE85CDB00D838C390070E26E /* PPDirectives.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE85CDAF0D838C390070E26E /* PPDirectives.cpp */; }; - DE85CDB60D839BAE0070E26E /* PPLexerChange.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE85CDB50D839BAE0070E26E /* PPLexerChange.cpp */; }; - DE928B130C05659200231DA4 /* ModuleBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE928B120C05659200231DA4 /* ModuleBuilder.cpp */; }; - DE928B200C0565B000231DA4 /* ModuleBuilder.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE928B1F0C0565B000231DA4 /* ModuleBuilder.h */; }; - DE928B7D0C0A615100231DA4 /* CodeGenModule.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE928B7C0C0A615100231DA4 /* CodeGenModule.h */; }; - DE928B7F0C0A615600231DA4 /* CodeGenModule.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE928B7E0C0A615600231DA4 /* CodeGenModule.cpp */; }; - DE928B810C0A615B00231DA4 /* CodeGenFunction.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE928B800C0A615B00231DA4 /* CodeGenFunction.h */; }; - DE928B830C0A616000231DA4 /* CodeGenFunction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE928B820C0A616000231DA4 /* CodeGenFunction.cpp */; }; - DEAEE98B0A5A2B970045101B /* MultipleIncludeOpt.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DEAEE98A0A5A2B970045101B /* MultipleIncludeOpt.h */; }; - DEAEED4B0A5AF89A0045101B /* NOTES.txt in CopyFiles */ = {isa = PBXBuildFile; fileRef = DEAEED4A0A5AF89A0045101B /* NOTES.txt */; }; - DEB077990F44F97800F5A2BE /* TokenConcatenation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DEB077980F44F97800F5A2BE /* TokenConcatenation.cpp */; }; - DEB07AC80F4A427E00F5A2BE /* SemaAttr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DEB07AC70F4A427E00F5A2BE /* SemaAttr.cpp */; }; - DEC8D9910A9433CD00353FCA /* Decl.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DEC8D9900A9433CD00353FCA /* Decl.h */; }; - DEC8D9A40A94346E00353FCA /* AST.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DEC8D9A30A94346E00353FCA /* AST.h */; }; - DECAB0D00DB3C84200E13CCB /* RewriteRope.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DECAB0CF0DB3C84200E13CCB /* RewriteRope.cpp */; }; - DECB6D650F9AE26600F5FBC7 /* JumpDiagnostics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DECB6D640F9AE26600F5FBC7 /* JumpDiagnostics.cpp */; }; - DECB6F070F9D93A800F5FBC7 /* InitPreprocessor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DECB6F060F9D93A800F5FBC7 /* InitPreprocessor.cpp */; }; - DED626C90AE0C065001E80A4 /* TargetInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DED626C80AE0C065001E80A4 /* TargetInfo.cpp */; }; - DED7D7410A524295003AD0FB /* Diagnostic.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DED7D7310A524295003AD0FB /* Diagnostic.h */; }; - DED7D7430A524295003AD0FB /* FileManager.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DED7D7330A524295003AD0FB /* FileManager.h */; }; - DED7D7450A524295003AD0FB /* SourceLocation.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DED7D7350A524295003AD0FB /* SourceLocation.h */; }; - DED7D7460A524295003AD0FB /* SourceManager.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DED7D7360A524295003AD0FB /* SourceManager.h */; }; - DED7D7470A524295003AD0FB /* TokenKinds.def in CopyFiles */ = {isa = PBXBuildFile; fileRef = DED7D7370A524295003AD0FB /* TokenKinds.def */; }; - DED7D7480A524295003AD0FB /* TokenKinds.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DED7D7380A524295003AD0FB /* TokenKinds.h */; }; - DED7D74A0A524295003AD0FB /* Lexer.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DED7D73B0A524295003AD0FB /* Lexer.h */; }; - DED7D74D0A524295003AD0FB /* MacroInfo.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DED7D73E0A524295003AD0FB /* MacroInfo.h */; }; - DED7D74E0A524295003AD0FB /* Pragma.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DED7D73F0A524295003AD0FB /* Pragma.h */; }; - DED7D74F0A524295003AD0FB /* Preprocessor.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DED7D7400A524295003AD0FB /* Preprocessor.h */; }; - DED7D77A0A5242C7003AD0FB /* Diagnostic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DED7D75D0A5242C7003AD0FB /* Diagnostic.cpp */; }; - DED7D77B0A5242C7003AD0FB /* FileManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DED7D75E0A5242C7003AD0FB /* FileManager.cpp */; }; - DED7D7890A5242C7003AD0FB /* SourceManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DED7D76D0A5242C7003AD0FB /* SourceManager.cpp */; }; - DED7D78A0A5242C7003AD0FB /* TokenKinds.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DED7D76E0A5242C7003AD0FB /* TokenKinds.cpp */; }; - DED7D7C30A5242E6003AD0FB /* Lexer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DED7D79E0A5242E6003AD0FB /* Lexer.cpp */; }; - DED7D7C50A5242E6003AD0FB /* MacroInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DED7D7A00A5242E6003AD0FB /* MacroInfo.cpp */; }; - DED7D7C70A5242E6003AD0FB /* PPExpressions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DED7D7A20A5242E6003AD0FB /* PPExpressions.cpp */; }; - DED7D7C80A5242E6003AD0FB /* Pragma.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DED7D7A30A5242E6003AD0FB /* Pragma.cpp */; }; - DED7D7C90A5242E6003AD0FB /* Preprocessor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DED7D7A40A5242E6003AD0FB /* Preprocessor.cpp */; }; - DED7D7D80A524302003AD0FB /* README.txt in CopyFiles */ = {isa = PBXBuildFile; fileRef = DED7D7D70A524302003AD0FB /* README.txt */; }; - DED7D9180A52518C003AD0FB /* ScratchBuffer.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DED7D9170A52518C003AD0FB /* ScratchBuffer.h */; }; - DED7D9E50A5257F6003AD0FB /* ScratchBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DED7D9E40A5257F6003AD0FB /* ScratchBuffer.cpp */; }; - DEDFE6460F7B3B4E0035BD10 /* driver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DEDFE6450F7B3B4E0035BD10 /* driver.cpp */; }; - DEDFE65A0F7B3B830035BD10 /* Types.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DEDFE6480F7B3B830035BD10 /* Types.cpp */; }; - DEDFE65B0F7B3B830035BD10 /* Tools.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DEDFE64A0F7B3B830035BD10 /* Tools.cpp */; }; - DEDFE65C0F7B3B830035BD10 /* Compilation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DEDFE64C0F7B3B830035BD10 /* Compilation.cpp */; }; - DEDFE65D0F7B3B830035BD10 /* ArgList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DEDFE64D0F7B3B830035BD10 /* ArgList.cpp */; }; - DEDFE65E0F7B3B830035BD10 /* Arg.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DEDFE64E0F7B3B830035BD10 /* Arg.cpp */; }; - DEDFE65F0F7B3B830035BD10 /* Action.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DEDFE64F0F7B3B830035BD10 /* Action.cpp */; }; - DEDFE6600F7B3B830035BD10 /* Phases.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DEDFE6500F7B3B830035BD10 /* Phases.cpp */; }; - DEDFE6610F7B3B830035BD10 /* OptTable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DEDFE6510F7B3B830035BD10 /* OptTable.cpp */; }; - DEDFE6620F7B3B830035BD10 /* Option.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DEDFE6520F7B3B830035BD10 /* Option.cpp */; }; - DEDFE6630F7B3B830035BD10 /* Job.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DEDFE6530F7B3B830035BD10 /* Job.cpp */; }; - DEDFE6640F7B3B830035BD10 /* ToolChains.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DEDFE6550F7B3B830035BD10 /* ToolChains.cpp */; }; - DEDFE6650F7B3B830035BD10 /* ToolChain.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DEDFE6560F7B3B830035BD10 /* ToolChain.cpp */; }; - DEDFE6660F7B3B830035BD10 /* Tool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DEDFE6570F7B3B830035BD10 /* Tool.cpp */; }; - DEDFE6670F7B3B830035BD10 /* HostInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DEDFE6580F7B3B830035BD10 /* HostInfo.cpp */; }; - DEDFE6680F7B3B830035BD10 /* Driver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DEDFE6590F7B3B830035BD10 /* Driver.cpp */; }; - DEEBBD440C19C5D200A9FE82 /* TODO.txt in CopyFiles */ = {isa = PBXBuildFile; fileRef = DEEBBD430C19C5D200A9FE82 /* TODO.txt */; }; - DEEBC3BA0C2363B800A9FE82 /* CodeGenTypes.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DEEBC3B90C2363B800A9FE82 /* CodeGenTypes.h */; }; - DEEBC3BC0C2363BC00A9FE82 /* CodeGenTypes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DEEBC3BB0C2363BC00A9FE82 /* CodeGenTypes.cpp */; }; - DEF2E95F0C5FBD74000C4259 /* InternalsManual.html in CopyFiles */ = {isa = PBXBuildFile; fileRef = DEF2E95E0C5FBD74000C4259 /* InternalsManual.html */; }; - DEF2EFF30C6CDD74000C4259 /* CGExprAgg.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DEF2EFF20C6CDD74000C4259 /* CGExprAgg.cpp */; }; - DEF2F0100C6CFED5000C4259 /* SemaChecking.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DEF2F00F0C6CFED5000C4259 /* SemaChecking.cpp */; }; - DEF7D9F70C9C8B1A0001F598 /* Rewriter.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DEF7D9F60C9C8B1A0001F598 /* Rewriter.h */; }; - DEF7D9F90C9C8B1D0001F598 /* Rewriter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DEF7D9F80C9C8B1D0001F598 /* Rewriter.cpp */; }; - DEFFECA70DB1546600B4E7C3 /* DeltaTree.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DEFFECA60DB1546600B4E7C3 /* DeltaTree.cpp */; }; - E16B523510D30B2400430AC9 /* cc1_main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E16B523410D30B2400430AC9 /* cc1_main.cpp */; }; -/* End PBXBuildFile section */ - /* Begin PBXCopyFilesBuildPhase section */ 8DD76F690486A84900D96B5E /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; @@ -461,46 +13,6 @@ dstPath = /usr/share/man/man1/; dstSubfolderSpec = 0; files = ( - DED7D7410A524295003AD0FB /* Diagnostic.h in CopyFiles */, - DED7D7430A524295003AD0FB /* FileManager.h in CopyFiles */, - DED7D7450A524295003AD0FB /* SourceLocation.h in CopyFiles */, - DED7D7460A524295003AD0FB /* SourceManager.h in CopyFiles */, - DED7D7470A524295003AD0FB /* TokenKinds.def in CopyFiles */, - DED7D7480A524295003AD0FB /* TokenKinds.h in CopyFiles */, - DED7D74A0A524295003AD0FB /* Lexer.h in CopyFiles */, - DED7D74D0A524295003AD0FB /* MacroInfo.h in CopyFiles */, - DED7D74E0A524295003AD0FB /* Pragma.h in CopyFiles */, - DED7D74F0A524295003AD0FB /* Preprocessor.h in CopyFiles */, - DED7D7D80A524302003AD0FB /* README.txt in CopyFiles */, - DED7D9180A52518C003AD0FB /* ScratchBuffer.h in CopyFiles */, - DEAEE98B0A5A2B970045101B /* MultipleIncludeOpt.h in CopyFiles */, - DEAEED4B0A5AF89A0045101B /* NOTES.txt in CopyFiles */, - DE1F22030A7D852A00FBF588 /* Parser.h in CopyFiles */, - DE06B73E0A8307640050E87E /* LangOptions.h in CopyFiles */, - DEC8D9910A9433CD00353FCA /* Decl.h in CopyFiles */, - DEC8D9A40A94346E00353FCA /* AST.h in CopyFiles */, - DE0FCA630A95859D00248FD5 /* Expr.h in CopyFiles */, - DE46BF280AE0A82D00CC047C /* TargetInfo.h in CopyFiles */, - DE344AB80AE5DF6D00DBC861 /* HeaderSearch.h in CopyFiles */, - DE3450D70AEB543100DBC861 /* DirectoryLookup.h in CopyFiles */, - DE3452810AEF1B1800DBC861 /* Stmt.h in CopyFiles */, - DE345C1A0AFC658B00DBC861 /* StmtVisitor.h in CopyFiles */, - DE3464220B03040900DBC861 /* Type.h in CopyFiles */, - DE75ED290B044DC90020CF81 /* ASTContext.h in CopyFiles */, - DE01DA490B12ADA300AC22CE /* PPCallbacks.h in CopyFiles */, - 1A30A9E90B93A4C800201A91 /* ExprCXX.h in CopyFiles */, - 1A869A700BA2164C008DA07A /* LiteralSupport.h in CopyFiles */, - DE928B200C0565B000231DA4 /* ModuleBuilder.h in CopyFiles */, - DE928B7D0C0A615100231DA4 /* CodeGenModule.h in CopyFiles */, - DE928B810C0A615B00231DA4 /* CodeGenFunction.h in CopyFiles */, - DEEBBD440C19C5D200A9FE82 /* TODO.txt in CopyFiles */, - DEEBC3BA0C2363B800A9FE82 /* CodeGenTypes.h in CopyFiles */, - DE6951C70C4D1F5D00A5826B /* RecordLayout.h in CopyFiles */, - DE6954640C5121BD00A5826B /* Token.h in CopyFiles */, - DEF2E95F0C5FBD74000C4259 /* InternalsManual.html in CopyFiles */, - DEF7D9F70C9C8B1A0001F598 /* Rewriter.h in CopyFiles */, - 84AF36A10CB17A3B00C820A5 /* DeclObjC.h in CopyFiles */, - DE3986F00CB8D4B300223765 /* IdentifierTable.h in CopyFiles */, ); runOnlyForDeploymentPostprocessing = 1; }; @@ -2388,411 +1900,6 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - DED7D77A0A5242C7003AD0FB /* Diagnostic.cpp in Sources */, - DED7D77B0A5242C7003AD0FB /* FileManager.cpp in Sources */, - DED7D7890A5242C7003AD0FB /* SourceManager.cpp in Sources */, - DED7D78A0A5242C7003AD0FB /* TokenKinds.cpp in Sources */, - DED7D7C30A5242E6003AD0FB /* Lexer.cpp in Sources */, - DED7D7C50A5242E6003AD0FB /* MacroInfo.cpp in Sources */, - DED7D7C70A5242E6003AD0FB /* PPExpressions.cpp in Sources */, - DED7D7C80A5242E6003AD0FB /* Pragma.cpp in Sources */, - DED7D7C90A5242E6003AD0FB /* Preprocessor.cpp in Sources */, - DED7D9E50A5257F6003AD0FB /* ScratchBuffer.cpp in Sources */, - DE06D4310A8BB52D0050E87E /* Parser.cpp in Sources */, - DED626C90AE0C065001E80A4 /* TargetInfo.cpp in Sources */, - DE344B540AE5E46C00DBC861 /* HeaderSearch.cpp in Sources */, - DE3460000AFDCC1900DBC861 /* ParseObjc.cpp in Sources */, - DE3460050AFDCC6500DBC861 /* ParseInit.cpp in Sources */, - DE34600B0AFDCCBF00DBC861 /* ParseStmt.cpp in Sources */, - DE34600F0AFDCCCE00DBC861 /* ParseDecl.cpp in Sources */, - DE3460130AFDCCDA00DBC861 /* ParseExpr.cpp in Sources */, - 1A869AA80BA21ABA008DA07A /* LiteralSupport.cpp in Sources */, - DE67E70D0C020ECA00F66BC5 /* SemaStmt.cpp in Sources */, - DE67E70F0C020ECF00F66BC5 /* SemaExprCXX.cpp in Sources */, - DE67E7110C020ED400F66BC5 /* SemaExpr.cpp in Sources */, - DE67E7130C020ED900F66BC5 /* SemaDecl.cpp in Sources */, - DE67E7170C020EE400F66BC5 /* Sema.cpp in Sources */, - DE06756C0C051CFE00EBBFD8 /* ParseExprCXX.cpp in Sources */, - DE928B130C05659200231DA4 /* ModuleBuilder.cpp in Sources */, - DE928B7F0C0A615600231DA4 /* CodeGenModule.cpp in Sources */, - DE928B830C0A616000231DA4 /* CodeGenFunction.cpp in Sources */, - DE4772FA0C10EAE5002239E8 /* CGStmt.cpp in Sources */, - DE4772FC0C10EAEC002239E8 /* CGExpr.cpp in Sources */, - DE4264FC0C113592005A861D /* CGDecl.cpp in Sources */, - DEEBC3BC0C2363BC00A9FE82 /* CodeGenTypes.cpp in Sources */, - DEF2EFF30C6CDD74000C4259 /* CGExprAgg.cpp in Sources */, - DEF2F0100C6CFED5000C4259 /* SemaChecking.cpp in Sources */, - 1ABC36940C7A4BDC006DB0AB /* CGBuiltin.cpp in Sources */, - DE224FF80C7AA98800D370A5 /* CGExprComplex.cpp in Sources */, - 1A7342480C7B57D500122F56 /* CGObjC.cpp in Sources */, - DE2252700C7E82D000D370A5 /* CGExprScalar.cpp in Sources */, - DE2255FC0C8004E600D370A5 /* ParseDeclCXX.cpp in Sources */, - DEF7D9F90C9C8B1D0001F598 /* Rewriter.cpp in Sources */, - DE3986F40CB8D50C00223765 /* IdentifierTable.cpp in Sources */, - 35707EFE0CD0F5CC000B2204 /* SourceLocation.cpp in Sources */, - DE704B260D0FBEBE009C7762 /* SemaDeclObjC.cpp in Sources */, - DE704DD20D1668A4009C7762 /* HeaderMap.cpp in Sources */, - DE47999C0D2EBE1A00706D2D /* SemaExprObjC.cpp in Sources */, - 03F50AC60D416EAA00B9CF60 /* Targets.cpp in Sources */, - 1A376A2D0D4AED9B002A1C52 /* CGExprConstant.cpp in Sources */, - DE38CD500D794D0100A273B6 /* CGObjCGNU.cpp in Sources */, - DE85CD810D8380B10070E26E /* TokenLexer.cpp in Sources */, - DE85CDA30D8383B20070E26E /* MacroArgs.cpp in Sources */, - DE85CDAC0D838C120070E26E /* PPMacroExpansion.cpp in Sources */, - DE85CDB00D838C390070E26E /* PPDirectives.cpp in Sources */, - DE85CDB60D839BAE0070E26E /* PPLexerChange.cpp in Sources */, - 72D16C1F0D9975C400E6DA4A /* HTMLRewrite.cpp in Sources */, - 35EF67700DAD1D2C00B19414 /* SemaDeclCXX.cpp in Sources */, - 352712510DAFE54700C76352 /* IdentifierResolver.cpp in Sources */, - DEFFECA70DB1546600B4E7C3 /* DeltaTree.cpp in Sources */, - DECAB0D00DB3C84200E13CCB /* RewriteRope.cpp in Sources */, - 35A3E7020DD3874400757F74 /* CGDebugInfo.cpp in Sources */, - 3599299B0DE2425300A8A33E /* SemaInit.cpp in Sources */, - 3534A01D0E129849002709B2 /* ParseCXXInlineMethods.cpp in Sources */, - DE22BCF20E14197E0094DC60 /* SemaDeclAttr.cpp in Sources */, - 3552E7550E520D80003A8CA5 /* PPCaching.cpp in Sources */, - 3552E7590E520DD7003A8CA5 /* CGObjCMac.cpp in Sources */, - 1A5D5E580E5E81010023C059 /* CGCXX.cpp in Sources */, - 35475B200E79973F0000BFE4 /* CGCall.cpp in Sources */, - 3551068C0E9A8546006A4E44 /* ParsePragma.cpp in Sources */, - 3551068D0E9A8546006A4E44 /* ParseTentative.cpp in Sources */, - DE4DC7A30EA1C33E00069E5A /* TokenRewriter.cpp in Sources */, - 35585DC00EAFBC4500D0A97A /* SemaOverload.cpp in Sources */, - 35E194690ECB82FB00F21733 /* SemaCXXScopeSpec.cpp in Sources */, - 35E1946A0ECB82FB00F21733 /* SemaCXXCast.cpp in Sources */, - 35E1946D0ECB83C100F21733 /* PTHLexer.cpp in Sources */, - 3537AA0E0ECD08A4008F7CDC /* PreprocessorLexer.cpp in Sources */, - 353959D50EE5F88A00E82461 /* ParseTemplate.cpp in Sources */, - 3591853F0EFB1088000039AF /* SemaTemplate.cpp in Sources */, - 357EA27D0F2526F300439B60 /* SemaLookup.cpp in Sources */, - 1A471AB50F437BC500753CE8 /* CGBlocks.cpp in Sources */, - DEB077990F44F97800F5A2BE /* TokenConcatenation.cpp in Sources */, - 1A2193CE0F45EEB700C0713D /* Mangle.cpp in Sources */, - DEB07AC80F4A427E00F5A2BE /* SemaAttr.cpp in Sources */, - 352246E80F5C6BE000D0D279 /* InitHeaderSearch.cpp in Sources */, - 352246EB0F5C6BE000D0D279 /* TextDiagnosticBuffer.cpp in Sources */, - 352246EC0F5C6BE000D0D279 /* TextDiagnosticPrinter.cpp in Sources */, - 35544B8C0F5C803200D92AA9 /* SemaTemplateInstantiate.cpp in Sources */, - 1ADF47AF0F782C3200E48A8A /* SemaTemplateInstantiateDecl.cpp in Sources */, - DEDFE6460F7B3B4E0035BD10 /* driver.cpp in Sources */, - DEDFE65A0F7B3B830035BD10 /* Types.cpp in Sources */, - DEDFE65B0F7B3B830035BD10 /* Tools.cpp in Sources */, - DEDFE65C0F7B3B830035BD10 /* Compilation.cpp in Sources */, - DEDFE65D0F7B3B830035BD10 /* ArgList.cpp in Sources */, - DEDFE65E0F7B3B830035BD10 /* Arg.cpp in Sources */, - DEDFE65F0F7B3B830035BD10 /* Action.cpp in Sources */, - DEDFE6600F7B3B830035BD10 /* Phases.cpp in Sources */, - DEDFE6610F7B3B830035BD10 /* OptTable.cpp in Sources */, - DEDFE6620F7B3B830035BD10 /* Option.cpp in Sources */, - DEDFE6630F7B3B830035BD10 /* Job.cpp in Sources */, - DEDFE6640F7B3B830035BD10 /* ToolChains.cpp in Sources */, - DEDFE6650F7B3B830035BD10 /* ToolChain.cpp in Sources */, - DEDFE6660F7B3B830035BD10 /* Tool.cpp in Sources */, - DEDFE6670F7B3B830035BD10 /* HostInfo.cpp in Sources */, - DEDFE6680F7B3B830035BD10 /* Driver.cpp in Sources */, - 1A701B640F7C8FE400FEC4D1 /* SemaAccess.cpp in Sources */, - 906BF4B00F83BA2E001071FA /* ConvertUTF.c in Sources */, - DECB6D650F9AE26600F5FBC7 /* JumpDiagnostics.cpp in Sources */, - DECB6F070F9D93A800F5FBC7 /* InitPreprocessor.cpp in Sources */, - 1A2A54B60FD1DD1C00F4CE45 /* ASTConsumers.cpp in Sources */, - 1A2A54B80FD1DD1C00F4CE45 /* CacheTokens.cpp in Sources */, - 1A2A54B90FD1DD1C00F4CE45 /* DependencyFile.cpp in Sources */, - 1A2A54BA0FD1DD1C00F4CE45 /* DiagChecker.cpp in Sources */, - 1A2A54BB0FD1DD1C00F4CE45 /* DocumentXML.cpp in Sources */, - 1A2A54BF0FD1DD1C00F4CE45 /* PrintPreprocessedOutput.cpp in Sources */, - 1A2A54C40FD1DD1C00F4CE45 /* StmtXML.cpp in Sources */, - 1A2A54C50FD1DD1C00F4CE45 /* Warnings.cpp in Sources */, - 1A6FE7090FD6F85800E00CA9 /* CGTemporaries.cpp in Sources */, - BDF87CF70FD746F300BBF872 /* SemaTemplateDeduction.cpp in Sources */, - DE37252E0FE481AD00CF2CC2 /* Builtins.cpp in Sources */, - 1AFF8AE31012BFC900D248DA /* CGRecordLayoutBuilder.cpp in Sources */, - 90FD6D7B103C3D49005F5B73 /* Analyzer.cpp in Sources */, - 90FD6D7C103C3D49005F5B73 /* ASTLocation.cpp in Sources */, - 90FD6D7D103C3D49005F5B73 /* DeclReferenceMap.cpp in Sources */, - 90FD6D7E103C3D49005F5B73 /* Entity.cpp in Sources */, - 90FD6D7F103C3D49005F5B73 /* GlobalSelector.cpp in Sources */, - 90FD6D80103C3D49005F5B73 /* Handlers.cpp in Sources */, - 90FD6D81103C3D49005F5B73 /* Indexer.cpp in Sources */, - 90FD6D82103C3D49005F5B73 /* IndexProvider.cpp in Sources */, - 90FD6D83103C3D49005F5B73 /* Program.cpp in Sources */, - 90FD6D85103C3D49005F5B73 /* SelectorMap.cpp in Sources */, - 90FD6DB6103D977E005F5B73 /* index-test.cpp in Sources */, - 9012911D1048068D0083456D /* ASTUnit.cpp in Sources */, - 90129121104812F90083456D /* CIndex.cpp in Sources */, - 90F9EFAA104ABDED00D09A15 /* c-index-test.c in Sources */, - 1A4C41BF105B4C0B0047B5E7 /* CGClass.cpp in Sources */, - 1A6B6CD410693FC900BB4A8F /* CodeCompleteConsumer.cpp in Sources */, - 1A6B6CD510693FC900BB4A8F /* SemaCodeComplete.cpp in Sources */, - 1A6B6E9A1069833600BB4A8F /* CGExprCXX.cpp in Sources */, - 1A6C01F7108128710072DEE4 /* CGRTTI.cpp in Sources */, - 1A81AA19108144F40094E50B /* CGVTables.cpp in Sources */, - 1AF1B50F109A4FB800AFAFAC /* CGException.cpp in Sources */, - 1A986AB710D0746D00A8EA9E /* CGDeclCXX.cpp in Sources */, - E16B523510D30B2400430AC9 /* cc1_main.cpp in Sources */, - 1ACB57E41105820D0047B991 /* CompilerInstance.cpp in Sources */, - 1ACB57E51105820D0047B991 /* CompilerInvocation.cpp in Sources */, - 1ACB57E61105820D0047B991 /* DeclXML.cpp in Sources */, - 1ACB57E71105820D0047B991 /* FrontendAction.cpp in Sources */, - 1ACB57E81105820D0047B991 /* FrontendActions.cpp in Sources */, - 1ACB57E91105820D0047B991 /* FrontendOptions.cpp in Sources */, - 1ACB57EA1105820D0047B991 /* LangStandards.cpp in Sources */, - 1ACB57EB1105820D0047B991 /* TypeXML.cpp in Sources */, - 1ACB57EC1105820D0047B991 /* VerifyDiagnosticsClient.cpp in Sources */, - 1A97825B1108BA18002B98FC /* CGVTT.cpp in Sources */, - 1A621BB7110FE6AA009E6834 /* TargetInfo.cpp in Sources */, - 1A621C4211111D61009E6834 /* CIndexCodeCompletion.cpp in Sources */, - 1A621C4311111D61009E6834 /* CIndexer.cpp in Sources */, - 1A621C4411111D61009E6834 /* CIndexInclusionStack.cpp in Sources */, - 1A621C4511111D61009E6834 /* CIndexUSRs.cpp in Sources */, - 1A621C4611111D61009E6834 /* CXCursor.cpp in Sources */, - BF89C3E211595818001C2D68 /* AnalysisBasedWarnings.cpp in Sources */, - BF89C3E91159594A001C2D68 /* SemaObjCProperty.cpp in Sources */, - BF89C3F911595A01001C2D68 /* SemaType.cpp in Sources */, - BF89C3FB11595A37001C2D68 /* SemaCodeComplete.cpp in Sources */, - BF89C3FD11595A5D001C2D68 /* SemaExceptionSpec.cpp in Sources */, - 1AFDD8721161085D00AE030A /* ASTMerge.cpp in Sources */, - 1ABD23D61182449800A48E65 /* APValue.cpp in Sources */, - 1ABD23D71182449800A48E65 /* ASTConsumer.cpp in Sources */, - 1ABD23D81182449800A48E65 /* ASTContext.cpp in Sources */, - 1ABD23D91182449800A48E65 /* ASTDiagnostic.cpp in Sources */, - 1ABD23DA1182449800A48E65 /* ASTImporter.cpp in Sources */, - 1ABD23DB1182449800A48E65 /* AttrImpl.cpp in Sources */, - 1ABD23DC1182449800A48E65 /* CXXInheritance.cpp in Sources */, - 1ABD23DD1182449800A48E65 /* Decl.cpp in Sources */, - 1ABD23DE1182449800A48E65 /* DeclarationName.cpp in Sources */, - 1ABD23DF1182449800A48E65 /* DeclBase.cpp in Sources */, - 1ABD23E01182449800A48E65 /* DeclCXX.cpp in Sources */, - 1ABD23E11182449800A48E65 /* DeclFriend.cpp in Sources */, - 1ABD23E21182449800A48E65 /* DeclGroup.cpp in Sources */, - 1ABD23E31182449800A48E65 /* DeclObjC.cpp in Sources */, - 1ABD23E41182449800A48E65 /* DeclPrinter.cpp in Sources */, - 1ABD23E51182449800A48E65 /* DeclTemplate.cpp in Sources */, - 1ABD23E61182449800A48E65 /* Expr.cpp in Sources */, - 1ABD23E71182449800A48E65 /* ExprConstant.cpp in Sources */, - 1ABD23E81182449800A48E65 /* ExprCXX.cpp in Sources */, - 1ABD23E91182449800A48E65 /* FullExpr.cpp in Sources */, - 1ABD23EA1182449800A48E65 /* InheritViz.cpp in Sources */, - 1ABD23EB1182449800A48E65 /* NestedNameSpecifier.cpp in Sources */, - 1ABD23EC1182449800A48E65 /* ParentMap.cpp in Sources */, - 1ABD23ED1182449800A48E65 /* RecordLayout.cpp in Sources */, - 1ABD23EE1182449800A48E65 /* RecordLayoutBuilder.cpp in Sources */, - 1ABD23EF1182449800A48E65 /* Stmt.cpp in Sources */, - 1ABD23F01182449800A48E65 /* StmtDumper.cpp in Sources */, - 1ABD23F11182449800A48E65 /* StmtIterator.cpp in Sources */, - 1ABD23F21182449800A48E65 /* StmtPrinter.cpp in Sources */, - 1ABD23F31182449800A48E65 /* StmtProfile.cpp in Sources */, - 1ABD23F41182449800A48E65 /* StmtViz.cpp in Sources */, - 1ABD23F51182449800A48E65 /* TemplateBase.cpp in Sources */, - 1ABD23F61182449800A48E65 /* TemplateName.cpp in Sources */, - 1ABD23F71182449800A48E65 /* Type.cpp in Sources */, - 1ABD23F81182449800A48E65 /* TypeLoc.cpp in Sources */, - 1ABD23F91182449800A48E65 /* TypePrinter.cpp in Sources */, - BFE2F6C111DA955A0007EDC0 /* DeltaTree.cpp in Sources */, - BFE2F6C211DA955A0007EDC0 /* FixItRewriter.cpp in Sources */, - BFE2F6C311DA955A0007EDC0 /* FrontendActions.cpp in Sources */, - BFE2F6C411DA955A0007EDC0 /* HTMLPrint.cpp in Sources */, - BFE2F6C511DA955A0007EDC0 /* HTMLRewrite.cpp in Sources */, - BFE2F6D111DA955A0007EDC0 /* RewriteMacros.cpp in Sources */, - BFE2F6D211DA955A0007EDC0 /* RewriteObjC.cpp in Sources */, - BFE2F6D311DA955A0007EDC0 /* Rewriter.cpp in Sources */, - BFE2F6D411DA955A0007EDC0 /* RewriteRope.cpp in Sources */, - BFE2F6D511DA955A0007EDC0 /* RewriteTest.cpp in Sources */, - BFE2F6D611DA955A0007EDC0 /* TokenRewriter.cpp in Sources */, - 57F66612121B4DE600DCE3B7 /* ASTWriter.cpp in Sources */, - 57F66613121B4DE600DCE3B7 /* ASTWriterDecl.cpp in Sources */, - 57F66614121B4DE600DCE3B7 /* ASTWriterStmt.cpp in Sources */, - 57AA9250121C8B9400B4AA6C /* ASTReader.cpp in Sources */, - 57AA9251121C8B9400B4AA6C /* ASTReaderDecl.cpp in Sources */, - 57AA9252121C8B9400B4AA6C /* ASTReaderStmt.cpp in Sources */, - BF9FEDFB1225E6A9003A8B71 /* AttributeList.cpp in Sources */, - BF9FEDFD1225E6C6003A8B71 /* DeclSpec.cpp in Sources */, - BF9FEDFF1225E6DD003A8B71 /* TargetAttributesSema.cpp in Sources */, - BF9FEE021225E73F003A8B71 /* ExprClassification.cpp in Sources */, - BF9FEE041225E759003A8B71 /* ItaniumCXXABI.cpp in Sources */, - BF9FEE061225E770003A8B71 /* MicrosoftCXXABI.cpp in Sources */, - BF9FEE2C1225E7EA003A8B71 /* BackendUtil.cpp in Sources */, - BF9FEE311225E86C003A8B71 /* CodeGenAction.cpp in Sources */, - BF9FEE331225E898003A8B71 /* ItaniumCXXABI.cpp in Sources */, - BF9FEE351225E8B1003A8B71 /* MicrosoftCXXABI.cpp in Sources */, - BF9FEE381225E925003A8B71 /* BoostConAction.cpp in Sources */, - BF9FEE521226FE9F003A8B71 /* ParseAST.cpp in Sources */, - BF9FEEF2122D8068003A8B71 /* PreprocessingRecord.cpp in Sources */, - 1AC1A67D12999D8E006FBC77 /* AnalysisContext.cpp in Sources */, - 1AC1A67E12999D8E006FBC77 /* CFG.cpp in Sources */, - 1AC1A67F12999D8E006FBC77 /* CFGStmtMap.cpp in Sources */, - 1AC1A68012999D8E006FBC77 /* FormatString.cpp in Sources */, - 1AC1A68112999D8E006FBC77 /* LiveVariables.cpp in Sources */, - 1AC1A68212999D8E006FBC77 /* PrintfFormatString.cpp in Sources */, - 1AC1A68312999D8E006FBC77 /* PseudoConstantAnalysis.cpp in Sources */, - 1AC1A68412999D8E006FBC77 /* ReachableCode.cpp in Sources */, - 1AC1A68512999D8E006FBC77 /* ScanfFormatString.cpp in Sources */, - 1AC1A68612999D8E006FBC77 /* UninitializedValues.cpp in Sources */, - 1AC1A9EF1299A287006FBC77 /* AdjustedReturnValueChecker.cpp in Sources */, - 1AC1A9F01299A287006FBC77 /* AggExprVisitor.cpp in Sources */, - 1AC1A9F11299A287006FBC77 /* AnalysisConsumer.cpp in Sources */, - 1AC1A9F21299A287006FBC77 /* AnalysisManager.cpp in Sources */, - 1AC1A9F31299A287006FBC77 /* AnalyzerStatsChecker.cpp in Sources */, - 1AC1A9F41299A287006FBC77 /* ArrayBoundChecker.cpp in Sources */, - 1AC1A9F51299A287006FBC77 /* AttrNonNullChecker.cpp in Sources */, - 1AC1A9F61299A287006FBC77 /* BasicConstraintManager.cpp in Sources */, - 1AC1A9F71299A287006FBC77 /* BasicObjCFoundationChecks.cpp in Sources */, - 1AC1A9F81299A287006FBC77 /* BasicStore.cpp in Sources */, - 1AC1A9F91299A287006FBC77 /* BasicValueFactory.cpp in Sources */, - 1AC1A9FA1299A287006FBC77 /* BugReporter.cpp in Sources */, - 1AC1A9FB1299A287006FBC77 /* BugReporterVisitors.cpp in Sources */, - 1AC1A9FC1299A287006FBC77 /* BuiltinFunctionChecker.cpp in Sources */, - 1AC1A9FD1299A287006FBC77 /* CallAndMessageChecker.cpp in Sources */, - 1AC1A9FE1299A287006FBC77 /* CastSizeChecker.cpp in Sources */, - 1AC1A9FF1299A287006FBC77 /* CastToStructChecker.cpp in Sources */, - 1AC1AA001299A287006FBC77 /* CFRefCount.cpp in Sources */, - 1AC1AA011299A287006FBC77 /* CheckDeadStores.cpp in Sources */, - 1AC1AA021299A287006FBC77 /* Checker.cpp in Sources */, - 1AC1AA031299A287006FBC77 /* CheckerHelpers.cpp in Sources */, - 1AC1AA041299A287006FBC77 /* CheckObjCDealloc.cpp in Sources */, - 1AC1AA051299A287006FBC77 /* CheckObjCInstMethSignature.cpp in Sources */, - 1AC1AA061299A287006FBC77 /* CheckSecuritySyntaxOnly.cpp in Sources */, - 1AC1AA071299A287006FBC77 /* CheckSizeofPointer.cpp in Sources */, - 1AC1AA081299A287006FBC77 /* ChrootChecker.cpp in Sources */, - 1AC1AA091299A287006FBC77 /* CocoaConventions.cpp in Sources */, - 1AC1AA0A1299A287006FBC77 /* CStringChecker.cpp in Sources */, - 1AC1AB3D1299A287006FBC77 /* DereferenceChecker.cpp in Sources */, - 1AC1AB3E1299A287006FBC77 /* DivZeroChecker.cpp in Sources */, - 1AC1AB3F1299A287006FBC77 /* Environment.cpp in Sources */, - 1AC1AB401299A287006FBC77 /* ExplodedGraph.cpp in Sources */, - 1AC1AB411299A287006FBC77 /* FixedAddressChecker.cpp in Sources */, - 1AC1AB421299A287006FBC77 /* FlatStore.cpp in Sources */, - 1AC1AB431299A287006FBC77 /* FrontendActions.cpp in Sources */, - 1AC1AB441299A287006FBC77 /* GRBlockCounter.cpp in Sources */, - 1AC1AB451299A287006FBC77 /* GRCoreEngine.cpp in Sources */, - 1AC1AB461299A287006FBC77 /* GRCXXExprEngine.cpp in Sources */, - 1AC1AB471299A287006FBC77 /* GRExprEngine.cpp in Sources */, - 1AC1AB481299A287006FBC77 /* GRExprEngineExperimentalChecks.cpp in Sources */, - 1AC1AB491299A287006FBC77 /* GRState.cpp in Sources */, - 1AC1AB4A1299A287006FBC77 /* HTMLDiagnostics.cpp in Sources */, - 1AC1AB4B1299A287006FBC77 /* IdempotentOperationChecker.cpp in Sources */, - 1AC1AB4C1299A287006FBC77 /* LLVMConventionsChecker.cpp in Sources */, - 1AC1AB4D1299A287006FBC77 /* MacOSXAPIChecker.cpp in Sources */, - 1AC1AB4F1299A287006FBC77 /* MallocChecker.cpp in Sources */, - 1AC1AB501299A287006FBC77 /* ManagerRegistry.cpp in Sources */, - 1AC1AB511299A287006FBC77 /* MemRegion.cpp in Sources */, - 1AC1AB521299A287006FBC77 /* NoReturnFunctionChecker.cpp in Sources */, - 1AC1AB531299A287006FBC77 /* NSAutoreleasePoolChecker.cpp in Sources */, - 1AC1AB541299A287006FBC77 /* NSErrorChecker.cpp in Sources */, - 1AC1AB551299A287006FBC77 /* ObjCAtSyncChecker.cpp in Sources */, - 1AC1AB561299A287006FBC77 /* ObjCUnusedIVarsChecker.cpp in Sources */, - 1AC1AB571299A287006FBC77 /* OSAtomicChecker.cpp in Sources */, - 1AC1AB581299A287006FBC77 /* PathDiagnostic.cpp in Sources */, - 1AC1AB591299A287006FBC77 /* PlistDiagnostics.cpp in Sources */, - 1AC1AB5A1299A287006FBC77 /* PointerArithChecker.cpp in Sources */, - 1AC1AB5B1299A287006FBC77 /* PointerSubChecker.cpp in Sources */, - 1AC1AB5C1299A287006FBC77 /* PthreadLockChecker.cpp in Sources */, - 1AC1AB5D1299A287006FBC77 /* RangeConstraintManager.cpp in Sources */, - 1AC1AB5E1299A287006FBC77 /* RegionStore.cpp in Sources */, - 1AC1AD331299A287006FBC77 /* ReturnPointerRangeChecker.cpp in Sources */, - 1AC1AD341299A287006FBC77 /* ReturnUndefChecker.cpp in Sources */, - 1AC1AD351299A287006FBC77 /* SimpleConstraintManager.cpp in Sources */, - 1AC1AD361299A287006FBC77 /* SimpleSValuator.cpp in Sources */, - 1AC1AD371299A287006FBC77 /* StackAddrLeakChecker.cpp in Sources */, - 1AC1AD381299A287006FBC77 /* Store.cpp in Sources */, - 1AC1AD391299A287006FBC77 /* StreamChecker.cpp in Sources */, - 1AC1AD3A1299A287006FBC77 /* SVals.cpp in Sources */, - 1AC1AD3B1299A287006FBC77 /* SValuator.cpp in Sources */, - 1AC1AD3C1299A287006FBC77 /* SymbolManager.cpp in Sources */, - 1AC1AD3D1299A287006FBC77 /* UndefBranchChecker.cpp in Sources */, - 1AC1AD3E1299A287006FBC77 /* UndefCapturedBlockVarChecker.cpp in Sources */, - 1AC1AD3F1299A287006FBC77 /* UndefinedArraySubscriptChecker.cpp in Sources */, - 1AC1AD401299A287006FBC77 /* UndefinedAssignmentChecker.cpp in Sources */, - 1AC1AD411299A287006FBC77 /* UndefResultChecker.cpp in Sources */, - 1AC1AD421299A287006FBC77 /* UnixAPIChecker.cpp in Sources */, - 1AC1AD431299A287006FBC77 /* UnreachableCodeChecker.cpp in Sources */, - 1AC1AD441299A287006FBC77 /* ValueManager.cpp in Sources */, - 1AC1AD451299A287006FBC77 /* VLASizeChecker.cpp in Sources */, - 1A3D2C4E12A2CD3D0088C44A /* CGCXXABI.cpp in Sources */, - BB5C372912A5057500259F53 /* DumpXML.cpp in Sources */, - BBA5AB7E1309C2FA000B38F1 /* AdjustedReturnValueChecker.cpp in Sources */, - BBA5AB7F1309C2FA000B38F1 /* AnalyzerStatsChecker.cpp in Sources */, - BBA5AB801309C2FA000B38F1 /* ArrayBoundChecker.cpp in Sources */, - BBA5AB811309C2FA000B38F1 /* ArrayBoundCheckerV2.cpp in Sources */, - BBA5AB821309C2FA000B38F1 /* AttrNonNullChecker.cpp in Sources */, - BBA5AB831309C2FA000B38F1 /* BasicObjCFoundationChecks.cpp in Sources */, - BBA5AB841309C2FA000B38F1 /* BuiltinFunctionChecker.cpp in Sources */, - BBA5AB851309C2FA000B38F1 /* CallAndMessageChecker.cpp in Sources */, - BBA5AB861309C2FA000B38F1 /* CastSizeChecker.cpp in Sources */, - BBA5AB871309C2FA000B38F1 /* CastToStructChecker.cpp in Sources */, - BBA5AB881309C2FA000B38F1 /* CheckObjCDealloc.cpp in Sources */, - BBA5AB891309C2FA000B38F1 /* CheckObjCInstMethSignature.cpp in Sources */, - BBA5AB8A1309C2FA000B38F1 /* CheckSecuritySyntaxOnly.cpp in Sources */, - BBA5AB8B1309C2FA000B38F1 /* CheckSizeofPointer.cpp in Sources */, - BBA5AB8C1309C2FA000B38F1 /* ChrootChecker.cpp in Sources */, - BBA5AB8D1309C2FA000B38F1 /* ClangSACheckerProvider.cpp in Sources */, - BBA5AB8E1309C2FA000B38F1 /* CStringChecker.cpp in Sources */, - BBA5AB8F1309C2FA000B38F1 /* DeadStoresChecker.cpp in Sources */, - BBA5AB901309C2FA000B38F1 /* DereferenceChecker.cpp in Sources */, - BBA5AB911309C2FA000B38F1 /* DivZeroChecker.cpp in Sources */, - BBA5AB921309C2FA000B38F1 /* ExperimentalChecks.cpp in Sources */, - BBA5AB931309C2FA000B38F1 /* ExprEngine.cpp in Sources */, - BBA5AB941309C2FA000B38F1 /* FixedAddressChecker.cpp in Sources */, - BBA5AB951309C2FA000B38F1 /* IdempotentOperationChecker.cpp in Sources */, - BBA5AB961309C2FA000B38F1 /* LLVMConventionsChecker.cpp in Sources */, - BBA5AB971309C2FA000B38F1 /* MacOSXAPIChecker.cpp in Sources */, - BBA5AB991309C2FA000B38F1 /* MallocChecker.cpp in Sources */, - BBA5AB9A1309C2FA000B38F1 /* NoReturnFunctionChecker.cpp in Sources */, - BBA5AB9B1309C2FA000B38F1 /* NSAutoreleasePoolChecker.cpp in Sources */, - BBA5AB9C1309C2FA000B38F1 /* NSErrorChecker.cpp in Sources */, - BBA5AB9D1309C2FA000B38F1 /* ObjCAtSyncChecker.cpp in Sources */, - BBA5AB9E1309C2FA000B38F1 /* ObjCSelfInitChecker.cpp in Sources */, - BBA5AB9F1309C2FA000B38F1 /* ObjCUnusedIVarsChecker.cpp in Sources */, - BBA5ABA01309C2FA000B38F1 /* OSAtomicChecker.cpp in Sources */, - BBA5ABA11309C2FA000B38F1 /* PointerArithChecker.cpp in Sources */, - BBA5ABA21309C2FA000B38F1 /* PointerSubChecker.cpp in Sources */, - BBA5ABA31309C2FA000B38F1 /* PthreadLockChecker.cpp in Sources */, - BBA5ABA41309C2FA000B38F1 /* ReturnPointerRangeChecker.cpp in Sources */, - BBA5ABA51309C2FA000B38F1 /* ReturnUndefChecker.cpp in Sources */, - BBA5ABA61309C2FA000B38F1 /* StackAddrLeakChecker.cpp in Sources */, - BBA5ABA71309C2FA000B38F1 /* StreamChecker.cpp in Sources */, - BBA5ABA81309C2FA000B38F1 /* UndefBranchChecker.cpp in Sources */, - BBA5ABA91309C2FA000B38F1 /* UndefCapturedBlockVarChecker.cpp in Sources */, - BBA5ABAA1309C2FA000B38F1 /* UndefinedArraySubscriptChecker.cpp in Sources */, - BBA5ABAB1309C2FA000B38F1 /* UndefinedAssignmentChecker.cpp in Sources */, - BBA5ABAC1309C2FA000B38F1 /* UndefResultChecker.cpp in Sources */, - BBA5ABAD1309C2FA000B38F1 /* UnixAPIChecker.cpp in Sources */, - BBA5ABAE1309C2FA000B38F1 /* UnreachableCodeChecker.cpp in Sources */, - BBA5ABAF1309C2FA000B38F1 /* VLASizeChecker.cpp in Sources */, - BBA5ABB01309C2FA000B38F1 /* AggExprVisitor.cpp in Sources */, - BBA5ABB11309C2FA000B38F1 /* AnalysisManager.cpp in Sources */, - BBA5ABB21309C2FA000B38F1 /* BasicConstraintManager.cpp in Sources */, - BBA5ABB31309C2FA000B38F1 /* BasicStore.cpp in Sources */, - BBA5ABB41309C2FA000B38F1 /* BasicValueFactory.cpp in Sources */, - BBA5ABB51309C2FA000B38F1 /* BlockCounter.cpp in Sources */, - BBA5ABB61309C2FA000B38F1 /* BugReporter.cpp in Sources */, - BBA5ABB71309C2FA000B38F1 /* BugReporterVisitors.cpp in Sources */, - BBA5ABB81309C2FA000B38F1 /* CFRefCount.cpp in Sources */, - BBA5ABB91309C2FA000B38F1 /* Checker.cpp in Sources */, - BBA5ABBA1309C2FA000B38F1 /* CheckerHelpers.cpp in Sources */, - BBA5ABBB1309C2FA000B38F1 /* CheckerManager.cpp in Sources */, - BBA5ABBC1309C2FA000B38F1 /* CoreEngine.cpp in Sources */, - BBA5ABBD1309C2FA000B38F1 /* CXXExprEngine.cpp in Sources */, - BBA5ABBE1309C2FA000B38F1 /* Environment.cpp in Sources */, - BBA5ABBF1309C2FA000B38F1 /* ExplodedGraph.cpp in Sources */, - BBA5ABC01309C2FA000B38F1 /* FlatStore.cpp in Sources */, - BBA5ABC11309C2FA000B38F1 /* GRState.cpp in Sources */, - BBA5ABC21309C2FA000B38F1 /* HTMLDiagnostics.cpp in Sources */, - BBA5ABC41309C2FA000B38F1 /* MemRegion.cpp in Sources */, - BBA5ABC51309C2FA000B38F1 /* ObjCMessage.cpp in Sources */, - BBA5ABC61309C2FA000B38F1 /* PathDiagnostic.cpp in Sources */, - BBA5ABC71309C2FA000B38F1 /* PlistDiagnostics.cpp in Sources */, - BBA5ABC81309C2FA000B38F1 /* RangeConstraintManager.cpp in Sources */, - BBA5ABC91309C2FA000B38F1 /* RegionStore.cpp in Sources */, - BBA5ABCA1309C2FA000B38F1 /* SimpleConstraintManager.cpp in Sources */, - BBA5ABCB1309C2FA000B38F1 /* SimpleSValBuilder.cpp in Sources */, - BBA5ABCC1309C2FA000B38F1 /* Store.cpp in Sources */, - BBA5ABCD1309C2FA000B38F1 /* SValBuilder.cpp in Sources */, - BBA5ABCE1309C2FA000B38F1 /* SVals.cpp in Sources */, - BBA5ABCF1309C2FA000B38F1 /* SymbolManager.cpp in Sources */, - BBA5ABD01309C2FA000B38F1 /* TextPathDiagnostics.cpp in Sources */, - BBA5ABD11309C2FA000B38F1 /* AnalysisConsumer.cpp in Sources */, - BBA5ABD21309C2FA000B38F1 /* CheckerRegistration.cpp in Sources */, - BBA5ABD31309C2FA000B38F1 /* FrontendActions.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/docs/LanguageExtensions.html b/docs/LanguageExtensions.html index 8f412c63653b..b0de13a91e9b 100644 --- a/docs/LanguageExtensions.html +++ b/docs/LanguageExtensions.html @@ -419,8 +419,7 @@ compile-time assertions using <tt>static_assert</tt> is enabled.</p> <p>Use <tt>__has_feature(cxx_auto_type)</tt> to determine C++0x type inference is supported using the <tt>auto</tt> specifier. If this is disabled, -<tt>auto</tt> will instead be a storage class specifier, as in C or C++98. -Clang does not currently implement this feature.</p> +<tt>auto</tt> will instead be a storage class specifier, as in C or C++98.</p> <h3 id="cxx_variadic_templates">C++0x variadic templates</h3> diff --git a/examples/wpa/clang-wpa.cpp b/examples/wpa/clang-wpa.cpp index bbb9e147ebad..89eddb356242 100644 --- a/examples/wpa/clang-wpa.cpp +++ b/examples/wpa/clang-wpa.cpp @@ -155,7 +155,8 @@ int main(int argc, char **argv) { Opts.CheckersControlList.push_back(std::make_pair("cocoa", true)); llvm::OwningPtr<ento::CheckerManager> checkerMgr; - checkerMgr.reset(ento::registerCheckers(Opts, PP.getDiagnostics())); + checkerMgr.reset(ento::registerCheckers(Opts, PP.getLangOptions(), + PP.getDiagnostics())); using namespace clang::ento; AnalysisManager AMgr(TU->getASTContext(), PP.getDiagnostics(), diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h index b3b49c79c3a9..722f6be538b4 100644 --- a/include/clang-c/Index.h +++ b/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/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 0e887133d01e..c0eeb5af3892 100644 --- a/include/clang/AST/ASTContext.h +++ b/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/include/clang/AST/ASTImporter.h b/include/clang/AST/ASTImporter.h index b659ce74bb7c..e1535965b1e4 100644 --- a/include/clang/AST/ASTImporter.h +++ b/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/include/clang/AST/CMakeLists.txt b/include/clang/AST/CMakeLists.txt index 800c58361b02..c10cda84fb83 100644 --- a/include/clang/AST/CMakeLists.txt +++ b/include/clang/AST/CMakeLists.txt @@ -1,24 +1,17 @@ -set(LLVM_TARGET_DEFINITIONS ../Basic/Attr.td) -tablegen(Attrs.inc - -gen-clang-attr-classes - -I ${CMAKE_CURRENT_SOURCE_DIR}/../../) -add_custom_target(ClangAttrClasses - DEPENDS Attrs.inc) +clang_tablegen(Attrs.inc -gen-clang-attr-classes + -I ${CMAKE_CURRENT_SOURCE_DIR}/../../ + SOURCE ../Basic/Attr.td + TARGET ClangAttrClasses) -tablegen(AttrImpl.inc - -gen-clang-attr-impl - -I ${CMAKE_CURRENT_SOURCE_DIR}/../../) -add_custom_target(ClangAttrImpl - DEPENDS AttrImpl.inc) +clang_tablegen(AttrImpl.inc -gen-clang-attr-impl + -I ${CMAKE_CURRENT_SOURCE_DIR}/../../ + SOURCE ../Basic/Attr.td + TARGET ClangAttrImpl) -set(LLVM_TARGET_DEFINITIONS ../Basic/StmtNodes.td) -tablegen(StmtNodes.inc - -gen-clang-stmt-nodes) -add_custom_target(ClangStmtNodes - DEPENDS StmtNodes.inc) +clang_tablegen(StmtNodes.inc -gen-clang-stmt-nodes + SOURCE ../Basic/StmtNodes.td + TARGET ClangStmtNodes) -set(LLVM_TARGET_DEFINITIONS ../Basic/DeclNodes.td) -tablegen(DeclNodes.inc - -gen-clang-decl-nodes) -add_custom_target(ClangDeclNodes - DEPENDS DeclNodes.inc) +clang_tablegen(DeclNodes.inc -gen-clang-decl-nodes + SOURCE ../Basic/DeclNodes.td + TARGET ClangDeclNodes) diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index ee515da0835c..31cee24df993 100644 --- a/include/clang/AST/Decl.h +++ b/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/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index bf249cea9d5f..b35d134d0534 100644 --- a/include/clang/AST/DeclBase.h +++ b/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/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index d11ee8f7fd64..1656a7e9737c 100644 --- a/include/clang/AST/DeclCXX.h +++ b/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/include/clang/AST/DeclGroup.h b/include/clang/AST/DeclGroup.h index cb9e1681cc06..63cdac594920 100644 --- a/include/clang/AST/DeclGroup.h +++ b/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/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index 176c6badae16..f41859c85790 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/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/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index a17205c2b6b9..95bfad5a16c2 100644 --- a/include/clang/AST/Expr.h +++ b/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/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index 85ce9621d928..225db3c11fd0 100644 --- a/include/clang/AST/ExprCXX.h +++ b/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/include/clang/AST/NestedNameSpecifier.h b/include/clang/AST/NestedNameSpecifier.h index 99cc1f268fb2..024bf402894b 100644 --- a/include/clang/AST/NestedNameSpecifier.h +++ b/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/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index 921b799b94b5..e85b6dcd279a 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/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/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h index 7ede9ce323f4..d1f7d667f33d 100644 --- a/include/clang/AST/Stmt.h +++ b/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/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h b/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h new file mode 100644 index 000000000000..72f644aaf028 --- /dev/null +++ b/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/include/clang/Analysis/AnalysisContext.h b/include/clang/Analysis/AnalysisContext.h index 2ecbfdc6bf02..851451457881 100644 --- a/include/clang/Analysis/AnalysisContext.h +++ b/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/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def index 7d270ad7fb89..b73ac1f4dd45 100644 --- a/include/clang/Basic/Builtins.def +++ b/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/include/clang/Basic/Builtins.h b/include/clang/Basic/Builtins.h index 4df4c8f95374..0d17e03d8a52 100644 --- a/include/clang/Basic/Builtins.h +++ b/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/include/clang/Basic/CMakeLists.txt b/include/clang/Basic/CMakeLists.txt index c5952365d593..19066e4c0eef 100644 --- a/include/clang/Basic/CMakeLists.txt +++ b/include/clang/Basic/CMakeLists.txt @@ -1,11 +1,10 @@ macro(clang_diag_gen component) - tablegen(Diagnostic${component}Kinds.inc - -gen-clang-diags-defs -clang-component=${component}) - add_custom_target(ClangDiagnostic${component} - DEPENDS Diagnostic${component}Kinds.inc) + clang_tablegen(Diagnostic${component}Kinds.inc + -gen-clang-diags-defs -clang-component=${component} + SOURCE Diagnostic.td + TARGET ClangDiagnostic${component}) endmacro(clang_diag_gen) -set(LLVM_TARGET_DEFINITIONS Diagnostic.td) clang_diag_gen(Analysis) clang_diag_gen(AST) clang_diag_gen(Common) @@ -14,19 +13,16 @@ clang_diag_gen(Frontend) clang_diag_gen(Lex) clang_diag_gen(Parse) clang_diag_gen(Sema) -tablegen(DiagnosticGroups.inc - -gen-clang-diag-groups) -add_custom_target(ClangDiagnosticGroups - DEPENDS DiagnosticGroups.inc) +clang_tablegen(DiagnosticGroups.inc -gen-clang-diag-groups + SOURCE Diagnostic.td + TARGET ClangDiagnosticGroups) -set(LLVM_TARGET_DEFINITIONS Attr.td) -tablegen(AttrList.inc - -gen-clang-attr-list - -I ${CMAKE_CURRENT_SOURCE_DIR}/../../) -add_custom_target(ClangAttrList - DEPENDS AttrList.inc) +clang_tablegen(AttrList.inc -gen-clang-attr-list + -I ${CMAKE_CURRENT_SOURCE_DIR}/../../ + SOURCE Attr.td + TARGET ClangAttrList) # ARM NEON -set(LLVM_TARGET_DEFINITIONS arm_neon.td) -tablegen(arm_neon.inc -gen-arm-neon-sema) -add_custom_target(ClangARMNeon DEPENDS arm_neon.inc) +clang_tablegen(arm_neon.inc -gen-arm-neon-sema + SOURCE arm_neon.td + TARGET ClangARMNeon) diff --git a/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h index 19e7c91f5324..3fc60d136b5c 100644 --- a/include/clang/Basic/Diagnostic.h +++ b/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/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td index 5f9f4a7f3927..30706769d45e 100644 --- a/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/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/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index d4377c9a0b07..412fb587108e 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/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/include/clang/Basic/DiagnosticIDs.h b/include/clang/Basic/DiagnosticIDs.h index b46380569851..2b03cae565c8 100644 --- a/include/clang/Basic/DiagnosticIDs.h +++ b/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/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index 9d7ec9d45447..9a68af9c45ca 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/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/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 2e7f274b8ed5..a9fb2da00176 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/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/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h index f4db55ae0626..0bd983e8e6c6 100644 --- a/include/clang/Basic/LangOptions.h +++ b/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 @@ -165,8 +166,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/include/clang/Basic/PartialDiagnostic.h b/include/clang/Basic/PartialDiagnostic.h index d00195b32674..c63619440551 100644 --- a/include/clang/Basic/PartialDiagnostic.h +++ b/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/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h index c0fbd089e760..b1443dad09fd 100644 --- a/include/clang/Basic/SourceManager.h +++ b/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/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index a2c69f99540e..748e6cf32691 100644 --- a/include/clang/Driver/CC1Options.td +++ b/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 fgnu_runtime : Flag<"-fgnu-runtime">, @@ -536,6 +538,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>">, @@ -550,8 +554,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/include/clang/Driver/CMakeLists.txt b/include/clang/Driver/CMakeLists.txt index 99be53ffc72b..abd4cfe50129 100644 --- a/include/clang/Driver/CMakeLists.txt +++ b/include/clang/Driver/CMakeLists.txt @@ -1,17 +1,11 @@ -set(LLVM_TARGET_DEFINITIONS Options.td) -tablegen(Options.inc - -gen-opt-parser-defs) -add_custom_target(ClangDriverOptions - DEPENDS Options.inc) +clang_tablegen(Options.inc -gen-opt-parser-defs + SOURCE Options.td + TARGET ClangDriverOptions) -set(LLVM_TARGET_DEFINITIONS CC1Options.td) -tablegen(CC1Options.inc - -gen-opt-parser-defs) -add_custom_target(ClangCC1Options - DEPENDS CC1Options.inc) +clang_tablegen(CC1Options.inc -gen-opt-parser-defs + SOURCE CC1Options.td + TARGET ClangCC1Options) -set(LLVM_TARGET_DEFINITIONS CC1AsOptions.td) -tablegen(CC1AsOptions.inc - -gen-opt-parser-defs) -add_custom_target(ClangCC1AsOptions - DEPENDS CC1AsOptions.inc) +clang_tablegen(CC1AsOptions.inc -gen-opt-parser-defs + SOURCE CC1AsOptions.td + TARGET ClangCC1AsOptions) diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index 7e3ddc616e1c..288c10f52354 100644 --- a/include/clang/Driver/Options.td +++ b/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/include/clang/Frontend/AnalyzerOptions.h b/include/clang/Frontend/AnalyzerOptions.h index 580692865819..64263c1b54e8 100644 --- a/include/clang/Frontend/AnalyzerOptions.h +++ b/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/include/clang/Frontend/DeclXML.def b/include/clang/Frontend/DeclXML.def index 1b158fdfafc0..58f7e55fbe80 100644 --- a/include/clang/Frontend/DeclXML.def +++ b/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/include/clang/Frontend/HeaderSearchOptions.h b/include/clang/Frontend/HeaderSearchOptions.h index cbb4a57993b7..b0669eba4ccc 100644 --- a/include/clang/Frontend/HeaderSearchOptions.h +++ b/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/include/clang/Frontend/Utils.h b/include/clang/Frontend/Utils.h index 485161b1bc38..02342c1a4710 100644 --- a/include/clang/Frontend/Utils.h +++ b/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/include/clang/Lex/CMakeLists.txt b/include/clang/Lex/CMakeLists.txt index b823e83f906b..38055ebb64dd 100644 --- a/include/clang/Lex/CMakeLists.txt +++ b/include/clang/Lex/CMakeLists.txt @@ -1,6 +1,5 @@ -set(LLVM_TARGET_DEFINITIONS ../Basic/Attr.td) -tablegen(AttrSpellings.inc - -gen-clang-attr-spelling-list - -I ${CMAKE_CURRENT_SOURCE_DIR}/../../) -add_custom_target(ClangAttrSpellings +clang_tablegen(AttrSpellings.inc -gen-clang-attr-spelling-list + -I ${CMAKE_CURRENT_SOURCE_DIR}/../../ + SOURCE ../Basic/Attr.td + TARGET ClangAttrSpellings DEPENDS AttrSpellings.inc) diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index 018f7e9c8c02..9005adc6ade6 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/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/include/clang/Lex/TokenLexer.h b/include/clang/Lex/TokenLexer.h index 3f13e9cc1268..6ae00cd58658 100644 --- a/include/clang/Lex/TokenLexer.h +++ b/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/include/clang/Sema/AnalysisBasedWarnings.h b/include/clang/Sema/AnalysisBasedWarnings.h index 0a6656e97e1b..8b389b169b3c 100644 --- a/include/clang/Sema/AnalysisBasedWarnings.h +++ b/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/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h index 9c4bb646949b..64126bd4d80a 100644 --- a/include/clang/Sema/DeclSpec.h +++ b/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/include/clang/Sema/ExternalSemaSource.h b/include/clang/Sema/ExternalSemaSource.h index 6d7bc6316bd2..e2b083e83047 100644 --- a/include/clang/Sema/ExternalSemaSource.h +++ b/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/include/clang/Sema/Initialization.h b/include/clang/Sema/Initialization.h index c1915659905b..bdf0d8e7b602 100644 --- a/include/clang/Sema/Initialization.h +++ b/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/include/clang/Sema/ParsedTemplate.h b/include/clang/Sema/ParsedTemplate.h index 5aa6f47425aa..9e1a6165b194 100644 --- a/include/clang/Sema/ParsedTemplate.h +++ b/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/include/clang/Sema/ScopeInfo.h b/include/clang/Sema/ScopeInfo.h index b0bb95509a91..51297ae40205 100644 --- a/include/clang/Sema/ScopeInfo.h +++ b/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/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 91d6914f24e3..a93739892cfe 100644 --- a/include/clang/Sema/Sema.h +++ b/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/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h index 9799b8d852c2..424e78c391bc 100644 --- a/include/clang/Serialization/ASTReader.h +++ b/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/include/clang/Serialization/ASTWriter.h b/include/clang/Serialization/ASTWriter.h index beb493625e87..04ad93fa7c1a 100644 --- a/include/clang/Serialization/ASTWriter.h +++ b/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/include/clang/Serialization/CMakeLists.txt b/include/clang/Serialization/CMakeLists.txt index 3712009bf37d..d91513da9997 100644 --- a/include/clang/Serialization/CMakeLists.txt +++ b/include/clang/Serialization/CMakeLists.txt @@ -1,12 +1,9 @@ -set(LLVM_TARGET_DEFINITIONS ../Basic/Attr.td) -tablegen(AttrPCHRead.inc - -gen-clang-attr-pch-read - -I ${CMAKE_CURRENT_SOURCE_DIR}/../../) -add_custom_target(ClangAttrPCHRead - DEPENDS AttrPCHRead.inc) +clang_tablegen(AttrPCHRead.inc -gen-clang-attr-pch-read + -I ${CMAKE_CURRENT_SOURCE_DIR}/../../ + SOURCE ../Basic/Attr.td + TARGET ClangAttrPCHRead) -tablegen(AttrPCHWrite.inc - -gen-clang-attr-pch-write - -I ${CMAKE_CURRENT_SOURCE_DIR}/../../) -add_custom_target(ClangAttrPCHWrite - DEPENDS AttrPCHWrite.inc) +clang_tablegen(AttrPCHWrite.inc -gen-clang-attr-pch-write + -I ${CMAKE_CURRENT_SOURCE_DIR}/../../ + SOURCE ../Basic/Attr.td + TARGET ClangAttrPCHWrite) diff --git a/include/clang/StaticAnalyzer/Checkers/LocalCheckers.h b/include/clang/StaticAnalyzer/Checkers/LocalCheckers.h index 42feb78b4174..afba12dc0620 100644 --- a/include/clang/StaticAnalyzer/Checkers/LocalCheckers.h +++ b/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/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h index 1786fe610d6b..93d795831d3c 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h +++ b/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/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h index 2793284e298f..7b9bb03d8d05 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h +++ b/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/include/clang/StaticAnalyzer/Core/CheckerManager.h b/include/clang/StaticAnalyzer/Core/CheckerManager.h index 65c8b80aa2a8..276819549d1a 100644 --- a/include/clang/StaticAnalyzer/Core/CheckerManager.h +++ b/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/include/clang/StaticAnalyzer/Core/CheckerProvider.h b/include/clang/StaticAnalyzer/Core/CheckerProvider.h index 414ad92b2a5a..40b838e75886 100644 --- a/include/clang/StaticAnalyzer/Core/CheckerProvider.h +++ b/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/include/clang/StaticAnalyzer/Core/CheckerV2.h b/include/clang/StaticAnalyzer/Core/CheckerV2.h index 8c96866f1c99..e080d190ab75 100644 --- a/include/clang/StaticAnalyzer/Core/CheckerV2.h +++ b/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/include/clang/StaticAnalyzer/Core/PathSensitive/Checker.h b/include/clang/StaticAnalyzer/Core/PathSensitive/Checker.h index 22c202749ba7..627bc0ab3516 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/Checker.h +++ b/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/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h new file mode 100644 index 000000000000..4429c6b2a7ad --- /dev/null +++ b/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/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h index 800e63a4cdeb..25c644734232 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h +++ b/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/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h index 767644a03292..16f54ee7468d 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h +++ b/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/include/clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h b/include/clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h index 411441f8fe34..07cdbf523427 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h +++ b/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/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h b/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h index 4c3e379f3345..9d6298f36e3b 100644 --- a/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h +++ b/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/include/clang/StaticAnalyzer/Frontend/FrontendActions.h b/include/clang/StaticAnalyzer/Frontend/FrontendActions.h index e3867a2a2478..f01418175281 100644 --- a/include/clang/StaticAnalyzer/Frontend/FrontendActions.h +++ b/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/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 945dfb87f297..9c2455034d68 100644 --- a/lib/AST/ASTContext.cpp +++ b/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/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index 65c0a3bb619f..21f10fb7ad99 100644 --- a/lib/AST/ASTImporter.cpp +++ b/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/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 56db8c7e330b..73fe117b1e4e 100644 --- a/lib/AST/Decl.cpp +++ b/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/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index be379d522dd4..81df00d6c7e8 100644 --- a/lib/AST/DeclBase.cpp +++ b/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/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index fba73f59d563..46768c12d879 100644 --- a/lib/AST/DeclCXX.cpp +++ b/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/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp index 77b42574709f..c6ae128e42b5 100644 --- a/lib/AST/DeclPrinter.cpp +++ b/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/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 391b26ab48ea..1c1061b5a229 100644 --- a/lib/AST/Expr.cpp +++ b/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/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp index 28ff9fb57afc..4f4a6b4944d9 100644 --- a/lib/AST/ExprCXX.cpp +++ b/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/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 656bb99df98e..3a5eb66ea18f 100644 --- a/lib/AST/ExprConstant.cpp +++ b/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/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp index d66c374cbec0..939ca7a924aa 100644 --- a/lib/AST/ItaniumMangle.cpp +++ b/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/lib/AST/NestedNameSpecifier.cpp b/lib/AST/NestedNameSpecifier.cpp index 650321d76ee5..6f1ec058d74e 100644 --- a/lib/AST/NestedNameSpecifier.cpp +++ b/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/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp index cf14eba1405d..4ed031f97499 100644 --- a/lib/AST/RecordLayoutBuilder.cpp +++ b/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/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp index 7e73f02e67e7..8a80275aa165 100644 --- a/lib/AST/Stmt.cpp +++ b/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/lib/AST/StmtDumper.cpp b/lib/AST/StmtDumper.cpp index 846bd4ce1441..5c7dbb3ed990 100644 --- a/lib/AST/StmtDumper.cpp +++ b/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/lib/AST/TemplateBase.cpp b/lib/AST/TemplateBase.cpp index 5ab5f4644c88..1764f4ab1f03 100644 --- a/lib/AST/TemplateBase.cpp +++ b/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/lib/Analysis/AnalysisContext.cpp b/lib/Analysis/AnalysisContext.cpp index 5233d3b8f9f8..62097ef20dd9 100644 --- a/lib/Analysis/AnalysisContext.cpp +++ b/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/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp index a0ec5febbeff..cc6e9c592a1e 100644 --- a/lib/Analysis/CFG.cpp +++ b/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/lib/Analysis/CFGReachabilityAnalysis.cpp b/lib/Analysis/CFGReachabilityAnalysis.cpp new file mode 100644 index 000000000000..77865849014a --- /dev/null +++ b/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/lib/Analysis/CMakeLists.txt b/lib/Analysis/CMakeLists.txt index 0912f3c87448..84b211f2cfca 100644 --- a/lib/Analysis/CMakeLists.txt +++ b/lib/Analysis/CMakeLists.txt @@ -3,6 +3,7 @@ set(LLVM_USED_LIBS clangBasic clangAST clangIndex) add_clang_library(clangAnalysis AnalysisContext.cpp CFG.cpp + CFGReachabilityAnalysis.cpp CFGStmtMap.cpp CocoaConventions.cpp FormatString.cpp diff --git a/lib/Basic/DiagnosticIDs.cpp b/lib/Basic/DiagnosticIDs.cpp index 8725e7f9c0cc..553e4c929454 100644 --- a/lib/Basic/DiagnosticIDs.cpp +++ b/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/lib/Basic/SourceManager.cpp b/lib/Basic/SourceManager.cpp index 044c88dd2bf7..e2783ba6fda2 100644 --- a/lib/Basic/SourceManager.cpp +++ b/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/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp index a8198e4ae79e..55321f2498ef 100644 --- a/lib/Basic/Targets.cpp +++ b/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/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp index a35648d23d51..9587de223aa7 100644 --- a/lib/CodeGen/CGBlocks.cpp +++ b/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/lib/CodeGen/CGBlocks.h b/lib/CodeGen/CGBlocks.h index bee729dccee9..0bc8bcaa14f9 100644 --- a/lib/CodeGen/CGBlocks.h +++ b/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/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp index 8e88beb3cf0d..cd28bbe44db5 100644 --- a/lib/CodeGen/CGClass.cpp +++ b/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/lib/CodeGen/CGCleanup.cpp b/lib/CodeGen/CGCleanup.cpp index 374ede880d20..1d7901a2db4c 100644 --- a/lib/CodeGen/CGCleanup.cpp +++ b/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/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index 469b4605d7ca..dfd9f56b12e3 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/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/lib/CodeGen/CGDebugInfo.h b/lib/CodeGen/CGDebugInfo.h index 6a9ab9c58b52..a39078860fa9 100644 --- a/lib/CodeGen/CGDebugInfo.h +++ b/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/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index a87dfaed9d5e..f4db01d2570b 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/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/lib/CodeGen/CGException.cpp b/lib/CodeGen/CGException.cpp index 6181965748cc..4bce081e48dd 100644 --- a/lib/CodeGen/CGException.cpp +++ b/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/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 1b7e7a007ed2..2abaadff4b6d 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/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/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp index 08c458bd52d3..5d3490769991 100644 --- a/lib/CodeGen/CGObjC.cpp +++ b/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/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp index d481e7792674..5f19dc6e5647 100644 --- a/lib/CodeGen/CGObjCGNU.cpp +++ b/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/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index 7c679b90590c..8dbd85f8b738 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/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/lib/CodeGen/CGRecordLayoutBuilder.cpp b/lib/CodeGen/CGRecordLayoutBuilder.cpp index 4b19aefcf9c4..ceae66f3849e 100644 --- a/lib/CodeGen/CGRecordLayoutBuilder.cpp +++ b/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/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 67ef41448e8d..be646fb29022 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/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/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 9e5d7cf11276..a8453c31d54e 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/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/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index b6bd37c1c0d3..73e6ece14732 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/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/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp index d74b3f32d954..2ffc840b9f92 100644 --- a/lib/CodeGen/TargetInfo.cpp +++ b/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/lib/Driver/ToolChain.cpp b/lib/Driver/ToolChain.cpp index e4051a165b2d..e305683930cf 100644 --- a/lib/Driver/ToolChain.cpp +++ b/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/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp index 13b8b4609ec0..1c396bd0ed5b 100644 --- a/lib/Driver/ToolChains.cpp +++ b/lib/Driver/ToolChains.cpp @@ -42,7 +42,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/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index 6717349b9765..9f4a0bc162e3 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -1546,10 +1546,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, @@ -3085,7 +3085,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/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp index 4a5a51d9f1dc..a7942e6090c8 100644 --- a/lib/Frontend/ASTUnit.cpp +++ b/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/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 103d251a88f5..b9d15ad01ab1 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/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) @@ -862,6 +861,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); @@ -876,8 +876,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); @@ -892,8 +890,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)); } } @@ -1236,7 +1239,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); @@ -1272,10 +1274,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! } @@ -1457,7 +1461,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); @@ -1486,8 +1493,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); @@ -1658,8 +1663,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/lib/Frontend/DocumentXML.cpp b/lib/Frontend/DocumentXML.cpp index b24ece5119d6..a09db0be473e 100644 --- a/lib/Frontend/DocumentXML.cpp +++ b/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/lib/Frontend/InitHeaderSearch.cpp b/lib/Frontend/InitHeaderSearch.cpp index 4855b62b747d..2e3162c0a32e 100644 --- a/lib/Frontend/InitHeaderSearch.cpp +++ b/lib/Frontend/InitHeaderSearch.cpp @@ -42,7 +42,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; @@ -94,7 +96,7 @@ public: /// Realize - Merges all search path lists into one list and send it to /// HeaderSearch. - void Realize(); + void Realize(const LangOptions &Lang); }; } @@ -131,8 +133,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; } @@ -142,7 +144,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; } } @@ -179,29 +182,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. @@ -567,13 +570,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 @@ -613,7 +620,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: //===------------------------------------------------------------------===// @@ -809,13 +816,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); @@ -829,11 +831,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]; @@ -908,32 +910,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; @@ -978,5 +997,5 @@ void clang::ApplyHeaderSearchOptions(HeaderSearch &HS, if (HSOpts.UseStandardIncludes) Init.AddDefaultSystemIncludePaths(Lang, Triple, HSOpts); - Init.Realize(); + Init.Realize(Lang); } diff --git a/lib/Frontend/InitPreprocessor.cpp b/lib/Frontend/InitPreprocessor.cpp index d0111a5d26a9..91b5280a87ef 100644 --- a/lib/Frontend/InitPreprocessor.cpp +++ b/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/lib/Frontend/TextDiagnosticPrinter.cpp b/lib/Frontend/TextDiagnosticPrinter.cpp index 04c6a68023d9..084915311dcc 100644 --- a/lib/Frontend/TextDiagnosticPrinter.cpp +++ b/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/lib/Frontend/VerifyDiagnosticsClient.cpp b/lib/Frontend/VerifyDiagnosticsClient.cpp index 51b351f4a923..fff417e20dcb 100644 --- a/lib/Frontend/VerifyDiagnosticsClient.cpp +++ b/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/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/lib/FrontendTool/ExecuteCompilerInvocation.cpp index 4bb85e7e6340..65fad6da51fa 100644 --- a/lib/FrontendTool/ExecuteCompilerInvocation.cpp +++ b/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/lib/Headers/CMakeLists.txt b/lib/Headers/CMakeLists.txt index eef541e5b8ac..1e9eacc13ab3 100644 --- a/lib/Headers/CMakeLists.txt +++ b/lib/Headers/CMakeLists.txt @@ -28,8 +28,8 @@ if(MSVC_IDE OR XCODE) endif() # Generate arm_neon.h -set(LLVM_TARGET_DEFINITIONS ${CLANG_SOURCE_DIR}/include/clang/Basic/arm_neon.td) -tablegen(arm_neon.h.inc -gen-arm-neon) +clang_tablegen(arm_neon.h.inc -gen-arm-neon + SOURCE ${CLANG_SOURCE_DIR}/include/clang/Basic/arm_neon.td) set(out_files) foreach( f ${files} ) @@ -67,6 +67,7 @@ if (other_output_dir) endif () add_custom_target(clang-headers ALL DEPENDS ${out_files}) +set_target_properties(clang-headers PROPERTIES FOLDER "Misc") install(FILES ${files} ${output_dir}/arm_neon.h PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp index 0f0d25b887af..3e871ae7ab47 100644 --- a/lib/Lex/PPDirectives.cpp +++ b/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/lib/Lex/Pragma.cpp b/lib/Lex/Pragma.cpp index f0475bc0cb20..80d3bb1d2790 100644 --- a/lib/Lex/Pragma.cpp +++ b/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/lib/Lex/TokenLexer.cpp b/lib/Lex/TokenLexer.cpp index ea39b47904b0..caa44bf4a146 100644 --- a/lib/Lex/TokenLexer.cpp +++ b/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/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 5a7fc7e72d06..077edd700ad6 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/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/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index e73578f23e36..d8db711809ed 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/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/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp index 8387c8819525..59ced8b07fc5 100644 --- a/lib/Parse/ParseTemplate.cpp +++ b/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/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index a50763a0e38e..07e592cdb05b 100644 --- a/lib/Parse/Parser.cpp +++ b/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/lib/Rewrite/RewriteObjC.cpp b/lib/Rewrite/RewriteObjC.cpp index 875a0c7a84c5..0263f657a6e3 100644 --- a/lib/Rewrite/RewriteObjC.cpp +++ b/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/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp index 63f561d6ab19..6a422242a9d4 100644 --- a/lib/Sema/AnalysisBasedWarnings.cpp +++ b/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/lib/Sema/DeclSpec.cpp b/lib/Sema/DeclSpec.cpp index bc289ec42c99..037594a44a1c 100644 --- a/lib/Sema/DeclSpec.cpp +++ b/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/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index 23a3c24804e6..0c39e1325393 100644 --- a/lib/Sema/Sema.cpp +++ b/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/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp index aa0efcdc70e1..7ad4b459451d 100644 --- a/lib/Sema/SemaCXXScopeSpec.cpp +++ b/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/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 556665483e64..d83809d70897 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/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); @@ -2861,6 +2886,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; } @@ -3112,7 +3148,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; @@ -3124,12 +3160,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; @@ -3138,7 +3177,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/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index dd30c1261ed7..d6efd7a6c9dd 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/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/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index cbc940f2f0ac..893cf6ac26e4 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/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/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index e8abab847654..f483262a8cf5 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/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/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 66f6f2b960d1..652318f7204e 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/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/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 65b57c30cd7d..415ab3f38d58 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/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/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index f9c2c9a62ea3..6dd7aabaa1f0 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/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/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index b9a6a5713b8b..5882da0eab46 100644 --- a/lib/Sema/SemaInit.cpp +++ b/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/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 0fd0e08ac830..3deb4034c538 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/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/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 6fb789cfd8a1..8d03285ee443 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/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/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index e995e8f207df..89957e60deca 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/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/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index f0a0103205d5..f02dd2582402 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/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/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index bd0a618283b3..139fafb346f9 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/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/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 44f5913d55c7..ae0ac9cbe35c 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/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/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index c0150c07bbf1..3a40b6fd77a7 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/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/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index c88baa540f52..ba80076003c9 100644 --- a/lib/Sema/SemaType.cpp +++ b/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/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 944e6a13e113..57a44ad9d984 100644 --- a/lib/Sema/TreeTransform.h +++ b/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/lib/Sema/TypeLocBuilder.h b/lib/Sema/TypeLocBuilder.h index 3d20a5273d6d..1e0a7c454675 100644 --- a/lib/Sema/TypeLocBuilder.h +++ b/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/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index ce87b11c2695..c3953ba554dc 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/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/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index dec15dd694f5..493ccbad8618 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/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/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp index 4e91c989260d..42f0b1aacef3 100644 --- a/lib/Serialization/ASTReaderStmt.cpp +++ b/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/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index 8fcb535a9c89..383ca3dffc6c 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/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/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp index ce07e1389b82..12d1226be94e 100644 --- a/lib/Serialization/ASTWriterDecl.cpp +++ b/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/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp index 8a5ffe96db17..af846a92800c 100644 --- a/lib/Serialization/ASTWriterStmt.cpp +++ b/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/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp b/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp index 9194791fc075..25e224e50c68 100644 --- a/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp +++ b/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/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp b/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp index 1b6c528c2f16..7aff2010d84d 100644 --- a/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp +++ b/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/lib/StaticAnalyzer/Checkers/CMakeLists.txt b/lib/StaticAnalyzer/Checkers/CMakeLists.txt index e172a529d768..e3083967e01d 100644 --- a/lib/StaticAnalyzer/Checkers/CMakeLists.txt +++ b/lib/StaticAnalyzer/Checkers/CMakeLists.txt @@ -1,9 +1,7 @@ -set(LLVM_TARGET_DEFINITIONS Checkers.td) -tablegen(Checkers.inc - -gen-clang-sa-checkers - -I ${CMAKE_CURRENT_SOURCE_DIR}/../../../include) -add_custom_target(ClangSACheckers - DEPENDS Checkers.inc) +clang_tablegen(Checkers.inc -gen-clang-sa-checkers + -I ${CMAKE_CURRENT_SOURCE_DIR}/../../../include + SOURCE Checkers.td + TARGET ClangSACheckers) set(LLVM_USED_LIBS clangBasic clangAST) @@ -29,8 +27,8 @@ add_clang_library(clangStaticAnalyzerCheckers DebugCheckers.cpp DereferenceChecker.cpp DivZeroChecker.cpp - ExprEngine.cpp ExperimentalChecks.cpp + ExprEngine.cpp FixedAddressChecker.cpp IdempotentOperationChecker.cpp LLVMConventionsChecker.cpp @@ -48,7 +46,7 @@ add_clang_library(clangStaticAnalyzerCheckers PthreadLockChecker.cpp ReturnPointerRangeChecker.cpp ReturnUndefChecker.cpp - StackAddrLeakChecker.cpp + StackAddrEscapeChecker.cpp StreamChecker.cpp UndefBranchChecker.cpp UndefCapturedBlockVarChecker.cpp diff --git a/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/lib/StaticAnalyzer/Checkers/CStringChecker.cpp index 03f9047e960c..2566e3cbb430 100644 --- a/lib/StaticAnalyzer/Checkers/CStringChecker.cpp +++ b/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/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp b/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp index 518cf963bef4..6a4506bcf844 100644 --- a/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp +++ b/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/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp b/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp index 8ec226abf6a9..04cc253fc609 100644 --- a/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp +++ b/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/lib/StaticAnalyzer/Checkers/Checkers.td b/lib/StaticAnalyzer/Checkers/Checkers.td index 1dc748666441..894b961f7d1e 100644 --- a/lib/StaticAnalyzer/Checkers/Checkers.td +++ b/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/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp b/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp index 36e76d0d3ce2..b6eef6d150d4 100644 --- a/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp +++ b/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/lib/StaticAnalyzer/Checkers/ClangSACheckerProvider.cpp b/lib/StaticAnalyzer/Checkers/ClangSACheckerProvider.cpp index 94f200f3e892..5c0c9504db03 100644 --- a/lib/StaticAnalyzer/Checkers/ClangSACheckerProvider.cpp +++ b/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/lib/StaticAnalyzer/Checkers/ExperimentalChecks.cpp b/lib/StaticAnalyzer/Checkers/ExperimentalChecks.cpp index d9bb4801c381..990ba1c02b94 100644 --- a/lib/StaticAnalyzer/Checkers/ExperimentalChecks.cpp +++ b/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/lib/StaticAnalyzer/Checkers/ExprEngine.cpp b/lib/StaticAnalyzer/Checkers/ExprEngine.cpp index ab8d56471c55..c1b1e656989b 100644 --- a/lib/StaticAnalyzer/Checkers/ExprEngine.cpp +++ b/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/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp b/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp index fe628a2512b2..d7b27b563784 100644 --- a/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp +++ b/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/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp b/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp index f49b125a60a2..83d9668c48fa 100644 --- a/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp +++ b/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/lib/StaticAnalyzer/Checkers/InternalChecks.h b/lib/StaticAnalyzer/Checkers/InternalChecks.h index e855386fffea..e7c38ee25d8f 100644 --- a/lib/StaticAnalyzer/Checkers/InternalChecks.h +++ b/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/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp b/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp index 358be124b9e4..d70c65ae3073 100644 --- a/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp +++ b/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/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp index 9d3a887cdbf1..794740ab7203 100644 --- a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/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/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp b/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp index 9fb89d79fc79..fed6a99c89a2 100644 --- a/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp +++ b/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/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp b/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp index 7d440ab17e9f..77467190db73 100644 --- a/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp +++ b/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/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp b/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp index 4f247ea14670..5f32bb8f53a2 100644 --- a/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp +++ b/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/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp b/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp index 741e48bfcbe0..034a2aaef74e 100644 --- a/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp +++ b/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/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp b/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp index f28fe9a5379e..bf85b959c9ee 100644 --- a/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp +++ b/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/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp b/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp index 34c095f42e08..6c6901f41263 100644 --- a/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp +++ b/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/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp b/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp index 838a00f18785..298515609cd0 100644 --- a/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp +++ b/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/lib/StaticAnalyzer/Checkers/StackAddrLeakChecker.cpp b/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp index 363f4042db6b..6a9a37d955bf 100644 --- a/lib/StaticAnalyzer/Checkers/StackAddrLeakChecker.cpp +++ b/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/lib/StaticAnalyzer/Checkers/StreamChecker.cpp b/lib/StaticAnalyzer/Checkers/StreamChecker.cpp index 2655be28a462..d0626b8cef83 100644 --- a/lib/StaticAnalyzer/Checkers/StreamChecker.cpp +++ b/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/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp b/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp index a53ebb5ae19c..be4fbf60eb2e 100644 --- a/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp +++ b/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/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp b/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp index 3038e29c0efc..1bc487a49c1e 100644 --- a/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp +++ b/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/lib/StaticAnalyzer/Core/BugReporter.cpp b/lib/StaticAnalyzer/Core/BugReporter.cpp index 9a84045ebd97..672982a3c025 100644 --- a/lib/StaticAnalyzer/Core/BugReporter.cpp +++ b/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/lib/StaticAnalyzer/Core/CheckerManager.cpp b/lib/StaticAnalyzer/Core/CheckerManager.cpp index 1989b822ae40..75d331a131a8 100644 --- a/lib/StaticAnalyzer/Core/CheckerManager.cpp +++ b/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/lib/StaticAnalyzer/Core/CoreEngine.cpp b/lib/StaticAnalyzer/Core/CoreEngine.cpp index 070042a641f6..08a2068c0106 100644 --- a/lib/StaticAnalyzer/Core/CoreEngine.cpp +++ b/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/lib/StaticAnalyzer/Core/Environment.cpp b/lib/StaticAnalyzer/Core/Environment.cpp index ecaff295b390..1bffa3022e43 100644 --- a/lib/StaticAnalyzer/Core/Environment.cpp +++ b/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/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp index dbfebccee745..e3e7ee957a6f 100644 --- a/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp +++ b/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/lib/StaticAnalyzer/Frontend/CMakeLists.txt b/lib/StaticAnalyzer/Frontend/CMakeLists.txt index cd9ac1b0c7e8..16014bad3c06 100644 --- a/lib/StaticAnalyzer/Frontend/CMakeLists.txt +++ b/lib/StaticAnalyzer/Frontend/CMakeLists.txt @@ -16,5 +16,5 @@ add_dependencies(clangStaticAnalyzerFrontend ClangAttrClasses ClangAttrList ClangDeclNodes - ClangStmtNode + ClangStmtNodes ) diff --git a/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp b/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp index 6625729eafe4..677e20cd9c0e 100644 --- a/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp +++ b/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/test/Analysis/CFDateGC.m b/test/Analysis/CFDateGC.m index abcefdec58ed..a00895586e2e 100644 --- a/test/Analysis/CFDateGC.m +++ b/test/Analysis/CFDateGC.m @@ -1,8 +1,8 @@ -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=basic -verify -fobjc-gc -analyzer-constraints=basic %s -Wno-implicit-function-declaration -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=basic -verify -fobjc-gc -analyzer-constraints=range %s -Wno-implicit-function-declaration -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=basic -verify -fobjc-gc -disable-free %s -Wno-implicit-function-declaration -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=basic -verify -fobjc-gc %s -Wno-implicit-function-declaration -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=range -verify -fobjc-gc %s -Wno-implicit-function-declaration +// RUN: %clang_cc1 -analyze -analyzer-check-objc-mem -analyzer-store=basic -verify -fobjc-gc -analyzer-constraints=basic %s -Wno-implicit-function-declaration +// RUN: %clang_cc1 -analyze -analyzer-check-objc-mem -analyzer-store=basic -verify -fobjc-gc -analyzer-constraints=range %s -Wno-implicit-function-declaration +// RUN: %clang_cc1 -analyze -analyzer-check-objc-mem -analyzer-store=basic -verify -fobjc-gc -disable-free %s -Wno-implicit-function-declaration +// RUN: %clang_cc1 -analyze -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=basic -verify -fobjc-gc %s -Wno-implicit-function-declaration +// RUN: %clang_cc1 -analyze -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=range -verify -fobjc-gc %s -Wno-implicit-function-declaration //===----------------------------------------------------------------------===// // The following code is reduced using delta-debugging from diff --git a/test/Analysis/CFRetainRelease_NSAssertionHandler.m b/test/Analysis/CFRetainRelease_NSAssertionHandler.m index ce9e6ff1b60b..7ece5c665904 100644 --- a/test/Analysis/CFRetainRelease_NSAssertionHandler.m +++ b/test/Analysis/CFRetainRelease_NSAssertionHandler.m @@ -1,7 +1,7 @@ -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -verify %s -analyzer-constraints=basic -analyzer-store=basic -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -verify %s -analyzer-constraints=range -analyzer-store=basic -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -verify %s -analyzer-constraints=basic -analyzer-store=region -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -verify %s -analyzer-constraints=range -analyzer-store=region +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -verify %s -analyzer-constraints=basic -analyzer-store=basic +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -verify %s -analyzer-constraints=range -analyzer-store=basic +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -verify %s -analyzer-constraints=basic -analyzer-store=region +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -verify %s -analyzer-constraints=range -analyzer-store=region typedef struct objc_selector *SEL; typedef signed char BOOL; diff --git a/test/Analysis/CGColorSpace.c b/test/Analysis/CGColorSpace.c index 737f1a32b500..9d554a98f636 100644 --- a/test/Analysis/CGColorSpace.c +++ b/test/Analysis/CGColorSpace.c @@ -1,7 +1,7 @@ -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=basic -verify %s -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=range -verify %s -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=basic -verify %s -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=range -verify %s +// RUN: %clang_cc1 -analyze -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=basic -verify %s +// RUN: %clang_cc1 -analyze -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=range -verify %s +// RUN: %clang_cc1 -analyze -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=basic -verify %s +// RUN: %clang_cc1 -analyze -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=range -verify %s typedef struct CGColorSpace *CGColorSpaceRef; extern CGColorSpaceRef CGColorSpaceCreateDeviceRGB(void); diff --git a/test/Analysis/CheckNSError.m b/test/Analysis/CheckNSError.m index 6bf299d6bed5..d12ad4eb2e65 100644 --- a/test/Analysis/CheckNSError.m +++ b/test/Analysis/CheckNSError.m @@ -1,7 +1,7 @@ -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=basic -verify %s -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=basic -verify %s -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=range -verify %s -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=range -verify %s +// RUN: %clang_cc1 -analyze -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=basic -verify %s +// RUN: %clang_cc1 -analyze -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=basic -verify %s +// RUN: %clang_cc1 -analyze -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=range -verify %s +// RUN: %clang_cc1 -analyze -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=range -verify %s typedef signed char BOOL; diff --git a/test/Analysis/MissingDealloc.m b/test/Analysis/MissingDealloc.m index d7aaa99be70e..27fd340dd0b2 100644 --- a/test/Analysis/MissingDealloc.m +++ b/test/Analysis/MissingDealloc.m @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-checker=cocoa.experimental.Dealloc '-DIBOutlet=__attribute__((iboutlet))' %s -verify +// RUN: %clang_cc1 -analyze -analyzer-checker=cocoa.experimental.Dealloc '-DIBOutlet=__attribute__((iboutlet))' %s -verify typedef signed char BOOL; @protocol NSObject - (BOOL)isEqual:(id)object; diff --git a/test/Analysis/NSPanel.m b/test/Analysis/NSPanel.m index 7ebe18ff0f2c..3f356349ad8a 100644 --- a/test/Analysis/NSPanel.m +++ b/test/Analysis/NSPanel.m @@ -1,7 +1,7 @@ -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=basic -verify %s -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=range -verify %s -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=basic -verify %s -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=range -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=basic -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=range -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=basic -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=range -verify %s // BEGIN delta-debugging reduced header stuff diff --git a/test/Analysis/NSString.m b/test/Analysis/NSString.m index c5f7a4569a5b..52664df231c8 100644 --- a/test/Analysis/NSString.m +++ b/test/Analysis/NSString.m @@ -1,13 +1,13 @@ -// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=cocoa.NilArg -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=basic -verify %s -// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=cocoa.NilArg -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=range -verify %s -// RUN: %clang_cc1 -DTEST_64 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=cocoa.NilArg -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=basic -verify %s -// RUN: %clang_cc1 -DTEST_64 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=cocoa.NilArg -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=range -verify %s +// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=cocoa.NilArg -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=basic -verify %s +// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=cocoa.NilArg -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=range -verify %s +// RUN: %clang_cc1 -DTEST_64 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=cocoa.NilArg -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=basic -verify %s +// RUN: %clang_cc1 -DTEST_64 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=cocoa.NilArg -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=range -verify %s // ==-- FIXME: -analyzer-store=basic fails on this file (false negatives). --== -// NOTWORK: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=cocoa.NilArg -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=range -verify %s && -// NOTWORK: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=cocoa.NilArg -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=basic -verify %s && -// NOTWORK: %clang_cc1 -DTEST_64 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=cocoa.NilArg -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=basic -verify %s && -// NOTWORK: %clang_cc1 -DTEST_64 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=cocoa.NilArg -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=range -verify %s +// NOTWORK: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=cocoa.NilArg -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=range -verify %s && +// NOTWORK: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=cocoa.NilArg -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=basic -verify %s && +// NOTWORK: %clang_cc1 -DTEST_64 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=cocoa.NilArg -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=basic -verify %s && +// NOTWORK: %clang_cc1 -DTEST_64 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=cocoa.NilArg -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=range -verify %s //===----------------------------------------------------------------------===// // The following code is reduced using delta-debugging from diff --git a/test/Analysis/NSWindow.m b/test/Analysis/NSWindow.m index c386adf3f085..76e265f1ebcb 100644 --- a/test/Analysis/NSWindow.m +++ b/test/Analysis/NSWindow.m @@ -1,7 +1,7 @@ -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-checker=core.DeadStores -analyzer-store=basic -analyzer-constraints=basic -verify %s -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-checker=core.DeadStores -analyzer-store=basic -analyzer-constraints=range -verify %s -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-checker=core.DeadStores -analyzer-store=region -analyzer-constraints=basic -verify %s -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-checker=core.DeadStores -analyzer-store=region -analyzer-constraints=range -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-checker=core.DeadStores -analyzer-store=basic -analyzer-constraints=basic -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-checker=core.DeadStores -analyzer-store=basic -analyzer-constraints=range -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-checker=core.DeadStores -analyzer-store=region -analyzer-constraints=basic -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-checker=core.DeadStores -analyzer-store=region -analyzer-constraints=range -verify %s // These declarations were reduced using Delta-Debugging from Foundation.h // on Mac OS X. The test cases are below. diff --git a/test/Analysis/NoReturn.m b/test/Analysis/NoReturn.m index a02c93cfd350..f3bfcf53190e 100644 --- a/test/Analysis/NoReturn.m +++ b/test/Analysis/NoReturn.m @@ -1,7 +1,7 @@ -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=basic -verify %s -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=range -verify %s -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=basic -verify %s -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=range -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=basic -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=range -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=basic -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=range -verify %s #include <stdarg.h> diff --git a/test/Analysis/ObjCProperties.m b/test/Analysis/ObjCProperties.m index 72f3d3894d8a..9362692bd75e 100644 --- a/test/Analysis/ObjCProperties.m +++ b/test/Analysis/ObjCProperties.m @@ -1,7 +1,7 @@ -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=basic %s -verify -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=range %s -verify -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=basic %s -verify -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=range %s -verify +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=basic %s -verify +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=range %s -verify +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=basic %s -verify +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=range %s -verify // The point of this test cases is to exercise properties in the static // analyzer diff --git a/test/Analysis/ObjCRetSigs.m b/test/Analysis/ObjCRetSigs.m index 5a912a808984..93dae14ea198 100644 --- a/test/Analysis/ObjCRetSigs.m +++ b/test/Analysis/ObjCRetSigs.m @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-checker=cocoa.MethodSigs -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-checker=cocoa.MethodSigs -verify %s int printf(const char *, ...); diff --git a/test/Analysis/PR2599.m b/test/Analysis/PR2599.m index 68c8c0622612..89f36d27749c 100644 --- a/test/Analysis/PR2599.m +++ b/test/Analysis/PR2599.m @@ -1,7 +1,7 @@ -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-constraints=basic -analyzer-store=basic -analyzer-check-objc-mem -fobjc-gc -verify %s -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-constraints=range -analyzer-store=basic -analyzer-check-objc-mem -fobjc-gc -verify %s -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-constraints=basic -analyzer-store=basic -analyzer-check-objc-mem -fobjc-gc -verify %s -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-constraints=range -analyzer-store=region -analyzer-check-objc-mem -fobjc-gc -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-constraints=basic -analyzer-store=basic -analyzer-check-objc-mem -fobjc-gc -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-constraints=range -analyzer-store=basic -analyzer-check-objc-mem -fobjc-gc -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-constraints=basic -analyzer-store=basic -analyzer-check-objc-mem -fobjc-gc -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-constraints=range -analyzer-store=region -analyzer-check-objc-mem -fobjc-gc -verify %s typedef const void * CFTypeRef; typedef const struct __CFString * CFStringRef; diff --git a/test/Analysis/PR2978.m b/test/Analysis/PR2978.m index ac3ef790cabd..c3b21f230807 100644 --- a/test/Analysis/PR2978.m +++ b/test/Analysis/PR2978.m @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-checker=cocoa.experimental.Dealloc %s -verify +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-checker=cocoa.experimental.Dealloc %s -verify // Tests for the checker which checks missing/extra ivar 'release' calls // in dealloc. diff --git a/test/Analysis/PR3991.m b/test/Analysis/PR3991.m index c1f238c77c85..83ae19f4ba8c 100644 --- a/test/Analysis/PR3991.m +++ b/test/Analysis/PR3991.m @@ -1,7 +1,7 @@ -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=basic -verify -triple x86_64-apple-darwin9 %s -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=range -verify -triple x86_64-apple-darwin9 %s -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=basic -verify -triple x86_64-apple-darwin9 %s -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=range -verify -triple x86_64-apple-darwin9 %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=basic -verify -triple x86_64-apple-darwin9 %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=range -verify -triple x86_64-apple-darwin9 %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=basic -verify -triple x86_64-apple-darwin9 %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=range -verify -triple x86_64-apple-darwin9 %s //===----------------------------------------------------------------------===// // Delta-debugging produced forward declarations. diff --git a/test/Analysis/analyzer-stats.c b/test/Analysis/analyzer-stats.c index d8dde23d6709..2a2e325acef8 100644 --- a/test/Analysis/analyzer-stats.c +++ b/test/Analysis/analyzer-stats.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-checker=core.DeadStores -verify -Wno-unreachable-code -analyzer-opt-analyze-nested-blocks -analyzer-stats %s +// RUN: %clang_cc1 -analyze -analyzer-check-objc-mem -analyzer-checker=core.DeadStores -verify -Wno-unreachable-code -analyzer-opt-analyze-nested-blocks -analyzer-stats %s int foo(); diff --git a/test/Analysis/array-struct-region.c b/test/Analysis/array-struct-region.c index 8162200b0aca..168423e0c2cd 100644 --- a/test/Analysis/array-struct-region.c +++ b/test/Analysis/array-struct-region.c @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -analyze -analyzer-experimental-checks -analyzer-experimental-internal-checks -analyzer-checker=core.experimental.UnreachableCode -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=basic -verify %s -// RUN: %clang_cc1 -analyze -analyzer-experimental-checks -analyzer-experimental-internal-checks -analyzer-checker=core.experimental.UnreachableCode -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=range -verify %s +// RUN: %clang_cc1 -analyze -analyzer-experimental-checks -analyzer-checker=core.experimental.UnreachableCode -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=basic -verify %s +// RUN: %clang_cc1 -analyze -analyzer-experimental-checks -analyzer-checker=core.experimental.UnreachableCode -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=range -verify %s int string_literal_init() { char a[] = "abc"; diff --git a/test/Analysis/casts.c b/test/Analysis/casts.c index 1cb88e611224..1df30c9e3555 100644 --- a/test/Analysis/casts.c +++ b/test/Analysis/casts.c @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -verify %s -// RUN: %clang_cc1 -triple i386-apple-darwin9 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -verify %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=region -verify %s +// RUN: %clang_cc1 -triple i386-apple-darwin9 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=region -verify %s // Test if the 'storage' region gets properly initialized after it is cast to // 'struct sockaddr *'. diff --git a/test/Analysis/casts.m b/test/Analysis/casts.m index c99b4d6c4db0..a6f11926818d 100644 --- a/test/Analysis/casts.m +++ b/test/Analysis/casts.m @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=basic -verify %s -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=basic -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=region -verify %s // Test function pointer casts. Currently we track function addresses using // loc::FunctionVal. Because casts can be arbitrary, do we need to model diff --git a/test/Analysis/cfref_PR2519.c b/test/Analysis/cfref_PR2519.c index ebf35443c29d..94475bdcdf2d 100644 --- a/test/Analysis/cfref_PR2519.c +++ b/test/Analysis/cfref_PR2519.c @@ -1,7 +1,7 @@ -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=basic -verify %s -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=range -verify %s -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=basic -verify %s -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=range -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=basic -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=range -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=basic -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=range -verify %s typedef unsigned char Boolean; typedef signed long CFIndex; diff --git a/test/Analysis/cfref_rdar6080742.c b/test/Analysis/cfref_rdar6080742.c index 12b08198242e..debc1d8990cc 100644 --- a/test/Analysis/cfref_rdar6080742.c +++ b/test/Analysis/cfref_rdar6080742.c @@ -1,7 +1,7 @@ -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=basic -verify %s -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=range -verify %s -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=basic -verify %s -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=range -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=basic -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=range -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=basic -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=range -verify %s // This test case was reported in <rdar:problem/6080742>. // It tests path-sensitivity with respect to '!(cfstring != 0)' (negation of inequality). diff --git a/test/Analysis/complex.c b/test/Analysis/complex.c index 1a33349960fb..c8bdce015363 100644 --- a/test/Analysis/complex.c +++ b/test/Analysis/complex.c @@ -1,7 +1,7 @@ -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=basic -verify -Wno-unreachable-code -ffreestanding %s -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=range -verify -Wno-unreachable-code -ffreestanding %s -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=basic -verify -Wno-unreachable-code -ffreestanding %s -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=range -verify -Wno-unreachable-code -ffreestanding %s +// RUN: %clang_cc1 -analyze -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=basic -verify -Wno-unreachable-code -ffreestanding %s +// RUN: %clang_cc1 -analyze -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=range -verify -Wno-unreachable-code -ffreestanding %s +// RUN: %clang_cc1 -analyze -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=basic -verify -Wno-unreachable-code -ffreestanding %s +// RUN: %clang_cc1 -analyze -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=range -verify -Wno-unreachable-code -ffreestanding %s #include <stdint.h> diff --git a/test/Analysis/concrete-address.c b/test/Analysis/concrete-address.c index 07ca7136e2f3..13afe0cbebd4 100644 --- a/test/Analysis/concrete-address.c +++ b/test/Analysis/concrete-address.c @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=basic -verify %s -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=basic -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=region -verify %s void foo() { int *p = (int*) 0x10000; // Should not crash here. diff --git a/test/Analysis/conditional-op-missing-lhs.c b/test/Analysis/conditional-op-missing-lhs.c index e738964194d9..51d40f2a040e 100644 --- a/test/Analysis/conditional-op-missing-lhs.c +++ b/test/Analysis/conditional-op-missing-lhs.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-checker=core.DeadStores -warn-uninit-values -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.DeadStores -warn-uninit-values -verify %s void f1() { diff --git a/test/Analysis/constant-folding.c b/test/Analysis/constant-folding.c index bb339f6957a1..33b48f5164cb 100644 --- a/test/Analysis/constant-folding.c +++ b/test/Analysis/constant-folding.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-checker=core.experimental.UnreachableCode -analyzer-check-objc-mem -analyzer-experimental-checks -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental.UnreachableCode -analyzer-check-objc-mem -analyzer-experimental-checks -verify %s // Trigger a warning if the analyzer reaches this point in the control flow. #define WARN ((void)*(char*)0) diff --git a/test/Analysis/dead-stores.c b/test/Analysis/dead-stores.c index 7fc0f0464d72..39394c6354a4 100644 --- a/test/Analysis/dead-stores.c +++ b/test/Analysis/dead-stores.c @@ -1,8 +1,8 @@ -// RUN: %clang_cc1 -Wunused-variable -analyze -analyzer-checker=core.experimental.IdempotentOps -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-checker=core.DeadStores -fblocks -verify -Wno-unreachable-code -analyzer-opt-analyze-nested-blocks %s -// RUN: %clang_cc1 -Wunused-variable -analyze -analyzer-checker=core.experimental.IdempotentOps -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=basic -analyzer-checker=core.DeadStores -fblocks -verify -Wno-unreachable-code -analyzer-opt-analyze-nested-blocks %s -// RUN: %clang_cc1 -Wunused-variable -analyze -analyzer-checker=core.experimental.IdempotentOps -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=range -analyzer-checker=core.DeadStores -fblocks -verify -Wno-unreachable-code -analyzer-opt-analyze-nested-blocks %s -// RUN: %clang_cc1 -Wunused-variable -analyze -analyzer-checker=core.experimental.IdempotentOps -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=basic -analyzer-checker=core.DeadStores -fblocks -verify -Wno-unreachable-code -analyzer-opt-analyze-nested-blocks %s -// RUN: %clang_cc1 -Wunused-variable -analyze -analyzer-checker=core.experimental.IdempotentOps -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=range -analyzer-checker=core.DeadStores -fblocks -verify -Wno-unreachable-code -analyzer-opt-analyze-nested-blocks %s +// RUN: %clang_cc1 -Wunused-variable -analyze -analyzer-checker=core.DeadStores,core.experimental.IdempotentOps -analyzer-check-objc-mem -fblocks -verify -Wno-unreachable-code -analyzer-opt-analyze-nested-blocks %s +// RUN: %clang_cc1 -Wunused-variable -analyze -analyzer-checker=core.DeadStores,core.experimental.IdempotentOps -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=basic -fblocks -verify -Wno-unreachable-code -analyzer-opt-analyze-nested-blocks %s +// RUN: %clang_cc1 -Wunused-variable -analyze -analyzer-checker=core.DeadStores,core.experimental.IdempotentOps -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=range -fblocks -verify -Wno-unreachable-code -analyzer-opt-analyze-nested-blocks %s +// RUN: %clang_cc1 -Wunused-variable -analyze -analyzer-checker=core.DeadStores,core.experimental.IdempotentOps -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=basic -fblocks -verify -Wno-unreachable-code -analyzer-opt-analyze-nested-blocks %s +// RUN: %clang_cc1 -Wunused-variable -analyze -analyzer-checker=core.DeadStores,core.experimental.IdempotentOps -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=range -fblocks -verify -Wno-unreachable-code -analyzer-opt-analyze-nested-blocks %s void f1() { int k, y; // expected-warning{{unused variable 'k'}} expected-warning{{unused variable 'y'}} diff --git a/test/Analysis/dead-stores.cpp b/test/Analysis/dead-stores.cpp index 59a48bada1b3..8477b701fa0c 100644 --- a/test/Analysis/dead-stores.cpp +++ b/test/Analysis/dead-stores.cpp @@ -1,8 +1,8 @@ -// RUN: %clang_cc1 -fexceptions -analyze -analyzer-experimental-internal-checks -analyzer-checker=core.DeadStores -verify -Wno-unreachable-code %s -// RUN: %clang_cc1 -fexceptions -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=basic -analyzer-checker=core.DeadStores -verify -Wno-unreachable-code %s -// RUN: %clang_cc1 -fexceptions -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=range -analyzer-checker=core.DeadStores -verify -Wno-unreachable-code %s -// RUN: %clang_cc1 -fexceptions -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=basic -analyzer-checker=core.DeadStores -verify -Wno-unreachable-code %s -// RUN: %clang_cc1 -fexceptions -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=range -analyzer-checker=core.DeadStores -verify -Wno-unreachable-code %s +// RUN: %clang_cc1 -fexceptions -analyze -analyzer-checker=core.DeadStores -verify -Wno-unreachable-code %s +// RUN: %clang_cc1 -fexceptions -analyze -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=basic -analyzer-checker=core.DeadStores -verify -Wno-unreachable-code %s +// RUN: %clang_cc1 -fexceptions -analyze -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=range -analyzer-checker=core.DeadStores -verify -Wno-unreachable-code %s +// RUN: %clang_cc1 -fexceptions -analyze -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=basic -analyzer-checker=core.DeadStores -verify -Wno-unreachable-code %s +// RUN: %clang_cc1 -fexceptions -analyze -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=range -analyzer-checker=core.DeadStores -verify -Wno-unreachable-code %s //===----------------------------------------------------------------------===// // Basic dead store checking (but in C++ mode). diff --git a/test/Analysis/dead-stores.m b/test/Analysis/dead-stores.m index 00c9e53d2525..8e13a97393e9 100644 --- a/test/Analysis/dead-stores.m +++ b/test/Analysis/dead-stores.m @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-checker=core.DeadStores -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-checker=core.DeadStores -verify %s typedef signed char BOOL; typedef unsigned int NSUInteger; diff --git a/test/Analysis/delegates.m b/test/Analysis/delegates.m index 18b42417eb97..194a64a85516 100644 --- a/test/Analysis/delegates.m +++ b/test/Analysis/delegates.m @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=basic -verify %s -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -verify %s +// RUN: %clang_cc1 -analyze -analyzer-check-objc-mem -analyzer-store=basic -verify %s +// RUN: %clang_cc1 -analyze -analyzer-check-objc-mem -analyzer-store=region -verify %s //===----------------------------------------------------------------------===// diff --git a/test/Analysis/elementtype.c b/test/Analysis/elementtype.c index 08ffe32d3c88..ba66015d746e 100644 --- a/test/Analysis/elementtype.c +++ b/test/Analysis/elementtype.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=region %s typedef struct added_obj_st { int type; diff --git a/test/Analysis/exercise-ps.c b/test/Analysis/exercise-ps.c index 196b67936a9c..f2b15bff3159 100644 --- a/test/Analysis/exercise-ps.c +++ b/test/Analysis/exercise-ps.c @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=basic -verify %s -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=basic -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=region -verify %s // // Just exercise the analyzer on code that has at one point caused issues // (i.e., no assertions or crashes). diff --git a/test/Analysis/fields.c b/test/Analysis/fields.c index 0827f3dbad18..c7e223138b1c 100644 --- a/test/Analysis/fields.c +++ b/test/Analysis/fields.c @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem %s -analyzer-store=basic -verify -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem %s -analyzer-store=region -verify +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem %s -analyzer-store=basic -verify +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem %s -analyzer-store=region -verify unsigned foo(); typedef struct bf { unsigned x:2; } bf; diff --git a/test/Analysis/free.c b/test/Analysis/free.c index 60bb3f2eb5a6..8aba4a05f0bf 100644 --- a/test/Analysis/free.c +++ b/test/Analysis/free.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-experimental-checks -fblocks -verify %s +// RUN: %clang_cc1 -analyze -analyzer-check-objc-mem -analyzer-store=region -analyzer-experimental-checks -fblocks -verify %s void free(void *); void t1 () { diff --git a/test/Analysis/func.c b/test/Analysis/func.c index 53c873df55a9..e4e20a0bed14 100644 --- a/test/Analysis/func.c +++ b/test/Analysis/func.c @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=basic -verify %s -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=basic -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=region -verify %s void f(void) { void (*p)(void); diff --git a/test/Analysis/malloc.c b/test/Analysis/malloc.c index fdfccab204ce..2ffa1033598d 100644 --- a/test/Analysis/malloc.c +++ b/test/Analysis/malloc.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-checker=core.experimental.UnreachableCode -analyzer-check-objc-mem -analyzer-experimental-checks -analyzer-store=region -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental.UnreachableCode,core.experimental.CastSize -analyzer-check-objc-mem -analyzer-experimental-checks -analyzer-store=region -verify %s typedef __typeof(sizeof(int)) size_t; void *malloc(size_t); void free(void *); diff --git a/test/Analysis/misc-ps-64.m b/test/Analysis/misc-ps-64.m index f65673eea24f..bdb12c963f95 100644 --- a/test/Analysis/misc-ps-64.m +++ b/test/Analysis/misc-ps-64.m @@ -1,7 +1,7 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=basic -verify -fblocks %s -// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=range -verify -fblocks %s -// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=basic -verify -fblocks %s -// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=range -verify -fblocks %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=basic -verify -fblocks %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=range -verify -fblocks %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=basic -verify -fblocks %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=range -verify -fblocks %s // <rdar://problem/6440393> - A bunch of misc. failures involving evaluating // these expressions and building CFGs. These tests are here to prevent diff --git a/test/Analysis/misc-ps-basic-store.m b/test/Analysis/misc-ps-basic-store.m index 4f8e4f656f08..55042c142584 100644 --- a/test/Analysis/misc-ps-basic-store.m +++ b/test/Analysis/misc-ps-basic-store.m @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=basic -verify -fblocks %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=basic -verify -fblocks %s //--------------------------------------------------------------------------- // Test case 'checkaccess_union' differs for region store and basic store. diff --git a/test/Analysis/misc-ps-eager-assume.m b/test/Analysis/misc-ps-eager-assume.m index a986b8eca62a..a0323f480ccc 100644 --- a/test/Analysis/misc-ps-eager-assume.m +++ b/test/Analysis/misc-ps-eager-assume.m @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=range -verify -fblocks %s -analyzer-eagerly-assume +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=range -verify -fblocks %s -analyzer-eagerly-assume // Delta-reduced header stuff (needed for test cases). typedef signed char BOOL; diff --git a/test/Analysis/misc-ps-ranges.m b/test/Analysis/misc-ps-ranges.m index b1afc3d3a21c..01a228a5dec2 100644 --- a/test/Analysis/misc-ps-ranges.m +++ b/test/Analysis/misc-ps-ranges.m @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=range -verify -fblocks %s -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=range -verify -fblocks %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=range -verify -fblocks %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=range -verify -fblocks %s // <rdar://problem/6776949> // main's 'argc' argument is always > 0 diff --git a/test/Analysis/misc-ps-region-store-i386.m b/test/Analysis/misc-ps-region-store-i386.m index 026d4f5476f6..90183257d2b2 100644 --- a/test/Analysis/misc-ps-region-store-i386.m +++ b/test/Analysis/misc-ps-region-store-i386.m @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple i386-apple-darwin9 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -verify -fblocks %s +// RUN: %clang_cc1 -triple i386-apple-darwin9 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=region -verify -fblocks %s // Here is a case where a pointer is treated as integer, invalidated as an // integer, and then used again as a pointer. This test just makes sure diff --git a/test/Analysis/misc-ps-region-store-x86_64.m b/test/Analysis/misc-ps-region-store-x86_64.m index e3c6d47348e9..a440bc55ae19 100644 --- a/test/Analysis/misc-ps-region-store-x86_64.m +++ b/test/Analysis/misc-ps-region-store-x86_64.m @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -verify -fblocks %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=region -verify -fblocks %s // Here is a case where a pointer is treated as integer, invalidated as an // integer, and then used again as a pointer. This test just makes sure diff --git a/test/Analysis/misc-ps-region-store.cpp b/test/Analysis/misc-ps-region-store.cpp index 1dba09d76ddc..7c296fd3db9b 100644 --- a/test/Analysis/misc-ps-region-store.cpp +++ b/test/Analysis/misc-ps-region-store.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -triple i386-apple-darwin9 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -verify -fblocks -analyzer-opt-analyze-nested-blocks %s -// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -verify -fblocks -analyzer-opt-analyze-nested-blocks %s +// RUN: %clang_cc1 -triple i386-apple-darwin9 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=region -verify -fblocks -analyzer-opt-analyze-nested-blocks %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=region -verify -fblocks -analyzer-opt-analyze-nested-blocks %s // Test basic handling of references. char &test1_aux(); diff --git a/test/Analysis/misc-ps-region-store.m b/test/Analysis/misc-ps-region-store.m index b35a834c3352..37e1a12c87bd 100644 --- a/test/Analysis/misc-ps-region-store.m +++ b/test/Analysis/misc-ps-region-store.m @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -triple i386-apple-darwin9 -analyze -analyzer-checker=core.experimental.IdempotentOps -analyzer-checker=core.experimental.CastToStruct -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -verify -fblocks -analyzer-opt-analyze-nested-blocks %s -// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -DTEST_64 -analyze -analyzer-checker=core.experimental.IdempotentOps -analyzer-checker=core.experimental.CastToStruct -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -verify -fblocks -analyzer-opt-analyze-nested-blocks %s +// RUN: %clang_cc1 -triple i386-apple-darwin9 -analyze -analyzer-checker=core.experimental.IdempotentOps,core.experimental.CastToStruct,core.experimental.ReturnPtrRange,core.experimental.ReturnPtrRange,core.experimental.ArrayBound -analyzer-check-objc-mem -analyzer-store=region -verify -fblocks -analyzer-opt-analyze-nested-blocks %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -DTEST_64 -analyze -analyzer-checker=core.experimental.IdempotentOps,core.experimental.CastToStruct,core.experimental.ReturnPtrRange,core.experimental.ArrayBound -analyzer-check-objc-mem -analyzer-store=region -verify -fblocks -analyzer-opt-analyze-nested-blocks %s typedef long unsigned int size_t; void *memcpy(void *, const void *, size_t); diff --git a/test/Analysis/misc-ps-region-store.mm b/test/Analysis/misc-ps-region-store.mm index 92addd12f2aa..a2df723c794b 100644 --- a/test/Analysis/misc-ps-region-store.mm +++ b/test/Analysis/misc-ps-region-store.mm @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -triple i386-apple-darwin9 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -verify -fblocks -analyzer-opt-analyze-nested-blocks %s -// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -verify -fblocks -analyzer-opt-analyze-nested-blocks %s +// RUN: %clang_cc1 -triple i386-apple-darwin9 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=region -verify -fblocks -analyzer-opt-analyze-nested-blocks %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=region -verify -fblocks -analyzer-opt-analyze-nested-blocks %s //===------------------------------------------------------------------------------------------===// // This files tests our path-sensitive handling of Objective-c++ files. diff --git a/test/Analysis/misc-ps.m b/test/Analysis/misc-ps.m index 45b44b7412c9..db4fa02ff17c 100644 --- a/test/Analysis/misc-ps.m +++ b/test/Analysis/misc-ps.m @@ -1,12 +1,12 @@ // NOTE: Use '-fobjc-gc' to test the analysis being run twice, and multiple reports are not issued. -// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-checker=core.experimental.IdempotentOps -analyzer-checker=core.experimental.CastToStruct -analyzer-checker=cocoa.AtSync -analyzer-store=basic -fobjc-gc -analyzer-constraints=basic -verify -fblocks -Wno-unreachable-code %s -// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-checker=core.experimental.IdempotentOps -analyzer-checker=core.experimental.CastToStruct -analyzer-checker=cocoa.AtSync -analyzer-store=basic -analyzer-constraints=range -verify -fblocks -Wno-unreachable-code %s -// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-checker=core.experimental.IdempotentOps -analyzer-checker=core.experimental.CastToStruct -analyzer-checker=cocoa.AtSync -analyzer-store=region -analyzer-constraints=basic -verify -fblocks -Wno-unreachable-code %s -// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-checker=core.experimental.IdempotentOps -analyzer-checker=core.experimental.CastToStruct -analyzer-checker=cocoa.AtSync -analyzer-store=region -analyzer-constraints=range -verify -fblocks -Wno-unreachable-code %s -// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-checker=core.experimental.IdempotentOps -analyzer-checker=core.experimental.CastToStruct -analyzer-checker=cocoa.AtSync -analyzer-store=basic -fobjc-gc -analyzer-constraints=basic -verify -fblocks -Wno-unreachable-code %s -// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-checker=core.experimental.IdempotentOps -analyzer-checker=core.experimental.CastToStruct -analyzer-checker=cocoa.AtSync -analyzer-store=basic -analyzer-constraints=range -verify -fblocks -Wno-unreachable-code %s -// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-checker=core.experimental.IdempotentOps -analyzer-checker=core.experimental.CastToStruct -analyzer-checker=cocoa.AtSync -analyzer-store=region -analyzer-constraints=basic -verify -fblocks -Wno-unreachable-code %s -// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-checker=core.experimental.IdempotentOps -analyzer-checker=core.experimental.CastToStruct -analyzer-checker=cocoa.AtSync -analyzer-store=region -analyzer-constraints=range -verify -fblocks -Wno-unreachable-code %s +// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=core.experimental,cocoa.AtSync -analyzer-check-objc-mem -analyzer-store=basic -fobjc-gc -analyzer-constraints=basic -verify -fblocks -Wno-unreachable-code %s +// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=core.experimental,cocoa.AtSync -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=range -verify -fblocks -Wno-unreachable-code %s +// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=core.experimental,cocoa.AtSync -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=basic -verify -fblocks -Wno-unreachable-code %s +// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=core.experimental,cocoa.AtSync -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=range -verify -fblocks -Wno-unreachable-code %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=core.experimental,cocoa.AtSync -analyzer-check-objc-mem -analyzer-store=basic -fobjc-gc -analyzer-constraints=basic -verify -fblocks -Wno-unreachable-code %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=core.experimental,cocoa.AtSync -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=range -verify -fblocks -Wno-unreachable-code %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=core.experimental,cocoa.AtSync -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=basic -verify -fblocks -Wno-unreachable-code %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=core.experimental,cocoa.AtSync -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=range -verify -fblocks -Wno-unreachable-code %s #ifndef __clang_analyzer__ #error __clang__analyzer__ not defined @@ -1233,3 +1233,39 @@ void pr8648() { // crash with assignment y = ({ (union pr8648_union) { .pr8648_union_field = 0LL }; }).pr8648_union_field; } + +// PR 9269 - don't assert when building the following CFG. The for statement +// contains a condition with multiple basic blocks, and the value of the +// statement expression is then indexed as part of a bigger condition expression. +// This example exposed a bug in child traversal in the CFGBuilder. +void pr9269() { + struct s { char *bar[10]; } baz[2] = { 0 }; + unsigned i = 0; + for (i = 0; + (* ({ while(0); ({ &baz[0]; }); })).bar[0] != 0; + ++i) {} +} + +// Test evaluation of GNU-style ?:. +int pr9287(int type) { return type ? : 0; } // no-warning + +void pr9287_b(int type, int *p) { + int x = type ? : 0; + if (x) { + p = 0; + } + if (type) { + *p = 0xDEADBEEF; // expected-warning {{null pointer}} + } +} + +void pr9287_c(int type, int *p) { + int x = type ? : 0; + if (x) { + p = 0; + } + if (!type) { + *p = 0xDEADBEEF; // no-warning + } +} + diff --git a/test/Analysis/nil-receiver-undefined-larger-than-voidptr-ret-region.m b/test/Analysis/nil-receiver-undefined-larger-than-voidptr-ret-region.m index 4c754fb951ad..eeab4312fe9c 100644 --- a/test/Analysis/nil-receiver-undefined-larger-than-voidptr-ret-region.m +++ b/test/Analysis/nil-receiver-undefined-larger-than-voidptr-ret-region.m @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple i386-apple-darwin8 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-constraints=range -analyzer-store=region -verify %s +// RUN: %clang_cc1 -triple i386-apple-darwin8 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-constraints=range -analyzer-store=region -verify %s // <rdar://problem/6888289> - This test case shows that a nil instance // variable can possibly be initialized by a method. diff --git a/test/Analysis/nil-receiver-undefined-larger-than-voidptr-ret.m b/test/Analysis/nil-receiver-undefined-larger-than-voidptr-ret.m index 6c8f525eb375..4ba1015c9a1d 100644 --- a/test/Analysis/nil-receiver-undefined-larger-than-voidptr-ret.m +++ b/test/Analysis/nil-receiver-undefined-larger-than-voidptr-ret.m @@ -1,9 +1,9 @@ -// RUN: %clang_cc1 -triple i386-apple-darwin8 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-constraints=basic -analyzer-store=basic %s 2>&1 | FileCheck -check-prefix=darwin8 %s -// RUN: %clang_cc1 -triple i386-apple-darwin8 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-constraints=basic -analyzer-store=region %s 2>&1 | FileCheck -check-prefix=darwin8 %s -// RUN: %clang_cc1 -triple i386-apple-darwin9 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-constraints=basic -analyzer-store=basic %s 2>&1 | FileCheck -check-prefix=darwin9 %s -// RUN: %clang_cc1 -triple i386-apple-darwin9 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-constraints=basic -analyzer-store=region %s 2>&1 | FileCheck -check-prefix=darwin9 %s -// RUN: %clang_cc1 -triple thumbv6-apple-darwin4.0.0-iphoneos -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-constraints=basic -analyzer-store=basic %s 2>&1 | FileCheck -check-prefix=darwin9 %s -// RUN: %clang_cc1 -triple thumbv6-apple-darwin4.0.0-iphoneos -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-constraints=basic -analyzer-store=region %s 2>&1 | FileCheck -check-prefix=darwin9 %s +// RUN: %clang_cc1 -triple i386-apple-darwin8 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-constraints=basic -analyzer-store=basic %s 2>&1 | FileCheck -check-prefix=darwin8 %s +// RUN: %clang_cc1 -triple i386-apple-darwin8 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-constraints=basic -analyzer-store=region %s 2>&1 | FileCheck -check-prefix=darwin8 %s +// RUN: %clang_cc1 -triple i386-apple-darwin9 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-constraints=basic -analyzer-store=basic %s 2>&1 | FileCheck -check-prefix=darwin9 %s +// RUN: %clang_cc1 -triple i386-apple-darwin9 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-constraints=basic -analyzer-store=region %s 2>&1 | FileCheck -check-prefix=darwin9 %s +// RUN: %clang_cc1 -triple thumbv6-apple-darwin4.0.0-iphoneos -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-constraints=basic -analyzer-store=basic %s 2>&1 | FileCheck -check-prefix=darwin9 %s +// RUN: %clang_cc1 -triple thumbv6-apple-darwin4.0.0-iphoneos -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-constraints=basic -analyzer-store=region %s 2>&1 | FileCheck -check-prefix=darwin9 %s @interface MyClass {} - (void *)voidPtrM; diff --git a/test/Analysis/no-exit-cfg.c b/test/Analysis/no-exit-cfg.c index 659f675efc0b..2924aaeffff5 100644 --- a/test/Analysis/no-exit-cfg.c +++ b/test/Analysis/no-exit-cfg.c @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=basic -verify %s -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=basic -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=region -verify %s // This is a test case for the issue reported in PR 2819: // http://llvm.org/bugs/show_bug.cgi?id=2819 diff --git a/test/Analysis/no-outofbounds.c b/test/Analysis/no-outofbounds.c index a97b68e2d6df..92cb8b327110 100644 --- a/test/Analysis/no-outofbounds.c +++ b/test/Analysis/no-outofbounds.c @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -analyzer-check-objc-mem -analyze -analyzer-experimental-internal-checks -analyzer-store=basic -verify %s -// RUN: %clang_cc1 -analyzer-check-objc-mem -analyze -analyzer-experimental-internal-checks -analyzer-store=region -verify %s +// RUN: %clang_cc1 -analyzer-check-objc-mem -analyze -analyzer-checker=core.experimental -analyzer-store=basic -verify %s +// RUN: %clang_cc1 -analyzer-check-objc-mem -analyze -analyzer-checker=core.experimental -analyzer-store=region -verify %s //===----------------------------------------------------------------------===// // This file tests cases where we should not flag out-of-bounds warnings. diff --git a/test/Analysis/null-deref-ps-region.c b/test/Analysis/null-deref-ps-region.c index 0199d20fdbb2..df498ce5e622 100644 --- a/test/Analysis/null-deref-ps-region.c +++ b/test/Analysis/null-deref-ps-region.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -std=gnu99 -analyzer-check-objc-mem -analyzer-store=region -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -std=gnu99 -analyzer-check-objc-mem -analyzer-store=region -verify %s // The store for 'a[1]' should not be removed mistakenly. SymbolicRegions may diff --git a/test/Analysis/null-deref-ps.c b/test/Analysis/null-deref-ps.c index 5db4923cd34d..27f648770c94 100644 --- a/test/Analysis/null-deref-ps.c +++ b/test/Analysis/null-deref-ps.c @@ -1,7 +1,7 @@ -// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=core.experimental.IdempotentOps -analyzer-experimental-internal-checks -std=gnu99 -analyzer-check-objc-mem -verify %s -analyzer-constraints=basic -analyzer-store=basic -Wreturn-type -// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=core.experimental.IdempotentOps -analyzer-experimental-internal-checks -std=gnu99 -analyzer-check-objc-mem -verify %s -analyzer-constraints=range -analyzer-store=basic -Wreturn-type -// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=core.experimental.IdempotentOps -analyzer-experimental-internal-checks -std=gnu99 -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=range -analyzer-no-purge-dead -verify %s -Wreturn-type -// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=core.experimental.IdempotentOps -analyzer-experimental-internal-checks -std=gnu99 -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=range -verify %s -Wreturn-type +// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=core.experimental -std=gnu99 -analyzer-check-objc-mem -verify %s -analyzer-constraints=basic -analyzer-store=basic -Wreturn-type +// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=core.experimental -std=gnu99 -analyzer-check-objc-mem -verify %s -analyzer-constraints=range -analyzer-store=basic -Wreturn-type +// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=core.experimental -std=gnu99 -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=range -analyzer-no-purge-dead -verify %s -Wreturn-type +// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=core.experimental -std=gnu99 -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=range -verify %s -Wreturn-type typedef unsigned uintptr_t; diff --git a/test/Analysis/operator-calls.cpp b/test/Analysis/operator-calls.cpp index 892a1ab0769f..97d54226f055 100644 --- a/test/Analysis/operator-calls.cpp +++ b/test/Analysis/operator-calls.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-experimental-checks -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-experimental-checks -verify %s struct X0 { }; bool operator==(const X0&, const X0&); diff --git a/test/Analysis/outofbound.c b/test/Analysis/outofbound.c index 3b261bbb5ca8..4508198b5292 100644 --- a/test/Analysis/outofbound.c +++ b/test/Analysis/outofbound.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -Wno-array-bounds -analyze -analyzer-experimental-internal-checks -analyzer-experimental-checks -analyzer-check-objc-mem -analyzer-store=region -verify %s +// RUN: %clang_cc1 -Wno-array-bounds -analyze -analyzer-checker=core.experimental -analyzer-experimental-checks -analyzer-check-objc-mem -analyzer-store=region -verify %s typedef __typeof(sizeof(int)) size_t; void *malloc(size_t); diff --git a/test/Analysis/override-werror.c b/test/Analysis/override-werror.c index f4854bb819ad..ce0f1ac9abe6 100644 --- a/test/Analysis/override-werror.c +++ b/test/Analysis/override-werror.c @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -Werror %s -analyzer-store=basic -verify -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -Werror %s -analyzer-store=region -verify +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -Werror %s -analyzer-store=basic -verify +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -Werror %s -analyzer-store=region -verify // This test case illustrates that using '-analyze' overrides the effect of // -Werror. This allows basic warnings not to interfere with producing diff --git a/test/Analysis/plist-output-alternate.m b/test/Analysis/plist-output-alternate.m index 12697b4c6c8d..7b8c2673b085 100644 --- a/test/Analysis/plist-output-alternate.m +++ b/test/Analysis/plist-output-alternate.m @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=range -fblocks -analyzer-output=plist -o - %s | FileCheck %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=range -fblocks -analyzer-output=plist -o - %s | FileCheck %s void test_null_init(void) { int *p = 0; diff --git a/test/Analysis/plist-output.m b/test/Analysis/plist-output.m index ec4f770cb245..2224a2fbb859 100644 --- a/test/Analysis/plist-output.m +++ b/test/Analysis/plist-output.m @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=range -fblocks -analyzer-output=plist -o - %s | FileCheck %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=range -fblocks -analyzer-output=plist -o - %s | FileCheck %s // XFAIL: * void test_null_init(void) { diff --git a/test/Analysis/pr4209.m b/test/Analysis/pr4209.m index dc1ef7b9997f..9ce07edcb02b 100644 --- a/test/Analysis/pr4209.m +++ b/test/Analysis/pr4209.m @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -triple i386-apple-darwin9 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=basic -verify %s -// RUN: %clang_cc1 -triple i386-apple-darwin9 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -verify %s +// RUN: %clang_cc1 -triple i386-apple-darwin9 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=basic -verify %s +// RUN: %clang_cc1 -triple i386-apple-darwin9 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=region -verify %s // This test case was crashing due to how CFRefCount.cpp resolved the // ObjCInterfaceDecl* and ClassName in EvalObjCMessageExpr. diff --git a/test/Analysis/pr_2542_rdar_6793404.m b/test/Analysis/pr_2542_rdar_6793404.m index feafe2ac8a1f..46b7fd36a64a 100644 --- a/test/Analysis/pr_2542_rdar_6793404.m +++ b/test/Analysis/pr_2542_rdar_6793404.m @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -pedantic -analyzer-store=basic -verify %s -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -pedantic -analyzer-store=region -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -pedantic -analyzer-store=basic -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -pedantic -analyzer-store=region -verify %s // BEGIN delta-debugging reduced header stuff diff --git a/test/Analysis/pr_4164.c b/test/Analysis/pr_4164.c index e8a410ff1372..ee5d4028e7d3 100644 --- a/test/Analysis/pr_4164.c +++ b/test/Analysis/pr_4164.c @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=basic -verify %s -// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -verify %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=basic -verify %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=region -verify %s // PR 4164: http://llvm.org/bugs/show_bug.cgi?id=4164 // diff --git a/test/Analysis/ptr-arith.c b/test/Analysis/ptr-arith.c index 044d72aeef16..fe378957531b 100644 --- a/test/Analysis/ptr-arith.c +++ b/test/Analysis/ptr-arith.c @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental.FixedAddr -analyzer-checker=core.experimental.PointerArithm -analyzer-checker=core.experimental.PointerSub -analyzer-check-objc-mem -analyzer-store=region -verify -triple x86_64-apple-darwin9 %s -// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental.FixedAddr -analyzer-checker=core.experimental.PointerArithm -analyzer-checker=core.experimental.PointerSub -analyzer-check-objc-mem -analyzer-store=region -verify -triple i686-apple-darwin9 %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental.FixedAddr,core.experimental.PointerArithm,core.experimental.PointerSub -analyzer-check-objc-mem -analyzer-store=region -verify -triple x86_64-apple-darwin9 %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental.FixedAddr,core.experimental.PointerArithm,core.experimental.PointerSub -analyzer-check-objc-mem -analyzer-store=region -verify -triple i686-apple-darwin9 %s // Used to trigger warnings for unreachable paths. #define WARN do { int a, b; int c = &b-&a; } while (0) diff --git a/test/Analysis/rdar-6442306-1.m b/test/Analysis/rdar-6442306-1.m index 0d35f23328ad..086cdd8d51b0 100644 --- a/test/Analysis/rdar-6442306-1.m +++ b/test/Analysis/rdar-6442306-1.m @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem %s -analyzer-store=basic -verify -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem %s -analyzer-store=region -verify +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem %s -analyzer-store=basic -verify +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem %s -analyzer-store=region -verify typedef int bar_return_t; typedef struct { diff --git a/test/Analysis/rdar-6540084.m b/test/Analysis/rdar-6540084.m index d6a03b6f9880..7ce73bc48da0 100644 --- a/test/Analysis/rdar-6540084.m +++ b/test/Analysis/rdar-6540084.m @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-checker=core.DeadStores -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-checker=core.DeadStores -verify %s // // This test exercises the live variables analysis (LiveVariables.cpp). // The case originally identified a non-termination bug. diff --git a/test/Analysis/rdar-6541136-region.c b/test/Analysis/rdar-6541136-region.c index 82232c6bb97d..d8d1e996a5fa 100644 --- a/test/Analysis/rdar-6541136-region.c +++ b/test/Analysis/rdar-6541136-region.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -verify -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region %s +// RUN: %clang_cc1 -verify -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=region %s struct tea_cheese { unsigned magic; }; typedef struct tea_cheese kernel_tea_cheese_t; diff --git a/test/Analysis/rdar-6541136.c b/test/Analysis/rdar-6541136.c index 844a9367b431..a175497fcba6 100644 --- a/test/Analysis/rdar-6541136.c +++ b/test/Analysis/rdar-6541136.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -verify -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=basic %s +// RUN: %clang_cc1 -verify -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=basic %s struct tea_cheese { unsigned magic; }; typedef struct tea_cheese kernel_tea_cheese_t; diff --git a/test/Analysis/rdar-6562655.m b/test/Analysis/rdar-6562655.m index 2aa22294172c..19b2697b3831 100644 --- a/test/Analysis/rdar-6562655.m +++ b/test/Analysis/rdar-6562655.m @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-constraints=basic -analyzer-store=basic -verify %s -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-constraints=basic -analyzer-store=region -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-constraints=basic -analyzer-store=basic -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-constraints=basic -analyzer-store=region -verify %s // // This test case mainly checks that the retain/release checker doesn't crash // on this file. diff --git a/test/Analysis/rdar-6582778-basic-store.c b/test/Analysis/rdar-6582778-basic-store.c index ff32372f44fc..a545d8b6ac70 100644 --- a/test/Analysis/rdar-6582778-basic-store.c +++ b/test/Analysis/rdar-6582778-basic-store.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=basic -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=basic -verify %s typedef const void * CFTypeRef; typedef double CFTimeInterval; diff --git a/test/Analysis/rdar-6600344-nil-receiver-undefined-struct-ret.m b/test/Analysis/rdar-6600344-nil-receiver-undefined-struct-ret.m index 838a98b2b79d..4932a526fc4c 100644 --- a/test/Analysis/rdar-6600344-nil-receiver-undefined-struct-ret.m +++ b/test/Analysis/rdar-6600344-nil-receiver-undefined-struct-ret.m @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-constraints=basic -analyzer-store=basic %s -verify -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-constraints=basic -analyzer-store=region %s -verify +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-constraints=basic -analyzer-store=basic %s -verify +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-constraints=basic -analyzer-store=region %s -verify typedef struct Foo { int x; } Bar; diff --git a/test/Analysis/rdar-7168531.m b/test/Analysis/rdar-7168531.m index 5a7b08584f57..8225cd36539f 100644 --- a/test/Analysis/rdar-7168531.m +++ b/test/Analysis/rdar-7168531.m @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -triple i386-apple-darwin10 -analyzer-store=region %s -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -triple i386-apple-darwin10 -analyzer-store=basic %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -triple i386-apple-darwin10 -analyzer-store=region %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -triple i386-apple-darwin10 -analyzer-store=basic %s // Note that the target triple is important for this test case. It specifies that we use the // fragile Objective-C ABI. diff --git a/test/Analysis/refcnt_naming.m b/test/Analysis/refcnt_naming.m index 7299001051c8..4fe6d19f1cbf 100644 --- a/test/Analysis/refcnt_naming.m +++ b/test/Analysis/refcnt_naming.m @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=basic -verify %s -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=basic -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=region -verify %s typedef const struct __CFString * CFStringRef; typedef const struct __CFAllocator * CFAllocatorRef; diff --git a/test/Analysis/reference.cpp b/test/Analysis/reference.cpp index 51c8aae66c1e..b01d70825a1f 100644 --- a/test/Analysis/reference.cpp +++ b/test/Analysis/reference.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=range -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=range -verify %s typedef typeof(sizeof(int)) size_t; void malloc (size_t); diff --git a/test/Analysis/region-1.m b/test/Analysis/region-1.m index 9274cfc81403..7770d29cfab9 100644 --- a/test/Analysis/region-1.m +++ b/test/Analysis/region-1.m @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=basic -verify %s -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=basic -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-store=region -verify %s // // This test case simply should not crash. It evaluates the logic of not // using MemRegion::getRValueType in incorrect places. diff --git a/test/Analysis/retain-release-basic-store.m b/test/Analysis/retain-release-basic-store.m index 751dca0ce30b..8c05efef66ee 100644 --- a/test/Analysis/retain-release-basic-store.m +++ b/test/Analysis/retain-release-basic-store.m @@ -69,7 +69,7 @@ extern DADiskRef DADiskCopyWholeDisk( DADiskRef disk ); @interface NSAppleEventManager : NSObject { } @end enum { -kDAReturnSuccess = 0, kDAReturnError = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x01, kDAReturnBusy = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x02, kDAReturnBadArgument = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x03, kDAReturnExclusiveAccess = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x04, kDAReturnNoResources = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x05, kDAReturnNotFound = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x06, kDAReturnNotMounted = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x07, kDAReturnNotPermitted = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x08, kDAReturnNotPrivileged = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x09, kDAReturnNotReady = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0A, kDAReturnNotWritable = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0B, kDAReturnUnsupported = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0C }; +kDAReturnSuccess = 0, kDAReturnError = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x01, kDAReturnBusy = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x02, kDAReturnBadArgument = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x03, kDAReturnExclusiveAccess = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x04, kDAReturnNoResources = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x05, kDAReturnNotFound = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x06, kDAReturnNotMounted = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x07, kDAReturnNotPermitted = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x08, kDAReturnNotPrivileged = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x09, kDAReturnNotReady = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0A, kDAReturnNotWritable = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0B, kDAReturnUnsupported = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0C }; typedef mach_error_t DAReturn; typedef const struct __DADissenter * DADissenterRef; extern DADissenterRef DADissenterCreate( CFAllocatorRef allocator, DAReturn status, CFStringRef string ); diff --git a/test/Analysis/retain-release-gc-only.m b/test/Analysis/retain-release-gc-only.m index 6f1dd92df997..7d7c58fbcd51 100644 --- a/test/Analysis/retain-release-gc-only.m +++ b/test/Analysis/retain-release-gc-only.m @@ -189,7 +189,7 @@ CVTimeStamp; } typedef int CIFormat; @end enum { -kDAReturnSuccess = 0, kDAReturnError = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x01, kDAReturnBusy = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x02, kDAReturnBadArgument = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x03, kDAReturnExclusiveAccess = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x04, kDAReturnNoResources = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x05, kDAReturnNotFound = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x06, kDAReturnNotMounted = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x07, kDAReturnNotPermitted = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x08, kDAReturnNotPrivileged = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x09, kDAReturnNotReady = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0A, kDAReturnNotWritable = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0B, kDAReturnUnsupported = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0C }; +kDAReturnSuccess = 0, kDAReturnError = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x01, kDAReturnBusy = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x02, kDAReturnBadArgument = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x03, kDAReturnExclusiveAccess = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x04, kDAReturnNoResources = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x05, kDAReturnNotFound = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x06, kDAReturnNotMounted = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x07, kDAReturnNotPermitted = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x08, kDAReturnNotPrivileged = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x09, kDAReturnNotReady = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0A, kDAReturnNotWritable = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0B, kDAReturnUnsupported = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0C }; typedef mach_error_t DAReturn; typedef const struct __DADissenter * DADissenterRef; extern DADissenterRef DADissenterCreate( CFAllocatorRef allocator, DAReturn status, CFStringRef string ); diff --git a/test/Analysis/retain-release-region-store.m b/test/Analysis/retain-release-region-store.m index 05b91fcf5c56..ec765e3fe809 100644 --- a/test/Analysis/retain-release-region-store.m +++ b/test/Analysis/retain-release-region-store.m @@ -75,7 +75,7 @@ extern DADiskRef DADiskCopyWholeDisk( DADiskRef disk ); @interface NSAppleEventManager : NSObject { } @end enum { -kDAReturnSuccess = 0, kDAReturnError = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x01, kDAReturnBusy = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x02, kDAReturnBadArgument = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x03, kDAReturnExclusiveAccess = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x04, kDAReturnNoResources = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x05, kDAReturnNotFound = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x06, kDAReturnNotMounted = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x07, kDAReturnNotPermitted = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x08, kDAReturnNotPrivileged = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x09, kDAReturnNotReady = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0A, kDAReturnNotWritable = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0B, kDAReturnUnsupported = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0C }; +kDAReturnSuccess = 0, kDAReturnError = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x01, kDAReturnBusy = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x02, kDAReturnBadArgument = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x03, kDAReturnExclusiveAccess = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x04, kDAReturnNoResources = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x05, kDAReturnNotFound = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x06, kDAReturnNotMounted = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x07, kDAReturnNotPermitted = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x08, kDAReturnNotPrivileged = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x09, kDAReturnNotReady = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0A, kDAReturnNotWritable = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0B, kDAReturnUnsupported = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0C }; typedef mach_error_t DAReturn; typedef const struct __DADissenter * DADissenterRef; extern DADissenterRef DADissenterCreate( CFAllocatorRef allocator, DAReturn status, CFStringRef string ); diff --git a/test/Analysis/retain-release.m b/test/Analysis/retain-release.m index 81e015f5fc44..5cc29b0f866b 100644 --- a/test/Analysis/retain-release.m +++ b/test/Analysis/retain-release.m @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=macosx.CFRetainRelease -analyzer-checker=cocoa.ClassRelease -analyzer-check-objc-mem -analyzer-store=basic -fblocks -verify %s -// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=macosx.CFRetainRelease -analyzer-checker=cocoa.ClassRelease -analyzer-check-objc-mem -analyzer-store=region -fblocks -verify %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=macosx.CFRetainRelease,cocoa.ClassRelease -analyzer-check-objc-mem -analyzer-store=basic -fblocks -verify %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=macosx.CFRetainRelease,cocoa.ClassRelease -analyzer-check-objc-mem -analyzer-store=region -fblocks -verify %s #if __has_feature(attribute_ns_returns_retained) #define NS_RETURNS_RETAINED __attribute__((ns_returns_retained)) @@ -217,7 +217,7 @@ CVTimeStamp; } typedef int CIFormat; @end enum { -kDAReturnSuccess = 0, kDAReturnError = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x01, kDAReturnBusy = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x02, kDAReturnBadArgument = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x03, kDAReturnExclusiveAccess = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x04, kDAReturnNoResources = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x05, kDAReturnNotFound = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x06, kDAReturnNotMounted = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x07, kDAReturnNotPermitted = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x08, kDAReturnNotPrivileged = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x09, kDAReturnNotReady = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0A, kDAReturnNotWritable = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0B, kDAReturnUnsupported = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0C }; +kDAReturnSuccess = 0, kDAReturnError = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x01, kDAReturnBusy = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x02, kDAReturnBadArgument = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x03, kDAReturnExclusiveAccess = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x04, kDAReturnNoResources = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x05, kDAReturnNotFound = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x06, kDAReturnNotMounted = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x07, kDAReturnNotPermitted = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x08, kDAReturnNotPrivileged = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x09, kDAReturnNotReady = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0A, kDAReturnNotWritable = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0B, kDAReturnUnsupported = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0C }; typedef mach_error_t DAReturn; typedef const struct __DADissenter * DADissenterRef; extern DADissenterRef DADissenterCreate( CFAllocatorRef allocator, DAReturn status, CFStringRef string ); diff --git a/test/Analysis/stack-addr-ps.c b/test/Analysis/stack-addr-ps.c index 0ee843408085..8e7e7dfd9a40 100644 --- a/test/Analysis/stack-addr-ps.c +++ b/test/Analysis/stack-addr-ps.c @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -analyze -analyzer-check-objc-mem -analyzer-checker=core.StackAddrLeak -analyzer-store=basic -fblocks -verify %s -// RUN: %clang_cc1 -analyze -analyzer-check-objc-mem -analyzer-checker=core.StackAddrLeak -analyzer-store=region -fblocks -verify %s +// RUN: %clang_cc1 -analyze -analyzer-check-objc-mem -analyzer-checker=core.StackAddrEscape -analyzer-store=basic -fblocks -verify %s +// RUN: %clang_cc1 -analyze -analyzer-check-objc-mem -analyzer-checker=core.StackAddrEscape -analyzer-store=region -fblocks -verify %s int* f1() { int x = 0; diff --git a/test/Analysis/stackaddrleak.c b/test/Analysis/stackaddrleak.c index 359e482c8cff..f19eddc811e8 100644 --- a/test/Analysis/stackaddrleak.c +++ b/test/Analysis/stackaddrleak.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -analyze -analyzer-check-objc-mem -analyzer-checker=core.StackAddrLeak -analyzer-store region -verify %s +// RUN: %clang_cc1 -analyze -analyzer-check-objc-mem -analyzer-checker=core.StackAddrEscape -analyzer-store region -verify %s char const *p; diff --git a/test/Analysis/string.c b/test/Analysis/string.c index baf48930d7e8..756115180cab 100644 --- a/test/Analysis/string.c +++ b/test/Analysis/string.c @@ -1,7 +1,7 @@ -// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental.CString -analyzer-checker=core.experimental.UnreachableCode -analyzer-check-objc-mem -analyzer-store=region -verify %s -// RUN: %clang_cc1 -analyze -DUSE_BUILTINS -analyzer-checker=core.experimental.CString -analyzer-checker=core.experimental.UnreachableCode -analyzer-check-objc-mem -analyzer-store=region -verify %s -// RUN: %clang_cc1 -analyze -DVARIANT -analyzer-checker=core.experimental.CString -analyzer-checker=core.experimental.UnreachableCode -analyzer-check-objc-mem -analyzer-store=region -verify %s -// RUN: %clang_cc1 -analyze -DUSE_BUILTINS -DVARIANT -analyzer-checker=core.experimental.CString -analyzer-checker=core.experimental.UnreachableCode -analyzer-check-objc-mem -analyzer-store=region -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental.CString,core.experimental.UnreachableCode -analyzer-check-objc-mem -analyzer-store=region -verify %s +// RUN: %clang_cc1 -analyze -DUSE_BUILTINS -analyzer-checker=core.experimental.CString,core.experimental.UnreachableCode -analyzer-check-objc-mem -analyzer-store=region -verify %s +// RUN: %clang_cc1 -analyze -DVARIANT -analyzer-checker=core.experimental.CString,core.experimental.UnreachableCode -analyzer-check-objc-mem -analyzer-store=region -verify %s +// RUN: %clang_cc1 -analyze -DUSE_BUILTINS -DVARIANT -analyzer-checker=core.experimental.CString,core.experimental.UnreachableCode -analyzer-check-objc-mem -analyzer-store=region -verify %s //===----------------------------------------------------------------------=== // Declarations @@ -140,6 +140,138 @@ void strlen_liveness(const char *x) { } //===----------------------------------------------------------------------=== +// strnlen() +//===----------------------------------------------------------------------=== + +#define strnlen BUILTIN(strnlen) +size_t strnlen(const char *s, size_t maxlen); + +void strnlen_constant0() { + if (strnlen("123", 10) != 3) + (void)*(char*)0; // no-warning +} + +void strnlen_constant1() { + const char *a = "123"; + if (strnlen(a, 10) != 3) + (void)*(char*)0; // no-warning +} + +void strnlen_constant2(char x) { + char a[] = "123"; + if (strnlen(a, 10) != 3) + (void)*(char*)0; // no-warning + a[0] = x; + if (strnlen(a, 10) != 3) + (void)*(char*)0; // expected-warning{{null}} +} + +void strnlen_constant4() { + if (strnlen("123456", 3) != 3) + (void)*(char*)0; // no-warning +} + +void strnlen_constant5() { + const char *a = "123456"; + if (strnlen(a, 3) != 3) + (void)*(char*)0; // no-warning +} + +void strnlen_constant6(char x) { + char a[] = "123456"; + if (strnlen(a, 3) != 3) + (void)*(char*)0; // no-warning + a[0] = x; + if (strnlen(a, 3) != 3) + (void)*(char*)0; // expected-warning{{null}} +} + +size_t strnlen_null() { + return strnlen(0, 3); // expected-warning{{Null pointer argument in call to byte string function}} +} + +size_t strnlen_fn() { + return strnlen((char*)&strlen_fn, 3); // expected-warning{{Argument to byte string function is the address of the function 'strlen_fn', which is not a null-terminated string}} +} + +size_t strnlen_nonloc() { +label: + return strnlen((char*)&&label, 3); // expected-warning{{Argument to byte string function is the address of the label 'label', which is not a null-terminated string}} +} + +void strnlen_subregion() { + struct two_stringsn { char a[2], b[2] }; + extern void use_two_stringsn(struct two_stringsn *); + + struct two_stringsn z; + use_two_stringsn(&z); + + size_t a = strnlen(z.a, 10); + z.b[0] = 5; + size_t b = strnlen(z.a, 10); + if (a == 0 && b != 0) + (void)*(char*)0; // expected-warning{{never executed}} + + use_two_stringsn(&z); + + size_t c = strnlen(z.a, 10); + if (a == 0 && c != 0) + (void)*(char*)0; // expected-warning{{null}} +} + +extern void use_stringn(char *); +void strnlen_argument(char *x) { + size_t a = strnlen(x, 10); + size_t b = strnlen(x, 10); + if (a == 0 && b != 0) + (void)*(char*)0; // expected-warning{{never executed}} + + use_stringn(x); + + size_t c = strnlen(x, 10); + if (a == 0 && c != 0) + (void)*(char*)0; // expected-warning{{null}} +} + +extern char global_strn[]; +void strnlen_global() { + size_t a = strnlen(global_strn, 10); + size_t b = strnlen(global_strn, 10); + if (a == 0 && b != 0) + (void)*(char*)0; // expected-warning{{never executed}} + + // Call a function with unknown effects, which should invalidate globals. + use_stringn(0); + + size_t c = strnlen(global_str, 10); + if (a == 0 && c != 0) + (void)*(char*)0; // expected-warning{{null}} +} + +void strnlen_indirect(char *x) { + size_t a = strnlen(x, 10); + char *p = x; + char **p2 = &p; + size_t b = strnlen(x, 10); + if (a == 0 && b != 0) + (void)*(char*)0; // expected-warning{{never executed}} + + extern void use_stringn_ptr(char*const*); + use_stringn_ptr(p2); + + size_t c = strnlen(x, 10); + if (a == 0 && c != 0) + (void)*(char*)0; // expected-warning{{null}} +} + +void strnlen_liveness(const char *x) { + if (strnlen(x, 10) < 5) + return; + if (strnlen(x, 10) < 5) + (void)*(char*)0; // no-warning +} + +//===----------------------------------------------------------------------=== // strcpy() //===----------------------------------------------------------------------=== @@ -196,6 +328,74 @@ void strcpy_no_overflow(char *y) { } //===----------------------------------------------------------------------=== +// strncpy() +//===----------------------------------------------------------------------=== + +#ifdef VARIANT + +#define __strncpy_chk BUILTIN(__strncpy_chk) +char *__strncpy_chk(char *restrict s1, const char *restrict s2, size_t n, size_t destlen); + +#define strncpy(a,b,c) __strncpy_chk(a,b,c, (size_t)-1) + +#else /* VARIANT */ + +#define strncpy BUILTIN(strncpy) +char *strncpy(char *restrict s1, const char *restrict s2, size_t n); + +#endif /* VARIANT */ + + +void strncpy_null_dst(char *x) { + strncpy(NULL, x, 1); // expected-warning{{Null pointer argument in call to byte string function}} +} + +void strncpy_null_src(char *x) { + strncpy(x, NULL, 1); // expected-warning{{Null pointer argument in call to byte string function}} +} + +void strncpy_fn(char *x) { + strncpy(x, (char*)&strncpy_fn, 1); // expected-warning{{Argument to byte string function is the address of the function 'strncpy_fn', which is not a null-terminated string}} +} + +void strncpy_effects(char *x, char *y) { + char a = x[0]; + + if (strncpy(x, y, strlen(y)) != x) + (void)*(char*)0; // no-warning + + if (strlen(x) != strlen(y)) + (void)*(char*)0; // no-warning + + if (a != x[0]) + (void)*(char*)0; // expected-warning{{null}} +} + +void strncpy_overflow(char *y) { + char x[4]; + if (strlen(y) == 4) + strncpy(x, y, strlen(y)); // expected-warning{{Byte string function overflows destination buffer}} +} + +void strncpy_len_overflow(char *y) { + char x[4]; + if (strlen(y) == 3) + strncpy(x, y, sizeof(x)); // no-warning +} + +void strncpy_no_overflow(char *y) { + char x[4]; + if (strlen(y) == 3) + strncpy(x, y, strlen(y)); // no-warning +} + +void strncpy_no_len_overflow(char *y) { + char x[4]; + if (strlen(y) == 4) + strncpy(x, y, sizeof(x)-1); // no-warning +} + +//===----------------------------------------------------------------------=== // stpcpy() //===----------------------------------------------------------------------=== diff --git a/test/Analysis/undef-buffers.c b/test/Analysis/undef-buffers.c index 4c5beb320ac9..27c3b8df8411 100644 --- a/test/Analysis/undef-buffers.c +++ b/test/Analysis/undef-buffers.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-experimental-checks -analyzer-store=region -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental -analyzer-check-objc-mem -analyzer-experimental-checks -analyzer-store=region -verify %s typedef __typeof(sizeof(int)) size_t; void *malloc(size_t); void free(void *); diff --git a/test/Analysis/unix-fns.c b/test/Analysis/unix-fns.c index 9f5362d184ff..656a1c9c1340 100644 --- a/test/Analysis/unix-fns.c +++ b/test/Analysis/unix-fns.c @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-check-objc-mem -analyzer-checker=unix.API -analyzer-checker=macosx.API %s -analyzer-store=region -fblocks -verify -// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-check-objc-mem -analyzer-checker=unix.API -analyzer-checker=macosx.API %s -analyzer-store=basic -fblocks -verify +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-check-objc-mem -analyzer-checker=unix.API,macosx.API %s -analyzer-store=region -fblocks -verify +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-check-objc-mem -analyzer-checker=unix.API,macosx.API %s -analyzer-store=basic -fblocks -verify struct _opaque_pthread_once_t { long __sig; diff --git a/test/Analysis/unreachable-code-path.c b/test/Analysis/unreachable-code-path.c index 52e6d3df2c01..6ae0822c7344 100644 --- a/test/Analysis/unreachable-code-path.c +++ b/test/Analysis/unreachable-code-path.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental.UnreachableCode -analyzer-check-objc-mem -analyzer-checker=core.DeadStores -verify -analyzer-opt-analyze-nested-blocks -Wno-unused-value %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core.DeadStores,core.experimental.UnreachableCode -analyzer-check-objc-mem -verify -analyzer-opt-analyze-nested-blocks -Wno-unused-value %s extern void foo(int a); diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index a32b9943c2a6..544ed3d9d9c7 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -54,6 +54,10 @@ if(PYTHONINTERP_FOUND) set(LIT "${LLVM_SOURCE_DIR}/utils/lit/lit.py") else() set(LIT "${PATH_TO_LLVM_BUILD}/bin/${CMAKE_CFG_INTDIR}/llvm-lit") + # Installed LLVM does not contain ${CMAKE_CFG_INTDIR} in paths. + if( NOT EXISTS ${LIT} ) + set(LIT "${PATH_TO_LLVM_BUILD}/bin/llvm-lit") + endif() endif() if( PATH_TO_LLVM_BUILD ) @@ -69,6 +73,7 @@ if(PYTHONINTERP_FOUND) separate_arguments(LIT_ARGS) add_custom_target(clang-test.deps) + set_target_properties(clang-test.deps PROPERTIES FOLDER "Clang tests") foreach(testdir ${CLANG_TEST_DIRECTORIES}) add_custom_target(clang-test-${testdir} @@ -80,6 +85,7 @@ if(PYTHONINTERP_FOUND) ${CMAKE_CURRENT_BINARY_DIR}/${testdir} DEPENDS clang c-index-test FileCheck not count COMMENT "Running Clang regression tests in ${testdir}") + set_target_properties(clang-test-${testdir} PROPERTIES FOLDER "Clang tests") endforeach() add_custom_target(clang-test @@ -92,6 +98,7 @@ if(PYTHONINTERP_FOUND) ${LIT_ARGS} ${CMAKE_CURRENT_BINARY_DIR} COMMENT "Running Clang regression tests") + set_target_properties(clang-test PROPERTIES FOLDER "Clang tests") add_custom_target(clang-c++tests COMMAND ${PYTHON_EXECUTABLE} @@ -102,6 +109,7 @@ if(PYTHONINTERP_FOUND) ${CMAKE_CURRENT_SOURCE_DIR}/../utils/C++Tests DEPENDS clang c-index-test FileCheck not count COMMENT "Running Clang regression tests") + set_target_properties(clang-c++tests PROPERTIES FOLDER "Clang tests") if( NOT CLANG_BUILT_STANDALONE ) add_custom_target(check-all @@ -113,13 +121,15 @@ if(PYTHONINTERP_FOUND) ${LLVM_BINARY_DIR}/test ${CMAKE_CURRENT_BINARY_DIR} COMMENT "Running Clang and LLVM regression tests") - add_dependencies(check-all check.deps clang-test.deps) + add_dependencies(check-all clang-test.deps) + if ( LLVM_INCLUDE_TESTS ) + add_dependencies(check-all check.deps ClangUnitTests) + endif ( LLVM_INCLUDE_TESTS ) add_dependencies(clang-test.deps - ClangUnitTests - llvm-dis opt + llvm-dis opt FileCheck count not ) - + set_target_properties(check-all PROPERTIES FOLDER "Clang tests") endif() add_dependencies(clang-test clang-test.deps) diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p2.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p2.cpp new file mode 100644 index 000000000000..18a0cf169d54 --- /dev/null +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p2.cpp @@ -0,0 +1,49 @@ +// RUN: %clang_cc1 -fexceptions -fsyntax-only -verify %s -std=c++0x + +struct S { + virtual ~S(); + + void g() throw (auto(*)()->int); + + // Note, this is not permitted: conversion-declarator cannot have a trailing return type. + // FIXME: don't issue the second diagnostic for this. + operator auto(*)()->int(); // expected-error{{'auto' not allowed here}} expected-error {{C++ requires a type specifier}} +}; + +typedef auto Fun(int a) -> decltype(a + a); +typedef auto (*PFun)(int a) -> decltype(a + a); + +void g(auto (*f)() -> int) { + try { } + catch (auto (&f)() -> int) { } + catch (auto (*const f[10])() -> int) { } +} + +namespace std { + class type_info; +} + +template<typename T> struct U {}; + +void j() { + (void)typeid(auto(*)()->void); + (void)sizeof(auto(*)()->void); + (void)__alignof(auto(*)()->void); + + U<auto(*)()->void> v; + + int n; + (void)static_cast<auto(*)()->void>(&j); + auto p = reinterpret_cast<auto(*)()->int>(&j); + (void)const_cast<auto(**)()->int>(&p); + (void)(auto(*)()->void)(&j); +} + +template <auto (*f)() -> void = &j> class C { }; +struct F : auto(*)()->int {}; // expected-error{{expected class name}} +template<typename T = auto(*)()->int> struct G { }; + +int g(); +auto (*h)() -> auto = &g; // expected-error{{'auto' not allowed here}} +auto (*i)() = &g; // ok; auto deduced as int. +auto (*k)() -> int = i; // ok; no deduction. diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp index 24780c68322c..b675fb8013e3 100644 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp @@ -3,12 +3,19 @@ void f() { auto a = a; // expected-error{{variable 'a' declared with 'auto' type cannot appear in its own initializer}} auto *b = b; // expected-error{{variable 'b' declared with 'auto' type cannot appear in its own initializer}} const auto c = c; // expected-error{{variable 'c' declared with 'auto' type cannot appear in its own initializer}} + if (auto d = d) {} // expected-error {{variable 'd' declared with 'auto' type cannot appear in its own initializer}} + auto e = ({ auto f = e; 0; }); // expected-error {{variable 'e' declared with 'auto' type cannot appear in its own initializer}} } void g() { auto a; // expected-error{{declaration of variable 'a' with type 'auto' requires an initializer}} auto *b; // expected-error{{declaration of variable 'b' with type 'auto *' requires an initializer}} + + if (auto b) {} // expected-error {{expected '='}} + for (;auto b;) {} // expected-error {{expected '='}} + while (auto b) {} // expected-error {{expected '='}} + if (auto b = true) { (void)b; } } auto n(1,2,3); // expected-error{{initializer for variable 'n' with type 'auto' contains multiple expressions}} @@ -21,7 +28,7 @@ namespace N void h() { auto b = 42ULL; - for (auto c = 0; c < 100; ++c) { + for (auto c = 0; c < b; ++c) { } } @@ -32,7 +39,7 @@ void p3example() { auto x = 5; const auto *v = &x, u = 6; static auto y = 0.0; - auto int r; // expected-error{{cannot combine with previous}} expected-error{{requires an initializer}} + auto int r; // expected-warning {{'auto' storage class specifier is redundant and will be removed in future releases}} same<decltype(x), int> xHasTypeInt; same<decltype(v), const int*> vHasTypeConstIntPtr; diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp index 836ccda6f9d7..fec53c941e3d 100644 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp @@ -14,6 +14,11 @@ struct S { operator auto(); // expected-error{{'auto' not allowed here}} }; +// PR 9278: auto is not allowed in typedefs, except with a trailing return type. +typedef auto *AutoPtr; // expected-error{{'auto' not allowed in typedef}} +typedef auto (*PFun)(int a); // expected-error{{'auto' not allowed in typedef}} +typedef auto Fun(int a) -> decltype(a + a); + void g(auto a) { // expected-error{{'auto' not allowed in function prototype}} try { } catch (auto &a) { } // expected-error{{'auto' not allowed in exception declaration}} @@ -60,13 +65,5 @@ template<typename T = auto> struct G { }; // expected-error{{'auto' not allowed using A = auto; // expected-error{{expected ';'}} expected-error{{requires a qualified name}} -// Whether this is illegal depends on the interpretation of [decl.spec.auto]p2 and p3, -// and in particular the "Otherwise, ..." at the start of p3. -namespace TrailingReturnType { - // FIXME: don't issue the second diagnostic for this error. - auto f() -> auto; // expected-error{{'auto' not allowed here}} unexpected-error{{without trailing return type}} - int g(); - auto (*h)() -> auto = &g; // expected-error{{'auto' not allowed here}} - auto (*i)() = &g; // ok; auto deduced as int. - auto (*j)() -> int = i; // ok; no deduction. -} +// FIXME: don't issue the second diagnostic for this error. +auto k() -> auto; // expected-error{{'auto' not allowed here}} unexpected-error{{without trailing return type}} diff --git a/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p2-cxx0x.cpp b/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p2-cxx0x.cpp index 4dc393da9f41..70c9aeb48819 100644 --- a/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p2-cxx0x.cpp +++ b/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p2-cxx0x.cpp @@ -3,3 +3,5 @@ auto a() -> int; // ok const auto b() -> int; // expected-error {{function with trailing return type must specify return type 'auto', not 'auto const'}} auto *c() -> int; // expected-error {{function with trailing return type must specify return type 'auto', not 'auto *'}} +auto (d() -> int); // expected-error {{trailing return type may not be nested within parentheses}} +auto e() -> auto (*)() -> auto (*)() -> void; // ok: same as void (*(*e())())(); diff --git a/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p8-0x.cpp b/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p8-0x.cpp new file mode 100644 index 000000000000..21efbfff1ab9 --- /dev/null +++ b/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p8-0x.cpp @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s + +auto f() -> int[32]; // expected-error{{function cannot return array}} +auto g() -> int(int); // expected-error{{function cannot return function}} +auto h() -> auto() -> int; // expected-error{{function cannot return function}} +auto i() -> auto(*)() -> int; diff --git a/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p9-0x.cpp b/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p9-0x.cpp new file mode 100644 index 000000000000..ca4701554be4 --- /dev/null +++ b/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p9-0x.cpp @@ -0,0 +1,3 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s + +auto j() -> enum { e3 }; // expected-error{{can not be defined in a type specifier}} diff --git a/test/CodeGen/asm-inout.c b/test/CodeGen/asm-inout.c index 5b0a5f7ef16a..29142f7c5592 100644 --- a/test/CodeGen/asm-inout.c +++ b/test/CodeGen/asm-inout.c @@ -29,3 +29,12 @@ asm( : "edi" ); } + +// PR8959 - This should implicitly truncate the immediate to a byte. +int test4(volatile int *addr) { + unsigned char oldval; + __asm__ ("frob %0" : "=r"(oldval) : "0"(0xff)); + return (int)oldval; +// CHECK: call i8 asm "frob $0", "=r,0{{.*}}"(i8 -1) +} + diff --git a/test/CodeGen/attribute-section-data-common.c b/test/CodeGen/attribute-section-data-common.c new file mode 100644 index 000000000000..2393bfb0329b --- /dev/null +++ b/test/CodeGen/attribute-section-data-common.c @@ -0,0 +1,5 @@ +// RUN: %clang -S %s -o /dev/null +struct rtxc_snapshot { + int a, b, c, d; +}; +__attribute__ ((section("__DATA, __common"))) struct rtxc_snapshot rtxc_log_A[4]; diff --git a/test/CodeGen/decl.c b/test/CodeGen/decl.c index 7a9971ee1812..5be421623616 100644 --- a/test/CodeGen/decl.c +++ b/test/CodeGen/decl.c @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -w -emit-llvm < %s | FileCheck %s -// CHECK: @test1.x = internal constant [12 x i32] [i32 1 +// CHECK: @test1.x = private constant [12 x i32] [i32 1 // CHECK: @test2.x = internal constant [13 x i32] [i32 1, // CHECK: @test5w = global %0 { i32 2, [4 x i8] undef } // CHECK: @test5y = global %union.test5u { double 7.300000e+0{{[0]*}}1 } diff --git a/test/CodeGen/may-alias.c b/test/CodeGen/may-alias.c index f3ea792da36c..6171be763dc7 100644 --- a/test/CodeGen/may-alias.c +++ b/test/CodeGen/may-alias.c @@ -8,12 +8,21 @@ typedef int __attribute__((may_alias)) aliasing_int; void test0(aliasing_int *ai, int *i) { +// CHECK: store i32 0, i32* %{{.*}}, !tbaa !1 *ai = 0; +// CHECK: store i32 1, i32* %{{.*}}, !tbaa !3 *i = 1; } -// CHECK: store i32 0, i32* %{{.*}}, !tbaa !1 -// CHECK: store i32 1, i32* %{{.*}}, !tbaa !3 +// PR9307 +struct Test1 { int x; }; +struct Test1MA { int x; } __attribute__((may_alias)); +void test1(struct Test1MA *p1, struct Test1 *p2) { + // CHECK: store i32 2, i32* {{%.*}}, !tbaa !1 + p1->x = 2; + // CHECK: store i32 3, i32* {{%.*}}, !tbaa !3 + p2->x = 3; +} // CHECK: !0 = metadata !{metadata !"any pointer", metadata !1} // CHECK: !1 = metadata !{metadata !"omnipotent char", metadata !2} diff --git a/test/CodeGenCXX/anonymous-union-member-initializer.cpp b/test/CodeGenCXX/anonymous-union-member-initializer.cpp index d97a2ae366b3..85e931b50c91 100644 --- a/test/CodeGenCXX/anonymous-union-member-initializer.cpp +++ b/test/CodeGenCXX/anonymous-union-member-initializer.cpp @@ -84,11 +84,11 @@ namespace test3 { // CHECK: define void @_ZN5test31AC2Ev( // CHECK: [[THIS:%.*]] = load // CHECK-NEXT: [[UNION:%.*]] = getelementptr inbounds {{.*}} [[THIS]], i32 0, i32 0 - // CHECK-NEXT: [[STRUCT:%.*]] = getelementptr inbounds {{.*}} [[UNION]], i32 0, i32 0 + // CHECK-NEXT: [[STRUCT:%.*]] = bitcast {{.*}}* [[UNION]] to // CHECK-NEXT: [[CALLBACK:%.*]] = getelementptr inbounds {{.*}} [[STRUCT]], i32 0, i32 0 // CHECK-NEXT: store void (i8*)* null, void (i8*)** [[CALLBACK]] // CHECK-NEXT: [[UNION:%.*]] = getelementptr inbounds {{.*}} [[THIS]], i32 0, i32 0 - // CHECK-NEXT: [[STRUCT:%.*]] = getelementptr inbounds {{.*}} [[UNION]], i32 0, i32 0 + // CHECK-NEXT: [[STRUCT:%.*]] = bitcast {{.*}}* [[UNION]] to // CHECK-NEXT: [[CVALUE:%.*]] = getelementptr inbounds {{.*}} [[STRUCT]], i32 0, i32 1 // CHECK-NEXT: store i8* null, i8** [[CVALUE]] } diff --git a/test/CodeGenCXX/conditional-gnu-ext.cpp b/test/CodeGenCXX/conditional-gnu-ext.cpp new file mode 100644 index 000000000000..46c5e7fab6de --- /dev/null +++ b/test/CodeGenCXX/conditional-gnu-ext.cpp @@ -0,0 +1,142 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s +// rdar: // 8353567 +// pr7726 + +extern "C" int printf(...); + +void test0() { +// CHECK: call i32 (...)* @printf({{.*}}, i8* inttoptr (i64 3735928559 to i8*)) + printf("%p\n", (void *)0xdeadbeef ? : (void *)0xaaaaaa); +} + +// rdar://8446940 +namespace radar8446940 { +extern "C" void abort(); + +int main () { + char x[1]; + char *y = x ? : 0; + + if (x != y) + abort(); +} +} + +namespace radar8453812 { +extern "C" void abort(); +_Complex int getComplex(_Complex int val) { + static int count; + if (count++) + abort(); + return val; +} + +_Complex int cmplx() { + _Complex int cond; + _Complex int rhs; + + return getComplex(1+2i) ? : rhs; +} + +// lvalue test +void foo (int& lv) { + ++lv; +} + +int global = 1; + +int &cond() { + static int count; + if (count++) + abort(); + return global; +} + + +int main() { + cmplx(); + int rhs = 10; + foo (cond()? : rhs); + return global-2; +} +} + +namespace test3 { + struct A { + A(); + A(const A&); + ~A(); + }; + + struct B { + B(); + B(const B&); + ~B(); + operator bool(); + operator A(); + }; + + B test0(B &x) { + // CHECK: define void @_ZN5test35test0ERNS_1BE( + // CHECK: [[X:%.*]] = alloca [[B:%.*]]*, + // CHECK-NEXT: store [[B]]* {{%.*}}, [[B]]** [[X]] + // CHECK-NEXT: [[T0:%.*]] = load [[B]]** [[X]] + // CHECK-NEXT: [[BOOL:%.*]] = call zeroext i1 @_ZN5test31BcvbEv([[B]]* [[T0]]) + // CHECK-NEXT: br i1 [[BOOL]] + // CHECK: call void @_ZN5test31BC1ERKS0_([[B]]* [[RESULT:%.*]], [[B]]* [[T0]]) + // CHECK-NEXT: br label + // CHECK: call void @_ZN5test31BC1Ev([[B]]* [[RESULT]]) + // CHECK-NEXT: br label + // CHECK: ret void + return x ?: B(); + } + + B test1() { + // CHECK: define void @_ZN5test35test1Ev( + // CHECK: [[TEMP:%.*]] = alloca [[B]], + // CHECK-NEXT: call void @_ZN5test312test1_helperEv([[B]]* sret [[TEMP]]) + // CHECK-NEXT: [[BOOL:%.*]] = call zeroext i1 @_ZN5test31BcvbEv([[B]]* [[TEMP]]) + // CHECK-NEXT: br i1 [[BOOL]] + // CHECK: call void @_ZN5test31BC1ERKS0_([[B]]* [[RESULT:%.*]], [[B]]* [[TEMP]]) + // CHECK-NEXT: br label + // CHECK: call void @_ZN5test31BC1Ev([[B]]* [[RESULT]]) + // CHECK-NEXT: br label + // CHECK: call void @_ZN5test31BD1Ev([[B]]* [[TEMP]]) + // CHECK-NEXT: ret void + extern B test1_helper(); + return test1_helper() ?: B(); + } + + + A test2(B &x) { + // CHECK: define void @_ZN5test35test2ERNS_1BE( + // CHECK: [[X:%.*]] = alloca [[B]]*, + // CHECK-NEXT: store [[B]]* {{%.*}}, [[B]]** [[X]] + // CHECK-NEXT: [[T0:%.*]] = load [[B]]** [[X]] + // CHECK-NEXT: [[BOOL:%.*]] = call zeroext i1 @_ZN5test31BcvbEv([[B]]* [[T0]]) + // CHECK-NEXT: br i1 [[BOOL]] + // CHECK: call void @_ZN5test31BcvNS_1AEEv([[A:%.*]]* sret [[RESULT:%.*]], [[B]]* [[T0]]) + // CHECK-NEXT: br label + // CHECK: call void @_ZN5test31AC1Ev([[A]]* [[RESULT]]) + // CHECK-NEXT: br label + // CHECK: ret void + return x ?: A(); + } + + A test3() { + // CHECK: define void @_ZN5test35test3Ev( + // CHECK: [[TEMP:%.*]] = alloca [[B]], + // CHECK-NEXT: call void @_ZN5test312test3_helperEv([[B]]* sret [[TEMP]]) + // CHECK-NEXT: [[BOOL:%.*]] = call zeroext i1 @_ZN5test31BcvbEv([[B]]* [[TEMP]]) + // CHECK-NEXT: br i1 [[BOOL]] + // CHECK: call void @_ZN5test31BcvNS_1AEEv([[A]]* sret [[RESULT:%.*]], [[B]]* [[TEMP]]) + // CHECK-NEXT: br label + // CHECK: call void @_ZN5test31AC1Ev([[A]]* [[RESULT]]) + // CHECK-NEXT: br label + // CHECK: call void @_ZN5test31BD1Ev([[B]]* [[TEMP]]) + // CHECK-NEXT: ret void + extern B test3_helper(); + return test3_helper() ?: A(); + } + +} diff --git a/test/CodeGenCXX/debug-info-limit.cpp b/test/CodeGenCXX/debug-info-limit.cpp new file mode 100644 index 000000000000..75f9271b003f --- /dev/null +++ b/test/CodeGenCXX/debug-info-limit.cpp @@ -0,0 +1,14 @@ +// RUN: %clang -emit-llvm -g -S %s -o - | FileCheck %s + +// TAG_member is used to encode debug info for class constructor. +// CHECK: TAG_member +class A { +public: + int z; +}; + +A *foo () { + A *a = new A(); + return a; +} + diff --git a/test/CodeGenCXX/exceptions.cpp b/test/CodeGenCXX/exceptions.cpp index 84d55c8f1907..80818189f48b 100644 --- a/test/CodeGenCXX/exceptions.cpp +++ b/test/CodeGenCXX/exceptions.cpp @@ -293,3 +293,15 @@ namespace test5 { } } } + +// PR9303: invalid assert on this +namespace test6 { + bool cond(); + void test() { + try { + lbl: + if (cond()) goto lbl; + } catch (...) { + } + } +} diff --git a/test/CodeGenCXX/gnu-conditional-scalar-ext.cpp b/test/CodeGenCXX/gnu-conditional-scalar-ext.cpp deleted file mode 100644 index fea83645a5cf..000000000000 --- a/test/CodeGenCXX/gnu-conditional-scalar-ext.cpp +++ /dev/null @@ -1,62 +0,0 @@ -// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s -// rdar: // 8353567 -// pr7726 - -extern "C" int printf(...); - -void test0() { -// CHECK: call i32 (...)* @printf({{.*}}, i8* inttoptr (i64 3735928559 to i8*)) - printf("%p\n", (void *)0xdeadbeef ? : (void *)0xaaaaaa); -} - -// rdar://8446940 -namespace radar8446940 { -extern "C" void abort(); - -int main () { - char x[1]; - char *y = x ? : 0; - - if (x != y) - abort(); -} -} - -namespace radar8453812 { -extern "C" void abort(); -_Complex int getComplex(_Complex int val) { - static int count; - if (count++) - abort(); - return val; -} - -_Complex int cmplx() { - _Complex int cond; - _Complex int rhs; - - return getComplex(1+2i) ? : rhs; -} - -// lvalue test -void foo (int& lv) { - ++lv; -} - -int global = 1; - -int &cond() { - static int count; - if (count++) - abort(); - return global; -} - - -int main() { - cmplx(); - int rhs = 10; - foo (cond()? : rhs); - return global-2; -} -} diff --git a/test/CodeGenCXX/mangle-exprs.cpp b/test/CodeGenCXX/mangle-exprs.cpp index 7322171856dc..e5f26e584b06 100644 --- a/test/CodeGenCXX/mangle-exprs.cpp +++ b/test/CodeGenCXX/mangle-exprs.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 | FileCheck %s +// RUN: %clang_cc1 -std=c++0x -emit-llvm %s -o - -triple=x86_64-apple-darwin9 | FileCheck %s template < bool condition, typename T = void > struct enable_if { typedef T type; }; @@ -24,6 +24,10 @@ namespace Casts { void static_(typename enable_if< O <= static_cast<unsigned>(4) >::type* = 0) { } + template< typename T > + void auto_(decltype(new auto(T()))) { + } + // FIXME: Test const_cast, reinterpret_cast, dynamic_cast, which are // a bit harder to use in template arguments. template <unsigned N> struct T {}; @@ -41,4 +45,7 @@ namespace Casts { // CHECK: define weak_odr void @_ZN5Casts1fILi6EEENS_1TIXT_EEEv template T<6> f<6>(); + + // CHECK: define weak_odr void @_ZN5Casts5auto_IiEEvDTnw_DapicvT__EEE( + template void auto_<int>(int*); } diff --git a/test/CodeGen/2008-08-25-incompatible-cond-expr.m b/test/CodeGenObjC/2008-08-25-incompatible-cond-expr.m index f285cca094ed..f285cca094ed 100644 --- a/test/CodeGen/2008-08-25-incompatible-cond-expr.m +++ b/test/CodeGenObjC/2008-08-25-incompatible-cond-expr.m diff --git a/test/CodeGen/2009-01-21-invalid-debug-info.m b/test/CodeGenObjC/2009-01-21-invalid-debug-info.m index af912e2dc54a..af912e2dc54a 100644 --- a/test/CodeGen/2009-01-21-invalid-debug-info.m +++ b/test/CodeGenObjC/2009-01-21-invalid-debug-info.m diff --git a/test/CodeGen/2010-02-09-DbgSelf.m b/test/CodeGenObjC/2010-02-09-DbgSelf.m index e09adac161ec..e09adac161ec 100644 --- a/test/CodeGen/2010-02-09-DbgSelf.m +++ b/test/CodeGenObjC/2010-02-09-DbgSelf.m diff --git a/test/CodeGen/2010-02-15-Dbg-MethodStart.m b/test/CodeGenObjC/2010-02-15-Dbg-MethodStart.m index 5186b20310a6..5186b20310a6 100644 --- a/test/CodeGen/2010-02-15-Dbg-MethodStart.m +++ b/test/CodeGenObjC/2010-02-15-Dbg-MethodStart.m diff --git a/test/CodeGenObjC/blocks-3.m b/test/CodeGenObjC/blocks-3.m index d8379b9f9d14..a0b693dc810b 100644 --- a/test/CodeGenObjC/blocks-3.m +++ b/test/CodeGenObjC/blocks-3.m @@ -1,5 +1,11 @@ // RUN: %clang_cc1 -triple x86_64-apple-darwin9 -emit-llvm -fblocks -o %t %s + +// 1x for the declaration +// 1x for the object-pointer byref copy helper +// 1x for the block-pointer byref copy helper +// 8x for the block copy helper // RUN: grep 'object_assign' %t | count 11 + // RUN: grep 'object_dispose' %t | count 29 int main() { diff --git a/test/CodeGenObjC/blocks-4.m b/test/CodeGenObjC/blocks-4.m index d945ed44fac0..f2d6e21a1ce1 100644 --- a/test/CodeGenObjC/blocks-4.m +++ b/test/CodeGenObjC/blocks-4.m @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple i386-apple-darwin9 -emit-llvm -fblocks -o %t %s +// RUN: %clang_cc1 -triple i386-apple-darwin9 -emit-llvm -fobjc-exceptions -fblocks -o %t %s // rdar://7590273 void EXIT(id e); diff --git a/test/CodeGenObjC/blocks.m b/test/CodeGenObjC/blocks.m index 11fb55b58c48..06dc908f2ba3 100644 --- a/test/CodeGenObjC/blocks.m +++ b/test/CodeGenObjC/blocks.m @@ -72,8 +72,8 @@ void test2(Test2 *x) { // CHECK-NEXT: store i8* bitcast (void (i8*)* @__Block_byref_object_dispose_{{.*}} to i8*), i8** [[T5]] // Actually capture the value. - // CHECK-NEXT: [[CAPTURE:%.*]] = load [[TEST2]]** [[X]] // CHECK-NEXT: [[T6:%.*]] = getelementptr inbounds [[WEAK_T]]* [[WEAKX]], i32 0, i32 6 + // CHECK-NEXT: [[CAPTURE:%.*]] = load [[TEST2]]** [[X]] // CHECK-NEXT: store [[TEST2]]* [[CAPTURE]], [[TEST2]]** [[T6]] // Then we initialize the block, blah blah blah. diff --git a/test/CodeGenObjC/exceptions-nonfragile.m b/test/CodeGenObjC/exceptions-nonfragile.m index 57ed1d9da9dd..280b5d416ffa 100644 --- a/test/CodeGenObjC/exceptions-nonfragile.m +++ b/test/CodeGenObjC/exceptions-nonfragile.m @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-nonfragile-abi -fexceptions -O2 -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-nonfragile-abi -fexceptions -fobjc-exceptions -O2 -o - %s | FileCheck %s // rdar://problem/8535238 // CHECK: declare void @objc_exception_rethrow() diff --git a/test/CodeGenObjC/exceptions.m b/test/CodeGenObjC/exceptions.m index 31805cb8df4e..d378f848f861 100644 --- a/test/CodeGenObjC/exceptions.m +++ b/test/CodeGenObjC/exceptions.m @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fexceptions -O2 -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fexceptions -fobjc-exceptions -O2 -o - %s | FileCheck %s // // <rdar://problem/7471679> [irgen] [eh] Exception code built with clang (x86_64) crashes diff --git a/test/CodeGenObjC/for-in.m b/test/CodeGenObjC/for-in.m index 7e6098a7eb57..26fe7922aee9 100644 --- a/test/CodeGenObjC/for-in.m +++ b/test/CodeGenObjC/for-in.m @@ -42,3 +42,9 @@ void t1() { break; } } + +// rdar://problem/9027663 +void t2(NSArray *array) { + for (NSArray *array in array) { // expected-warning {{collection expression type 'NSArray *' may not respond}} + } +} diff --git a/test/CodeGen/function-decay.m b/test/CodeGenObjC/function-decay.m index 161f9079b254..161f9079b254 100644 --- a/test/CodeGen/function-decay.m +++ b/test/CodeGenObjC/function-decay.m diff --git a/test/CodeGenObjC/gnu-exceptions.m b/test/CodeGenObjC/gnu-exceptions.m index 6790a2993750..7f3ae9df467e 100644 --- a/test/CodeGenObjC/gnu-exceptions.m +++ b/test/CodeGenObjC/gnu-exceptions.m @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm -fexceptions -fgnu-runtime -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm -fexceptions -fobjc-exceptions -fgnu-runtime -o - %s | FileCheck %s void opaque(void); void log(int i); diff --git a/test/CodeGen/illegal-UTF8.m b/test/CodeGenObjC/illegal-UTF8.m index 4762e800259f..4762e800259f 100644 --- a/test/CodeGen/illegal-UTF8.m +++ b/test/CodeGenObjC/illegal-UTF8.m diff --git a/test/CodeGenObjC/messages-2.m b/test/CodeGenObjC/messages-2.m index 05e30ab131a5..5ef2261b1983 100644 --- a/test/CodeGenObjC/messages-2.m +++ b/test/CodeGenObjC/messages-2.m @@ -1,4 +1,7 @@ -// RUN: %clang_cc1 -emit-llvm -o %t %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-nonfragile-abi -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK-NF + +// Most of this test is apparently just verifying that we don't crash. int printf(const char *, ...); @@ -140,3 +143,21 @@ typedef struct { return 5; } @end + +// rdar://problem/7854674 +// CHECK: define void @test0([[A:%.*]]* +// CHECK-NF: define void @test0([[A:%.*]]* +void test0(A *a) { + // CHECK: alloca [[A]]* + // CHECK-NEXT: [[POINT:%.*]] = alloca [[POINT_T:%.*]], + // CHECK-NF: alloca [[A]]* + // CHECK-NF-NEXT: [[POINT:%.*]] = alloca [[POINT_T:%.*]], + + // CHECK: [[T0:%.*]] = bitcast [[POINT_T]]* [[POINT]] to i8* + // CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[T0]], i8 0, i64 48, i32 4, i1 false) + // CHECK-NEXT: call {{.*}} @objc_msgSend_stret to + // CHECK-NF: [[T0:%.*]] = bitcast [[POINT_T]]* [[POINT]] to i8* + // CHECK-NF-NEXT: call void @llvm.memset.p0i8.i64(i8* [[T0]], i8 0, i64 48, i32 4, i1 false) + // CHECK-NF-NEXT: call {{.*}} @objc_msgSend_stret to + MyPoint point = [a returnAPoint]; +} diff --git a/test/CodeGenObjC/messages.m b/test/CodeGenObjC/messages.m index 5f77a8e327eb..b36fe5b644ed 100644 --- a/test/CodeGenObjC/messages.m +++ b/test/CodeGenObjC/messages.m @@ -1,9 +1,7 @@ -// RUN: %clang_cc1 -emit-llvm -o %t %s -// RUN: grep "objc_msgSend" %t | count 6 -// RUN: %clang_cc1 -fgnu-runtime -emit-llvm -o %t %s -// RUN: grep "objc_msg_lookup" %t | count 6 -// RUN: %clang_cc1 -fgnu-runtime -fobjc-nonfragile-abi -emit-llvm -o %t %s -// RUN: grep "objc_msg_lookup_sender" %t | count 6 +// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK-MAC +// RUN: %clang_cc1 -emit-llvm -fobjc-nonfragile-abi -o - %s | FileCheck %s -check-prefix=CHECK-MAC-NF +// RUN: %clang_cc1 -fgnu-runtime -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK-GNU +// RUN: %clang_cc1 -fgnu-runtime -fobjc-nonfragile-abi -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-GNU-NF typedef struct { int x; @@ -15,12 +13,35 @@ void f0(id a) { int i; MyPoint pt = { 1, 2}; + // CHECK-MAC: call {{.*}} @objc_msgSend( + // CHECK-MAC-NF: call {{.*}} @objc_msgSend( + // CHECK-GNU: call {{.*}} @objc_msg_lookup( + // CHECK-GNU-NF: call {{.*}} @objc_msg_lookup_sender( [a print0]; + + // CHECK-MAC: call {{.*}} @objc_msgSend to + // CHECK-MAC-NF: call {{.*}} @objc_msgSend to + // CHECK-GNU: call {{.*}} @objc_msg_lookup to + // CHECK-GNU-NF: call {{.*}} @objc_msg_lookup_sender to [a print1: 10]; + + // CHECK-MAC: call {{.*}} @objc_msgSend to + // CHECK-MAC-NF: call {{.*}} @objc_msgSend to + // CHECK-GNU: call {{.*}} @objc_msg_lookup to + // CHECK-GNU-NF: call {{.*}} @objc_msg_lookup_sender to [a print2: 10 and: "hello" and: 2.2]; + + // CHECK-MAC: call {{.*}} @objc_msgSend to + // CHECK-MAC-NF: call {{.*}} @objc_msgSend to + // CHECK-GNU: call {{.*}} @objc_msg_lookup to + // CHECK-GNU-NF: call {{.*}} @objc_msg_lookup_sender to [a takeStruct: pt ]; void *s = @selector(print0); for (i=0; i<2; ++i) + // CHECK-MAC: call {{.*}} @objc_msgSend to + // CHECK-MAC-NF: call {{.*}} @objc_msgSend to + // CHECK-GNU: call {{.*}} @objc_msg_lookup to + // CHECK-GNU-NF: call {{.*}} @objc_msg_lookup_sender to [a performSelector:s]; } diff --git a/test/CodeGenObjC/metadata_symbols.m b/test/CodeGenObjC/metadata_symbols.m index 31639466e8bb..d86422999f61 100644 --- a/test/CodeGenObjC/metadata_symbols.m +++ b/test/CodeGenObjC/metadata_symbols.m @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-nonfragile-abi -emit-llvm -fexceptions -o %t %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-nonfragile-abi -emit-llvm -fexceptions -fobjc-exceptions -o %t %s // RUN: FileCheck -check-prefix=CHECK-X86_64 < %t %s // RUN: grep '@"OBJC_EHTYPE_$_EH3"' %t | count 3 @@ -12,7 +12,7 @@ // CHECK-X86_64: define internal void @"\01-[A im0]" // CHECK-X86_64: define internal void @"\01-[A(Cat) im1]" -// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-nonfragile-abi -fvisibility hidden -emit-llvm -o %t %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-nonfragile-abi -fobjc-exceptions -fvisibility hidden -emit-llvm -o %t %s // RUN: FileCheck -check-prefix=CHECK-X86_64-HIDDEN < %t %s // CHECK-X86_64-HIDDEN: @"OBJC_CLASS_$_A" = hidden global {{.*}}, section "__DATA, __objc_data", align 8 @@ -23,7 +23,7 @@ // CHECK-X86_64-HIDDEN: define internal void @"\01-[A im0]" // CHECK-X86_64-HIDDEN: define internal void @"\01-[A(Cat) im1]" -// RUN: %clang_cc1 -triple armv6-apple-darwin10 -target-abi apcs-gnu -fobjc-nonfragile-abi -emit-llvm -o %t %s +// RUN: %clang_cc1 -triple armv6-apple-darwin10 -target-abi apcs-gnu -fobjc-nonfragile-abi -fobjc-exceptions -emit-llvm -o %t %s // RUN: FileCheck -check-prefix=CHECK-ARMV6 < %t %s // CHECK-ARMV6: @"OBJC_CLASS_$_A" = global {{.*}}, section "__DATA, __objc_data", align 4 diff --git a/test/CodeGenObjC/nested-rethrow.m b/test/CodeGenObjC/nested-rethrow.m index 627b913ab067..af5154a24c27 100644 --- a/test/CodeGenObjC/nested-rethrow.m +++ b/test/CodeGenObjC/nested-rethrow.m @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple i386-apple-darwin9 -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple i386-apple-darwin9 -emit-llvm -fobjc-exceptions %s -o - | FileCheck %s extern int printf(const char*, ...); diff --git a/test/CodeGen/rdr-6732143-dangling-block-reference.m b/test/CodeGenObjC/rdr-6732143-dangling-block-reference.m index b4d21a3f8fcc..fd812dd38823 100644 --- a/test/CodeGen/rdr-6732143-dangling-block-reference.m +++ b/test/CodeGenObjC/rdr-6732143-dangling-block-reference.m @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -emit-llvm %s -o - +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -emit-llvm -fobjc-exceptions %s -o - void f0(id x) { @synchronized (x) { diff --git a/test/CodeGenObjC/try.m b/test/CodeGenObjC/try.m index 884e33a219c0..ba79d6263467 100644 --- a/test/CodeGenObjC/try.m +++ b/test/CodeGenObjC/try.m @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 %s -S -o - -triple=i686-apple-darwin9 -// RUN: %clang_cc1 %s -S -o - -triple=x86_64-apple-darwin9 +// RUN: %clang_cc1 %s -fobjc-exceptions -S -o - -triple=i686-apple-darwin9 +// RUN: %clang_cc1 %s -fobjc-exceptions -S -o - -triple=x86_64-apple-darwin9 // rdar://6757213 - Don't crash if the internal proto for // __objc_personality_v0 mismatches with an actual one. diff --git a/test/CodeGenObjC/unwind-fn.m b/test/CodeGenObjC/unwind-fn.m index 5bfc7dce31a2..5e4a7a5863b7 100644 --- a/test/CodeGenObjC/unwind-fn.m +++ b/test/CodeGenObjC/unwind-fn.m @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -fobjc-nonfragile-abi -emit-llvm -fexceptions -o - %s | FileCheck --check-prefix=DEFAULT_EH %s -// RUN: %clang_cc1 -fsjlj-exceptions -fobjc-nonfragile-abi -fexceptions -emit-llvm -o - %s | FileCheck --check-prefix=SJLJ_EH %s +// RUN: %clang_cc1 -fobjc-nonfragile-abi -emit-llvm -fexceptions -fobjc-exceptions -o - %s | FileCheck --check-prefix=DEFAULT_EH %s +// RUN: %clang_cc1 -fsjlj-exceptions -fobjc-nonfragile-abi -fexceptions -fobjc-exceptions -emit-llvm -o - %s | FileCheck --check-prefix=SJLJ_EH %s // DEFAULT_EH: declare void @_Unwind_Resume_or_Rethrow(i8*) // SJLJ_EH: declare void @_Unwind_SjLj_Resume_or_Rethrow(i8*) diff --git a/test/Coverage/ast-printing.m b/test/Coverage/ast-printing.m index d9c97d43d463..81c3a6b0ba53 100644 --- a/test/Coverage/ast-printing.m +++ b/test/Coverage/ast-printing.m @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -fsyntax-only %s -// RUN: %clang_cc1 -ast-print %s -// RUN: %clang_cc1 -ast-dump %s +// RUN: %clang_cc1 -fsyntax-only -fobjc-exceptions %s +// RUN: %clang_cc1 -ast-print -fobjc-exceptions %s +// RUN: %clang_cc1 -ast-dump -fobjc-exceptions %s #include "objc-language-features.inc" diff --git a/test/Coverage/codegen-gnu.m b/test/Coverage/codegen-gnu.m index 6e7790dc5a70..432637c7e1ac 100644 --- a/test/Coverage/codegen-gnu.m +++ b/test/Coverage/codegen-gnu.m @@ -1,3 +1,3 @@ -// RUN: %clang_cc1 -triple i386-unknown-unknown -fgnu-runtime -emit-llvm -o %t %s +// RUN: %clang_cc1 -triple i386-unknown-unknown -fobjc-exceptions -fgnu-runtime -emit-llvm -o %t %s #include "objc-language-features.inc" diff --git a/test/Coverage/codegen-next.m b/test/Coverage/codegen-next.m index 978b443f0fa6..8f6645df515a 100644 --- a/test/Coverage/codegen-next.m +++ b/test/Coverage/codegen-next.m @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -o %t %s -// RUN: %clang_cc1 -g -emit-llvm -o %t %s +// RUN: %clang_cc1 -emit-llvm -fobjc-exceptions -o %t %s +// RUN: %clang_cc1 -g -emit-llvm -fobjc-exceptions -o %t %s #include "objc-language-features.inc" diff --git a/test/Driver/darwin-xarch.c b/test/Driver/darwin-xarch.c index 84201ceb835a..d2fb43e68caf 100644 --- a/test/Driver/darwin-xarch.c +++ b/test/Driver/darwin-xarch.c @@ -11,4 +11,4 @@ // RUN: -arch i386 -Xarch_i386 -Wl,-some-linker-arg -filelist X 2> %t // RUN: FileCheck --check-prefix=CHECK-LINK < %t %s // -// CHECK-LINK: ld"{{.*}} "-some-linker-arg" +// CHECK-LINK: ld{{.*}} "-arch" "i386"{{.*}} "-some-linker-arg" diff --git a/test/Driver/rewrite-objc.m b/test/Driver/rewrite-objc.m index ac77d79c20cb..e3d2c0f46d35 100644 --- a/test/Driver/rewrite-objc.m +++ b/test/Driver/rewrite-objc.m @@ -3,7 +3,7 @@ // TEST0: clang{{.*}}" "-cc1" // TEST0: "-rewrite-objc" // FIXME: CHECK-NOT is broken somehow, it doesn't work here. Check adjacency instead. -// TEST0: "-fmessage-length" "0" "-fdiagnostics-show-option" +// TEST0: "-fmessage-length" "0" "-fobjc-exceptions" "-fdiagnostics-show-option" // TEST0: rewrite-objc.m" // RUN: not %clang -ccc-no-clang -ccc-host-triple unknown -rewrite-objc %s -o - -### 2>&1 | \ diff --git a/test/FixIt/auto-fixit.m b/test/FixIt/auto-fixit.m new file mode 100644 index 000000000000..d09f04c2b797 --- /dev/null +++ b/test/FixIt/auto-fixit.m @@ -0,0 +1,11 @@ +/* RUN: cp %s %t + RUN: %clang_cc1 -x objective-c -fixit %t + RUN: %clang_cc1 -x objective-c -Werror %t + */ + +// rdar://9036633 + +int main() { + auto int i = 0; + return i; +} diff --git a/test/Frontend/dependency-gen.c b/test/Frontend/dependency-gen.c index c85d60be73f8..bad84938296a 100644 --- a/test/Frontend/dependency-gen.c +++ b/test/Frontend/dependency-gen.c @@ -6,3 +6,13 @@ // RUN: %clang -S -M -x c %s -o %t.d // RUN: grep '.*dependency-gen.*:' %t.d // RUN: grep 'dependency-gen.c' %t.d + +// PR8974 +// XFAIL: win32 +// RUN: rm -rf %t.dir +// RUN: mkdir -p %t.dir/a/b +// RUN: echo > %t.dir/a/b/x.h +// RUN: cd %t.dir +// RUN: %clang -include a/b/x.h -MD -MF %t.d -S -x c -o %t.o %s +// RUN: grep ' a/b/x\.h' %t.d + diff --git a/test/Index/annotate-nested-name-specifier.cpp b/test/Index/annotate-nested-name-specifier.cpp new file mode 100644 index 000000000000..70d84889e996 --- /dev/null +++ b/test/Index/annotate-nested-name-specifier.cpp @@ -0,0 +1,150 @@ +namespace outer { + namespace inner { + template<typename T> + struct vector { + typedef T* iterator; + }; + } +} + +namespace outer_alias = outer; + +struct X { }; + +using outer_alias::inner::vector; + +struct X_vector : outer_alias::inner::vector<X> { + using outer_alias::inner::vector<X>::iterator; +}; + +namespace outer { + namespace inner { + template<typename T, unsigned N> + struct array { + void foo(); + static int max_size; + }; + } +} + +template<typename T, unsigned N> +void outer::inner::array<T, N>::foo() { +} + +template<typename T, unsigned N> +int outer::inner::array<T, N>::max_size = 17; + +template<typename T> +struct X2 : outer::inner::vector<T> { + typedef T type; + using typename outer::inner::vector<type>::iterator; + using outer::inner::vector<type>::push_back; +}; + +namespace outer { + namespace inner { + namespace secret { + } + } +} + +using namespace outer_alias::inner::secret; +namespace super_secret = outer_alias::inner::secret; + +template<typename T> +struct X3 { + void f(T *t) { + t->::outer_alias::inner::template vector<T>::~vector<T>(); + } +}; + +// RUN: c-index-test -test-annotate-tokens=%s:13:1:60:1 %s | FileCheck %s + +// CHECK: Keyword: "using" [14:1 - 14:6] UsingDeclaration=vector[4:12] +// CHECK: Identifier: "outer_alias" [14:7 - 14:18] NamespaceRef=outer_alias:10:11 +// CHECK: Punctuation: "::" [14:18 - 14:20] UsingDeclaration=vector[4:12] +// CHECK: Identifier: "inner" [14:20 - 14:25] NamespaceRef=inner:2:13 +// CHECK: Punctuation: "::" [14:25 - 14:27] UsingDeclaration=vector[4:12] +// CHECK: Identifier: "vector" [14:27 - 14:33] OverloadedDeclRef=vector[4:12] +// CHECK: Punctuation: ";" [14:33 - 14:34] +// FIXME: Base specifiers, too +// CHECK: Keyword: "using" [17:3 - 17:8] UsingDeclaration=iterator[5:18] +// CHECK: Identifier: "outer_alias" [17:9 - 17:20] NamespaceRef=outer_alias:10:11 +// CHECK: Punctuation: "::" [17:20 - 17:22] UsingDeclaration=iterator[5:18] +// CHECK: Identifier: "inner" [17:22 - 17:27] NamespaceRef=inner:2:13 +// CHECK: Punctuation: "::" [17:27 - 17:29] UsingDeclaration=iterator[5:18] +// CHECK: Identifier: "vector" [17:29 - 17:35] TemplateRef=vector:4:12 +// CHECK: Punctuation: "<" [17:35 - 17:36] UsingDeclaration=iterator[5:18] +// CHECK: Identifier: "X" [17:36 - 17:37] TypeRef=struct X:12:8 +// CHECK: Punctuation: ">" [17:37 - 17:38] UsingDeclaration=iterator[5:18] +// CHECK: Punctuation: "::" [17:38 - 17:40] UsingDeclaration=iterator[5:18] +// CHECK: Identifier: "iterator" [17:40 - 17:48] OverloadedDeclRef=iterator[5:18] + +// FIXME: Check nested-name-specifiers on VarDecl, CXXMethodDecl. + +// CHECK: Keyword: "using" [40:3 - 40:8] UsingDeclaration=iterator:40:46 +// CHECK: Keyword: "typename" [40:9 - 40:17] UsingDeclaration=iterator:40:46 +// CHECK: Identifier: "outer" [40:18 - 40:23] NamespaceRef=outer:20:11 +// CHECK: Punctuation: "::" [40:23 - 40:25] UsingDeclaration=iterator:40:46 +// CHECK: Identifier: "inner" [40:25 - 40:30] NamespaceRef=inner:21:13 +// CHECK: Punctuation: "::" [40:30 - 40:32] UsingDeclaration=iterator:40:46 +// CHECK: Identifier: "vector" [40:32 - 40:38] TemplateRef=vector:4:12 +// CHECK: Punctuation: "<" [40:38 - 40:39] UsingDeclaration=iterator:40:46 +// CHECK: Identifier: "type" [40:39 - 40:43] TypeRef=type:39:13 +// CHECK: Punctuation: ">" [40:43 - 40:44] UsingDeclaration=iterator:40:46 +// CHECK: Punctuation: "::" [40:44 - 40:46] UsingDeclaration=iterator:40:46 +// CHECK: Identifier: "iterator" [40:46 - 40:54] UsingDeclaration=iterator:40:46 +// CHECK: Punctuation: ";" [40:54 - 40:55] ClassTemplate=X2:38:8 (Definition) +// CHECK: Keyword: "using" [41:3 - 41:8] UsingDeclaration=push_back:41:37 +// CHECK: Identifier: "outer" [41:9 - 41:14] NamespaceRef=outer:20:11 +// CHECK: Punctuation: "::" [41:14 - 41:16] UsingDeclaration=push_back:41:37 +// CHECK: Identifier: "inner" [41:16 - 41:21] NamespaceRef=inner:21:13 +// CHECK: Punctuation: "::" [41:21 - 41:23] UsingDeclaration=push_back:41:37 +// CHECK: Identifier: "vector" [41:23 - 41:29] TemplateRef=vector:4:12 +// CHECK: Punctuation: "<" [41:29 - 41:30] UsingDeclaration=push_back:41:37 +// CHECK: Identifier: "type" [41:30 - 41:34] TypeRef=type:39:13 +// CHECK: Punctuation: ">" [41:34 - 41:35] UsingDeclaration=push_back:41:37 +// CHECK: Punctuation: "::" [41:35 - 41:37] UsingDeclaration=push_back:41:37 +// CHECK: Identifier: "push_back" [41:37 - 41:46] UsingDeclaration=push_back:41:37 + +// Using directive +// CHECK: Keyword: "using" [51:1 - 51:6] UsingDirective=:51:37 +// CHECK: Keyword: "namespace" [51:7 - 51:16] UsingDirective=:51:37 +// CHECK: Identifier: "outer_alias" [51:17 - 51:28] NamespaceRef=outer_alias:10:11 +// CHECK: Punctuation: "::" [51:28 - 51:30] UsingDirective=:51:37 +// CHECK: Identifier: "inner" [51:30 - 51:35] NamespaceRef=inner:45:13 +// CHECK: Punctuation: "::" [51:35 - 51:37] UsingDirective=:51:37 +// CHECK: Identifier: "secret" [51:37 - 51:43] NamespaceRef=secret:46:15 + +// Namespace alias +// CHECK: Keyword: "namespace" [52:1 - 52:10] NamespaceAlias=super_secret:52:11 +// CHECK: Identifier: "super_secret" [52:11 - 52:23] NamespaceAlias=super_secret:52:11 +// CHECK: Punctuation: "=" [52:24 - 52:25] NamespaceAlias=super_secret:52:11 +// CHECK: Identifier: "outer_alias" [52:26 - 52:37] NamespaceRef=outer_alias:10:11 +// CHECK: Punctuation: "::" [52:37 - 52:39] NamespaceAlias=super_secret:52:11 +// CHECK: Identifier: "inner" [52:39 - 52:44] NamespaceRef=inner:45:13 +// CHECK: Punctuation: "::" [52:44 - 52:46] NamespaceAlias=super_secret:52:11 +// CHECK: Identifier: "secret" [52:46 - 52:52] NamespaceRef=secret:46:15 +// CHECK: Punctuation: ";" [52:52 - 52:53] + +// Pseudo-destructor +// CHECK: Identifier: "t" [57:5 - 57:6] DeclRefExpr=t:56:13 +// CHECK: Punctuation: "->" [57:6 - 57:8] UnexposedExpr= +// CHECK: Punctuation: "::" [57:8 - 57:10] UnexposedExpr= +// CHECK: Identifier: "outer_alias" [57:10 - 57:21] NamespaceRef=outer_alias:10:11 +// CHECK: Punctuation: "::" [57:21 - 57:23] UnexposedExpr= +// CHECK: Identifier: "inner" [57:23 - 57:28] NamespaceRef=inner:45:13 +// CHECK: Punctuation: "::" [57:28 - 57:30] UnexposedExpr= +// CHECK: Keyword: "template" [57:30 - 57:38] UnexposedExpr= +// CHECK: Identifier: "vector" [57:39 - 57:45] TemplateRef=vector:4:12 +// CHECK: Punctuation: "<" [57:45 - 57:46] UnexposedExpr= +// CHECK: Identifier: "T" [57:46 - 57:47] UnexposedExpr= +// CHECK: Punctuation: ">" [57:47 - 57:48] UnexposedExpr= +// CHECK: Punctuation: "::" [57:48 - 57:50] UnexposedExpr= +// CHECK: Punctuation: "~" [57:50 - 57:51] UnexposedExpr= +// CHECK: Identifier: "vector" [57:51 - 57:57] TemplateRef=vector:4:12 +// CHECK: Punctuation: "<" [57:57 - 57:58] UnexposedExpr= +// CHECK: Identifier: "T" [57:58 - 57:59] UnexposedExpr= +// CHECK: Punctuation: ">" [57:59 - 57:60] UnexposedExpr= +// CHECK: Punctuation: "(" [57:60 - 57:61] CallExpr= +// CHECK: Punctuation: ")" [57:61 - 57:62] CallExpr= diff --git a/test/PCH/objc_stmts.m b/test/PCH/objc_stmts.m index ed7466a53d9e..3bc728c35e42 100644 --- a/test/PCH/objc_stmts.m +++ b/test/PCH/objc_stmts.m @@ -1,11 +1,11 @@ // Test this without pch. -// RUN: %clang_cc1 -include %S/objc_stmts.h -emit-llvm -o - %s -// RUN: %clang_cc1 -include %S/objc_stmts.h -ast-dump -o - %s 2>&1 | FileCheck %s +// RUN: %clang_cc1 -include %S/objc_stmts.h -emit-llvm -fobjc-exceptions -o - %s +// RUN: %clang_cc1 -include %S/objc_stmts.h -ast-dump -fobjc-exceptions -o - %s 2>&1 | FileCheck %s // Test with pch. -// RUN: %clang_cc1 -x objective-c -emit-pch -o %t %S/objc_stmts.h -// RUN: %clang_cc1 -include-pch %t -emit-llvm -o - %s -// RUN: %clang_cc1 -include-pch %t -ast-dump -o - %s 2>&1 | FileCheck %s +// RUN: %clang_cc1 -x objective-c -emit-pch -fobjc-exceptions -o %t %S/objc_stmts.h +// RUN: %clang_cc1 -include-pch %t -emit-llvm -fobjc-exceptions -o - %s +// RUN: %clang_cc1 -include-pch %t -ast-dump -fobjc-exceptions -o - %s 2>&1 | FileCheck %s // CHECK: catch parm = "A *a" // CHECK: catch parm = "B *b" diff --git a/test/Parser/method-def-in-class.m b/test/Parser/method-def-in-class.m new file mode 100644 index 000000000000..490c0559d108 --- /dev/null +++ b/test/Parser/method-def-in-class.m @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// rdar://7029784 + +@interface A +-(id) f0 { // expected-error {{expected ';' after method prototype}} + assert(0); +} +@end + +@interface B +-(id) f0 { // expected-error {{expected ';' after method prototype}} + assert(0); +@end + +@interface C +- (id) f0 { // expected-error {{expected ';' after method prototype}} + assert(0); +}; +@end + +@interface D +- (id) f0 { // expected-error {{expected ';' after method prototype}} + assert(0); +@property int P; +@end diff --git a/test/Parser/objc-try-catch-1.m b/test/Parser/objc-try-catch-1.m index 719369124e5c..a3220ebc6477 100644 --- a/test/Parser/objc-try-catch-1.m +++ b/test/Parser/objc-try-catch-1.m @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -// RUN: %clang_cc1 -fsyntax-only -verify -x objective-c++ %s +// RUN: %clang_cc1 -fsyntax-only -verify -fobjc-exceptions %s +// RUN: %clang_cc1 -fsyntax-only -verify -fobjc-exceptions -x objective-c++ %s void * proc(); @interface NSConstantString diff --git a/test/Rewriter/finally.m b/test/Rewriter/finally.m index 7d160cfbdd2b..ab5d8387ccab 100644 --- a/test/Rewriter/finally.m +++ b/test/Rewriter/finally.m @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -rewrite-objc -verify %s -o - +// RUN: %clang_cc1 -rewrite-objc -fobjc-exceptions -verify %s -o - int main() { @try { diff --git a/test/Rewriter/rewrite-block-property.m b/test/Rewriter/rewrite-block-property.m new file mode 100644 index 000000000000..505e04b56ca9 --- /dev/null +++ b/test/Rewriter/rewrite-block-property.m @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fblocks -fms-extensions -rewrite-objc %s -o %t-rw.cpp +// RUN: %clang_cc1 -fsyntax-only -fblocks -Wno-address-of-temporary -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp + +// rdar://9055596 +void *sel_registerName(const char *); + +typedef void (^FooBlock) (int foo, int bar, int baz); + +@interface Foo { } +@property (readwrite, copy, nonatomic) FooBlock fooBlock; +@end + +static void Bar (Foo * foo) { + foo.fooBlock (1,2,3); +} diff --git a/test/Rewriter/rewrite-eh.m b/test/Rewriter/rewrite-eh.m index 5bc80b55093f..9045f7f766ef 100644 --- a/test/Rewriter/rewrite-eh.m +++ b/test/Rewriter/rewrite-eh.m @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -rewrite-objc -o - %s +// RUN: %clang_cc1 -rewrite-objc -fobjc-exceptions -o - %s // rdar://7522880 @interface NSException diff --git a/test/Rewriter/rewrite-foreach-5.m b/test/Rewriter/rewrite-foreach-5.m index adfd7f837841..7baccc37898c 100644 --- a/test/Rewriter/rewrite-foreach-5.m +++ b/test/Rewriter/rewrite-foreach-5.m @@ -1,4 +1,8 @@ -// RUN: %clang_cc1 -rewrite-objc %s -o - +// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fblocks -fms-extensions -rewrite-objc %s -o %t-rw.cpp +// RUN: %clang_cc1 -fsyntax-only -fblocks -Wno-address-of-temporary -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp + +void *sel_registerName(const char *); +void objc_enumerationMutation(id); @interface MyList - (id) allKeys; diff --git a/test/Rewriter/rewrite-foreach-6.m b/test/Rewriter/rewrite-foreach-6.m index 2aa19aecb82c..96b472a60eef 100644 --- a/test/Rewriter/rewrite-foreach-6.m +++ b/test/Rewriter/rewrite-foreach-6.m @@ -1,8 +1,12 @@ -// RUN: %clang_cc1 %s -rewrite-objc -o - +// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fblocks -fms-extensions -rewrite-objc %s -o %t-rw.cpp +// RUN: %clang_cc1 -fsyntax-only -fblocks -Wno-address-of-temporary -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp // rdar://5716356 // FIXME: Should be able to pipe into clang, but code is not // yet correct for other reasons: rdar://5716940 +void *sel_registerName(const char *); +void objc_enumerationMutation(id); + @class NSNotification; @class NSMutableArray; diff --git a/test/Rewriter/rewrite-foreach-protocol-id.m b/test/Rewriter/rewrite-foreach-protocol-id.m new file mode 100644 index 000000000000..85d0d0dc4473 --- /dev/null +++ b/test/Rewriter/rewrite-foreach-protocol-id.m @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fblocks -fms-extensions -rewrite-objc %s -o %t-rw.cpp +// RUN: %clang_cc1 -fsyntax-only -fblocks -Wno-address-of-temporary -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp +// rdar:// 9039342 + +void *sel_registerName(const char *); +void objc_enumerationMutation(id); + +@protocol CoreDAVLeafDataPayload @end + +@class NSString; + +@interface CoreDAVAction +- (id) context; +@end + +@interface I +{ + id uuidsToAddActions; +} +@end + +@implementation I +- (void) Meth { + for (id<CoreDAVLeafDataPayload> uuid in uuidsToAddActions) { + CoreDAVAction *action = 0; + id <CoreDAVLeafDataPayload> payload = [action context]; + } +} +@end diff --git a/test/Rewriter/rewrite-vararg.m b/test/Rewriter/rewrite-vararg.m new file mode 100644 index 000000000000..d45403153eed --- /dev/null +++ b/test/Rewriter/rewrite-vararg.m @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fblocks -fms-extensions -rewrite-objc %s -o %t-rw.cpp +// RUN: %clang_cc1 -fsyntax-only -fblocks -Wno-address-of-temporary -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp + +// rdar://9056351 +void *sel_registerName(const char *); + +@interface NSObject @end +@class NSString; + +@protocol P + -(void)ParliamentFunkadelic; +@end + +@interface Foo { + NSObject <P> *_dataSource; +} +@end + +@interface Bar { } ++(void)WhateverBar:(NSString*)format, ...; +@end + +@implementation Foo +-(void)WhateverFoo { + [Bar WhateverBar:@"ISyncSessionDriverDataSource %@ responded poorly", _dataSource]; +} +@end diff --git a/test/Sema/MicrosoftExtensions.c b/test/Sema/MicrosoftExtensions.c index 0ef72855684d..cb9fee9dc1d4 100644 --- a/test/Sema/MicrosoftExtensions.c +++ b/test/Sema/MicrosoftExtensions.c @@ -67,3 +67,15 @@ void foo() var.bad2; // expected-error {{no member named 'bad2' in 'struct test'}} } +// Enumeration types with a fixed underlying type. +const int seventeen = 17; +typedef int Int; + +struct X0 { + enum E1 : Int { SomeOtherValue } field; // expected-warning{{enumeration types with a fixed underlying type are a Microsoft extension}} + enum E1 : seventeen; +}; + +enum : long long { // expected-warning{{enumeration types with a fixed underlying type are a Microsoft extension}} + SomeValue = 0x100000000 +}; diff --git a/test/Sema/array-init.c b/test/Sema/array-init.c index 0ee22c0f1994..345ab6981b17 100644 --- a/test/Sema/array-init.c +++ b/test/Sema/array-init.c @@ -264,3 +264,17 @@ void test_matrix() { } char badchararray[1] = { badchararray[0], "asdf" }; // expected-warning {{excess elements in array initializer}} expected-error {{initializer element is not a compile-time constant}} + +// Test the GNU extension for initializing an array from an array +// compound literal. PR9261. +typedef int int5[5]; +int a1[5] = (int[]){1, 2, 3, 4, 5}; // expected-warning{{initialization of an array of type 'int [5]' from a compound literal of type 'int [5]' is a GNU extension}} +int a2[5] = (int[5]){1, 2, 3, 4, 5}; // expected-warning{{initialization of an array of type 'int [5]' from a compound literal of type 'int [5]' is a GNU extension}} +int a3[] = ((int[]){1, 2, 3, 4, 5}); // expected-warning{{initialization of an array of type 'int []' from a compound literal of type 'int [5]' is a GNU extension}} +int a4[] = (int[5]){1, 2, 3, 4, 5}; // expected-warning{{initialization of an array of type 'int []' from a compound literal of type 'int [5]' is a GNU extension}} +int a5[] = (int5){1, 2, 3, 4, 5}; // expected-warning{{initialization of an array of type 'int []' from a compound literal of type 'int5' (aka 'int [5]') is a GNU extension}} + +int a6[5] = (int[]){1, 2, 3}; // expected-error{{cannot initialize array of type 'int [5]' with array of type 'int [3]'}} + +int nonconst_value(); +int a7[5] = (int[5]){ 1, 2, 3, 4, nonconst_value() }; // expected-error{{initializer element is not a compile-time constant}} diff --git a/test/Sema/conversion.c b/test/Sema/conversion.c index e78902332eb1..619d6993251f 100644 --- a/test/Sema/conversion.c +++ b/test/Sema/conversion.c @@ -310,3 +310,24 @@ void test_8232669(void) { #define USER_SETBIT(set,bit) do { int i = bit; set[i/(8*sizeof(set[0]))] |= (1 << (i%(8*sizeof(set)))); } while(0) USER_SETBIT(bitset, 0); // expected-warning 2 {{implicit conversion changes signedness}} } + +// <rdar://problem/8559831> +enum E8559831a { E8559831a_val }; +enum E8559831b { E8559831b_val }; +typedef enum { E8559831c_val } E8559831c; +enum { E8559831d_val } value_d; + +void test_8559831_a(enum E8559831a value); +void test_8559831(enum E8559831b value_a, E8559831c value_c) { + test_8559831_a(value_a); // expected-warning{{implicit conversion from enumeration type 'enum E8559831b' to different enumeration type 'enum E8559831a'}} + enum E8559831a a1 = value_a; // expected-warning{{implicit conversion from enumeration type 'enum E8559831b' to different enumeration type 'enum E8559831a'}} + a1 = value_a; // expected-warning{{implicit conversion from enumeration type 'enum E8559831b' to different enumeration type 'enum E8559831a'}} + + test_8559831_a(value_c); // expected-warning{{implicit conversion from enumeration type 'E8559831c' to different enumeration type 'enum E8559831a'}} + enum E8559831a a2 = value_c; // expected-warning{{implicit conversion from enumeration type 'E8559831c' to different enumeration type 'enum E8559831a'}} + a2 = value_c; // expected-warning{{implicit conversion from enumeration type 'E8559831c' to different enumeration type 'enum E8559831a'}} + + test_8559831_a(value_d); + enum E8559831a a3 = value_d; + a3 = value_d; +} diff --git a/test/Sema/expr-comma-c89.c b/test/Sema/expr-comma-c99.c index d0883ba202f9..d0883ba202f9 100644 --- a/test/Sema/expr-comma-c89.c +++ b/test/Sema/expr-comma-c99.c diff --git a/test/Sema/exprs.c b/test/Sema/exprs.c index e88f7fc08bce..0d6c5488de5f 100644 --- a/test/Sema/exprs.c +++ b/test/Sema/exprs.c @@ -1,5 +1,31 @@ // RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only +// PR 8876 - don't warn about trivially unreachable null derefs. Note that +// we put this here because the reachability analysis only kicks in for +// suppressing false positives when code has no errors. +#define PR8876(err_ptr) do {\ + if (err_ptr) *(int*)(err_ptr) = 1;\ + } while (0) + +#define PR8876_pos(err_ptr) do {\ + if (!err_ptr) *(int*)(err_ptr) = 1;\ + } while (0) + + +int test_pr8876() { + PR8876(0); // no-warning + PR8876_pos(0); // expected-warning{{indirection of non-volatile null pointer will be deleted, not trap}} expected-note{{consider using __builtin_trap() or qualifying pointer with 'volatile'}} + return 0; +} + +// PR 8183 - Handle null pointer constants on the left-side of the '&&', and reason about +// this when determining the reachability of the null pointer dereference on the right side. +void pr8183(unsigned long long test) +{ + (void)((((void*)0)) && (*((unsigned long long*)(((void*)0))) = ((unsigned long long)((test)) % (unsigned long long)((1000000000))))); // no-warning + (*((unsigned long long*)(((void*)0))) = ((unsigned long long)((test)) % (unsigned long long)((1000000000)))); // expected-warning {{indirection of non-volatile null pointer will be deleted, not trap}} expected-note {{consider using __builtin_trap() or qualifying pointer with 'volatile'}} +} + // PR1966 _Complex double test1() { return __extension__ 1.0if; diff --git a/test/Sema/format-strings.c b/test/Sema/format-strings.c index be506d7c6b19..c78095a04d7b 100644 --- a/test/Sema/format-strings.c +++ b/test/Sema/format-strings.c @@ -340,3 +340,21 @@ void posix_extensions() { printf("%'f\n", (float) 1.0); // no-warning printf("%'p\n", (void*) 0); // expected-warning{{results in undefined behavior with 'p' conversion specifier}} } + +// PR8486 +// +// Test what happens when -Wformat is on, but -Wformat-security is off. +#pragma GCC diagnostic warning "-Wformat" +#pragma GCC diagnostic ignored "-Wformat-security" + +void pr8486() { + printf("%s", 1); // expected-warning{{conversion specifies type 'char *' but the argument has type 'int'}} +} + +// PR9314 +// Don't warn about string literals that are PreDefinedExprs, e.g. __func__. +void pr9314() { + printf(__PRETTY_FUNCTION__); // no-warning + printf(__func__); // no-warning +} + diff --git a/test/Sema/i-c-e.c b/test/Sema/i-c-e.c index 4c2962d4b21a..4d7007cd077c 100644 --- a/test/Sema/i-c-e.c +++ b/test/Sema/i-c-e.c @@ -60,10 +60,14 @@ int comma3[(1,2)]; // expected-warning {{size of static array must be an integer // Pointer + __builtin_constant_p char pbcp[__builtin_constant_p(4) ? (intptr_t)&expr : 0]; // expected-error {{variable length array declaration not allowed at file scope}} -int illegaldiv1[1 || 1/0]; // expected-warning {{division by zero is undefined}} +int illegaldiv1a[1 || 1/0]; // expected-warning {{division by zero is undefined}} +int illegaldiv1b[1 && 1/0]; // expected-warning {{division by zero is undefined}} expected-error{{variable length array declaration not allowed at file scope}} + int illegaldiv2[1/0]; // expected-error {{variable length array declaration not allowed at file scope}} \ // expected-warning {{division by zero is undefined}} int illegaldiv3[INT_MIN / -1]; // expected-error {{variable length array declaration not allowed at file scope}} +// PR9262 +int illegaldiv4[0 / (1 / 0)]; // expected-warning {{division by zero is undefined}} expected-error {{variable length array declaration not allowed at file scope}} int chooseexpr[__builtin_choose_expr(1, 1, expr)]; int realop[(__real__ 4) == 4 ? 1 : -1]; diff --git a/test/Sema/parentheses.c b/test/Sema/parentheses.c index 6d6fa1d4bd42..b45d8512f6bf 100644 --- a/test/Sema/parentheses.c +++ b/test/Sema/parentheses.c @@ -37,3 +37,7 @@ void bitwise_rel(unsigned i) { (void)(i && i || 0); // no warning. (void)(0 || i && i); // no warning. } + +// RUN: %clang_cc1 -fsyntax-only -Wparentheses -Werror -fdiagnostics-show-option %s 2>&1 | FileCheck %s +// CHECK: error: using the result of an assignment as a condition without parentheses [-Werror,-Wparentheses] + diff --git a/test/Sema/return.c b/test/Sema/return.c index 0c2c72ee537f..d9456b6e353b 100644 --- a/test/Sema/return.c +++ b/test/Sema/return.c @@ -242,6 +242,7 @@ static inline int si_forward() {} // expected-warning{{control reaches end of no // Test warnings on ignored qualifiers on return types. const int ignored_c_quals(); // expected-warning{{'const' type qualifier on return type has no effect}} const volatile int ignored_cv_quals(); // expected-warning{{'const volatile' type qualifiers on return type have no effect}} +char* const volatile restrict ignored_cvr_quals(); // expected-warning{{'const volatile restrict' type qualifiers on return type have no effect}} // Test that for switch(enum) that if the switch statement covers all the cases // that we don't consider that for -Wreturn-type. @@ -254,4 +255,3 @@ int test_enum_cases(enum Cases C) { case C3: return 4; } } // no-warning - diff --git a/test/Sema/shift.c b/test/Sema/shift.c index 4273cab98ee3..df6b1141bdfc 100644 --- a/test/Sema/shift.c +++ b/test/Sema/shift.c @@ -1,7 +1,9 @@ -// RUN: %clang -Wall -ffreestanding -fsyntax-only -Xclang -verify %s +// RUN: %clang -Wall -Wshift-sign-overflow -ffreestanding -fsyntax-only -Xclang -verify %s #include <limits.h> +#define WORD_BIT (sizeof(int) * CHAR_BIT) + enum { X = 1 << 0, Y = 1 << 1, @@ -32,6 +34,22 @@ void test() { c <<= CHAR_BIT+1; // expected-warning {{shift count >= width of type}} c >>= CHAR_BIT+1; // expected-warning {{shift count >= width of type}} (void)((long)c << CHAR_BIT); + + int i; + i = 1 << (WORD_BIT - 2); + i = 2 << (WORD_BIT - 1); // expected-warning {{bits to represent, but 'int' only has}} + i = 1 << (WORD_BIT - 1); // expected-warning {{overrides the sign bit of the shift expression}} + i = -1 << (WORD_BIT - 1); + i = 0 << (WORD_BIT - 1); + i = (char)1 << (WORD_BIT - 2); + + unsigned u; + u = 1U << (WORD_BIT - 1); + u = 5U << (WORD_BIT - 1); + + long long int lli; + lli = INT_MIN << 2; // expected-warning {{bits to represent, but 'int' only has}} + lli = 1LL << (sizeof(long long) * CHAR_BIT - 2); } #define a 0 diff --git a/test/SemaCUDA/kernel-call.cu b/test/SemaCUDA/kernel-call.cu index 6d51695522ce..7bc7ae113159 100644 --- a/test/SemaCUDA/kernel-call.cu +++ b/test/SemaCUDA/kernel-call.cu @@ -8,8 +8,16 @@ template <typename T> void t1(T arg) { g1<<<arg, arg>>>(1); } +void h1(int x) {} +int h2(int x) { return 1; } + int main(void) { g1<<<1, 1>>>(42); t1(1); + + h1<<<1, 1>>>(42); // expected-error {{kernel call to non-global function h1}} + + int (*fp)(int) = h2; + fp<<<1, 1>>>(42); // expected-error {{must have void return type}} } diff --git a/test/SemaCXX/MicrosoftExtensions.cpp b/test/SemaCXX/MicrosoftExtensions.cpp index 2bcbbcaeb52d..30ad4d0482f6 100644 --- a/test/SemaCXX/MicrosoftExtensions.cpp +++ b/test/SemaCXX/MicrosoftExtensions.cpp @@ -109,3 +109,16 @@ int main() f(0xffffffffffffffffLL); f(0xffffffffffffffffi64); } + +// Enumeration types with a fixed underlying type. +const int seventeen = 17; +typedef int Int; + +struct X0 { + enum E1 : Int { SomeOtherValue } field; // expected-warning{{enumeration types with a fixed underlying type are a Microsoft extension}} + enum E1 : seventeen; +}; + +enum : long long { // expected-warning{{enumeration types with a fixed underlying type are a Microsoft extension}} + SomeValue = 0x100000000 +}; diff --git a/test/SemaCXX/PR7944.cpp b/test/SemaCXX/PR7944.cpp index fc52d101e871..a998a15c3e0b 100644 --- a/test/SemaCXX/PR7944.cpp +++ b/test/SemaCXX/PR7944.cpp @@ -8,5 +8,5 @@ struct A { B* b() { return new B; } }; void g() { A a; - MACRO(a.b->f()); // expected-error{{base of member reference has function type}} + MACRO(a.b->f()); // expected-error{{base of member reference is a function}} } diff --git a/test/SemaCXX/abstract.cpp b/test/SemaCXX/abstract.cpp index 48805e217b6f..c262230962f9 100644 --- a/test/SemaCXX/abstract.cpp +++ b/test/SemaCXX/abstract.cpp @@ -249,3 +249,13 @@ namespace test4 { static D x; // expected-error {{abstract class}} }; } + +// PR9247: Crash on invalid in clang::Sema::ActOnFinishCXXMemberSpecification +namespace pr9247 { + struct A { + virtual void g(const A& input) = 0; + struct B { + C* f(int foo); + }; + }; +} diff --git a/test/SemaCXX/array-bounds.cpp b/test/SemaCXX/array-bounds.cpp index 0286c01d85ff..80646c719078 100644 --- a/test/SemaCXX/array-bounds.cpp +++ b/test/SemaCXX/array-bounds.cpp @@ -63,11 +63,11 @@ void test() { } template <int I> struct S { - char arr[I]; // expected-note 3 {{declared here}} + char arr[I]; // expected-note 2 {{declared here}} }; template <int I> void f() { S<3> s; - s.arr[4] = 0; // expected-warning 2 {{array index of '4' indexes past the end of an array (that contains 3 elements)}} + s.arr[4] = 0; // expected-warning {{array index of '4' indexes past the end of an array (that contains 3 elements)}} s.arr[I] = 0; // expected-warning {{array index of '5' indexes past the end of an array (that contains 3 elements)}} } @@ -79,9 +79,8 @@ void test_templates() { #define ARR_IN_MACRO(flag, arr, idx) flag ? arr[idx] : 1 int test_no_warn_macro_unreachable() { - int arr[SIZE]; // expected-note 2 {{array 'arr' declared here}} - // FIXME: We don't want to warn for the first case. - return ARR_IN_MACRO(0, arr, SIZE) + // expected-warning{{array index of '10' indexes past the end of an array (that contains 10 elements)}} + int arr[SIZE]; // expected-note {{array 'arr' declared here}} + return ARR_IN_MACRO(0, arr, SIZE) + // no-warning ARR_IN_MACRO(1, arr, SIZE); // expected-warning{{array index of '10' indexes past the end of an array (that contains 10 elements)}} } @@ -91,3 +90,33 @@ int test_pr9240() { return array[(unsigned long long) 100]; // expected-warning {{array index of '100' indexes past the end of an array (that contains 100 elements)}} } +// PR 9284 - a template parameter can cause an array bounds access to be +// infeasible. +template <bool extendArray> +void pr9284() { + int arr[3 + (extendArray ? 1 : 0)]; + + if (extendArray) + arr[3] = 42; // no-warning +} + +template <bool extendArray> +void pr9284b() { + int arr[3 + (extendArray ? 1 : 0)]; // expected-note {{array 'arr' declared here}} + + if (!extendArray) + arr[3] = 42; // expected-warning{{array index of '3' indexes past the end of an array (that contains 3 elements)}} +} + +void test_pr9284() { + pr9284<true>(); + pr9284<false>(); + pr9284b<true>(); + pr9284b<false>(); // expected-note{{in instantiation of function template specialization 'pr9284b<false>' requested here}} +} + +int test_pr9296() { + int array[2]; + return array[true]; // no-warning +} + diff --git a/test/SemaCXX/attr-unavailable.cpp b/test/SemaCXX/attr-unavailable.cpp index 6f5aa5e78c4c..fe3e8b14706f 100644 --- a/test/SemaCXX/attr-unavailable.cpp +++ b/test/SemaCXX/attr-unavailable.cpp @@ -18,3 +18,13 @@ void test_foo(short* sp) { int &(*fp3)(int) = foo; void (*fp4)(...) = foo; // expected-error{{'foo' is unavailable}} } + +namespace radar9046492 { +// rdar://9046492 +#define FOO __attribute__((unavailable("not available - replaced"))) + +void foo() FOO; // expected-note {{candidate function has been explicitly made unavailable}} +void bar() { + foo(); // expected-error {{call to unavailable function 'foo' not available - replaced}} +} +} diff --git a/test/SemaCXX/auto-cxx0x.cpp b/test/SemaCXX/auto-cxx0x.cpp index 654acb5ad20c..f9246beff92a 100644 --- a/test/SemaCXX/auto-cxx0x.cpp +++ b/test/SemaCXX/auto-cxx0x.cpp @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x void f() { - auto int a; // expected-error{{cannot combine with previous 'auto' declaration specifier}} // expected-error{{declaration of variable 'a' with type 'auto' requires an initializer}} + auto int a; // expected-warning {{'auto' storage class specifier is redundant and will be removed in future releases}} int auto b; // expected-error{{cannot combine with previous 'int' declaration specifier}} } diff --git a/test/SemaCXX/dependent-auto.cpp b/test/SemaCXX/dependent-auto.cpp index 0ea59481d5f3..52b15eda7324 100644 --- a/test/SemaCXX/dependent-auto.cpp +++ b/test/SemaCXX/dependent-auto.cpp @@ -32,3 +32,28 @@ bool h(T t) { } bool b = h('x'); // expected-note {{here}} + +// PR 9276 - Make sure we check auto types deduce the same +// in the case of a dependent initializer +namespace PR9276 { + template<typename T> + void f() { + auto i = T(), j = 0; // expected-error {{deduced as 'long' in declaration of 'i' and deduced as 'int' in declaration of 'j'}} + } + + void g() { + f<long>(); // expected-note {{here}} + f<int>(); + } +} + +namespace NoRepeatedDiagnostic { + template<typename T> + void f() { + auto a = 0, b = 0.0, c = T(); // expected-error {{deduced as 'int' in declaration of 'a' and deduced as 'double' in declaration of 'b'}} + } + // We've already diagnosed an issue. No extra diagnostics is needed for these. + template void f<int>(); + template void f<double>(); + template void f<char>(); +} diff --git a/test/SemaCXX/enum-scoped.cpp b/test/SemaCXX/enum-scoped.cpp index 7fdcf0d573a9..cf579e180f69 100644 --- a/test/SemaCXX/enum-scoped.cpp +++ b/test/SemaCXX/enum-scoped.cpp @@ -96,3 +96,10 @@ enum Redeclare6 : short; // expected-error{{redeclared with different underlying enum class Redeclare7; // expected-note{{previous use is here}} expected-note{{previous use is here}} enum class Redeclare7 : short; // expected-error{{redeclared with different underlying type}} enum class Redeclare7 : short; // expected-error{{redeclared with different underlying type}} + +enum : long { + long_enum_val = 10000 +}; + +enum : long x; // expected-error{{unnamed enumeration must be a definition}} \ +// expected-warning{{declaration does not declare anything}} diff --git a/test/SemaCXX/linkage.cpp b/test/SemaCXX/linkage.cpp index ba56318fbd68..6b73d596e01b 100644 --- a/test/SemaCXX/linkage.cpp +++ b/test/SemaCXX/linkage.cpp @@ -3,7 +3,7 @@ // compared against the earlier cached value. If we had a way of // testing linkage directly in Sema, that would be better. -// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -Werror -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck %s // PR8926 namespace test0 { @@ -64,5 +64,33 @@ namespace test3 { extern "C" void test3(A a) {} } +namespace { + // CHECK: define void @test4( + extern "C" void test4(void) {} +} + +// PR9316: Ensure that even non-namespace-scope function declarations in +// a C declaration context respect that over the anonymous namespace. +extern "C" { + namespace { + struct X { + int f() { + extern int g(); + extern int a; + + // Test both for mangling in the code generation and warnings from use + // of internal, undefined names via -Werror. + // CHECK: call i32 @g( + // CHECK: load i32* @a, + return g() + a; + } + }; + } + // Force the above function to be emitted by codegen. + int test(X& x) { + return x.f(); + } +} + // CHECK: define linkonce_odr i8* @_ZN5test21A1BILj0EE3fooEv( // CHECK: define linkonce_odr i8* @_ZN5test11A3fooILj0EEEPvv( diff --git a/test/SemaCXX/member-expr.cpp b/test/SemaCXX/member-expr.cpp index a4a39d780163..3c3eb04e08fa 100644 --- a/test/SemaCXX/member-expr.cpp +++ b/test/SemaCXX/member-expr.cpp @@ -28,7 +28,7 @@ struct B { A *f0(); }; int f0(B *b) { - return b->f0->f0; // expected-error{{perhaps you meant to call this function}} + return b->f0->f0; // expected-error{{perhaps you meant to call it with no arguments}} } int i; @@ -121,7 +121,7 @@ namespace PR9025 { S fun(); int fun(int i); int g() { - return fun.x; // expected-error{{base of member reference is an overloaded function; perhaps you meant to call the 0-argument overload?}} + return fun.x; // expected-error{{base of member reference is an overloaded function; perhaps you meant to call it with no arguments?}} } S fun2(); // expected-note{{possibly valid overload here}} @@ -129,4 +129,10 @@ namespace PR9025 { int g2() { return fun2.x; // expected-error{{base of member reference is an overloaded function; perhaps you meant to call it?}} } + + S fun3(int i=0); + int fun3(int i, int j); + int g3() { + return fun3.x; // expected-error{{base of member reference is an overloaded function; perhaps you meant to call it with no arguments?}} + } } diff --git a/test/SemaCXX/nested-name-spec-locations.cpp b/test/SemaCXX/nested-name-spec-locations.cpp new file mode 100644 index 000000000000..25914df627bd --- /dev/null +++ b/test/SemaCXX/nested-name-spec-locations.cpp @@ -0,0 +1,70 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// Note: the formatting in this test case is intentionally funny, with +// nested-name-specifiers stretched out vertically so that we can +// match up diagnostics per-line and still verify that we're getting +// good source-location information. + +namespace outer { + namespace inner { + template<typename T> + struct X0 { + }; + } +} + +template<typename T> +struct add_reference { + typedef T& type; +}; + +namespace outer_alias = outer; + +template<typename T> +struct UnresolvedUsingValueDeclTester { + using outer::inner::X0< + typename add_reference<T>::type + * // expected-error{{declared as a pointer to a reference of type}} + >::value; +}; + +UnresolvedUsingValueDeclTester<int> UnresolvedUsingValueDeclCheck; // expected-note{{in instantiation of template class}} + +template<typename T> +struct UnresolvedUsingTypenameDeclTester { + using outer::inner::X0< + typename add_reference<T>::type + * // expected-error{{declared as a pointer to a reference of type}} + >::value; +}; + +UnresolvedUsingTypenameDeclTester<int> UnresolvedUsingTypenameDeclCheck; // expected-note{{in instantiation of template class}} + + +template<typename T, typename U> +struct PseudoDestructorExprTester { + void f(T *t) { + t->T::template Inner<typename add_reference<U>::type + * // expected-error{{as a pointer to a reference of type}} + >::Blarg::~Blarg(); + } +}; + +struct HasInnerTemplate { + template<typename T> + struct Inner; + + typedef HasInnerTemplate T; +}; + +void PseudoDestructorExprCheck( + PseudoDestructorExprTester<HasInnerTemplate, float> tester) { + tester.f(0); // expected-note{{in instantiation of member function}} +} + +template<typename T> +struct DependentScopedDeclRefExpr { + void f() { + outer_alias::inner::X0<T>::value = 17; + } +}; diff --git a/test/SemaCXX/nested-name-spec.cpp b/test/SemaCXX/nested-name-spec.cpp index 1eb7014743cb..fef70931717e 100644 --- a/test/SemaCXX/nested-name-spec.cpp +++ b/test/SemaCXX/nested-name-spec.cpp @@ -263,3 +263,6 @@ namespace rdar7980179 { class A { void f0(); }; // expected-note {{previous}} int A::f0() {} // expected-error {{out-of-line definition of 'rdar7980179::A::f0' differ from the declaration in the return type}} } + +namespace alias = A; +double *dp = (alias::C*)0; // expected-error{{cannot initialize a variable of type 'double *' with an rvalue of type 'alias::C *'}} diff --git a/test/SemaCXX/return.cpp b/test/SemaCXX/return.cpp index 441c20f152b1..46524fccfcc5 100644 --- a/test/SemaCXX/return.cpp +++ b/test/SemaCXX/return.cpp @@ -24,5 +24,20 @@ const S class_c(); const volatile S class_cv(); const int scalar_c(); // expected-warning{{'const' type qualifier on return type has no effect}} +int const scalar_c2(); // expected-warning{{'const' type qualifier on return type has no effect}} + +const +char* +const // expected-warning{{'const' type qualifier on return type has no effect}} +f(); + +char +const* +const // expected-warning{{'const' type qualifier on return type has no effect}} +g(); + +char* const h(); // expected-warning{{'const' type qualifier on return type has no effect}} +char* volatile i(); // expected-warning{{'volatile' type qualifier on return type has no effect}} + const volatile int scalar_cv(); // expected-warning{{'const volatile' type qualifiers on return type have no effect}} } diff --git a/test/SemaCXX/shift.cpp b/test/SemaCXX/shift.cpp new file mode 100644 index 000000000000..d5a5bed9ea7a --- /dev/null +++ b/test/SemaCXX/shift.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -Wall -Wshift-sign-overflow -ffreestanding -fsyntax-only -verify %s + +#include <limits.h> + +#define WORD_BIT (sizeof(int) * CHAR_BIT) + +template <int N> void f() { + (void)(N << 30); // expected-warning {{bits to represent, but 'int' only has}} + (void)(30 << N); // expected-warning {{bits to represent, but 'int' only has}} +} + +void test() { + f<30>(); // expected-note {{instantiation}} +} diff --git a/test/SemaCXX/switch.cpp b/test/SemaCXX/switch.cpp index fc13630bbf12..3882a1f952ca 100644 --- a/test/SemaCXX/switch.cpp +++ b/test/SemaCXX/switch.cpp @@ -57,3 +57,10 @@ namespace test3 { template void foo<B>(); template void foo<C>(); //expected-note {{in instantiation}} } + +// PR9304 and rdar://9045501 +void click_check_header_sizes() { + switch (0 == 8) { // expected-warning {{switch condition has boolean value}} + case 0: ; + } +} diff --git a/test/SemaCXX/undefined-internal.cpp b/test/SemaCXX/undefined-internal.cpp index bb87ce0f126c..e926f18d5ff2 100644 --- a/test/SemaCXX/undefined-internal.cpp +++ b/test/SemaCXX/undefined-internal.cpp @@ -84,3 +84,41 @@ namespace test5 { B<A>::foo(); // expected-note {{used here}} } } + +namespace test6 { + template <class T> struct A { + static const int zero = 0; + static const int one = 1; + static const int two = 2; + + int value; + + A() : value(zero) { + value = one; + } + }; + + namespace { struct Internal; } + + void test() { + A<Internal> a; + a.value = A<Internal>::two; + } +} + +// We support (as an extension) private, undefined copy constructors when +// a temporary is bound to a reference even in C++98. Similarly, we shouldn't +// warn about this copy constructor being used without a definition. +namespace PR9323 { + namespace { + struct Uncopyable { + Uncopyable() {} + private: + Uncopyable(const Uncopyable&); // expected-note {{declared private here}} + }; + } + void f(const Uncopyable&) {} + void test() { + f(Uncopyable()); // expected-warning {{C++98 requires an accessible copy constructor}} + }; +} diff --git a/test/SemaCXX/warn-unused-result.cpp b/test/SemaCXX/warn-unused-result.cpp new file mode 100644 index 000000000000..d14fdf9833ff --- /dev/null +++ b/test/SemaCXX/warn-unused-result.cpp @@ -0,0 +1,44 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +int f() __attribute__((warn_unused_result)); + +struct S { + void t() const; +}; +S g1() __attribute__((warn_unused_result)); +S *g2() __attribute__((warn_unused_result)); +S &g3() __attribute__((warn_unused_result)); + +void test() { + f(); // expected-warning {{ignoring return value}} + g1(); // expected-warning {{ignoring return value}} + g2(); // expected-warning {{ignoring return value}} + g3(); // expected-warning {{ignoring return value}} + + (void)f(); + (void)g1(); + (void)g2(); + (void)g3(); + + if (f() == 0) return; + + g1().t(); + g2()->t(); + g3().t(); + + int i = f(); + S s1 = g1(); + S *s2 = g2(); + S &s3 = g3(); + const S &s4 = g1(); +} + +struct X { + int foo() __attribute__((warn_unused_result)); +}; + +void bah() { + X x, *x2; + x.foo(); // expected-warning {{ignoring return value}} + x2->foo(); // expected-warning {{ignoring return value}} +} diff --git a/test/SemaCXX/warn-unused-variables.cpp b/test/SemaCXX/warn-unused-variables.cpp index 8ae7d6ace4da..81f22a796a0e 100644 --- a/test/SemaCXX/warn-unused-variables.cpp +++ b/test/SemaCXX/warn-unused-variables.cpp @@ -32,17 +32,6 @@ namespace PR5531 { } } - -struct X { - int foo() __attribute__((warn_unused_result)); -}; - -void bah() { - X x, *x2; - x.foo(); // expected-warning {{ignoring return value of function declared with warn_unused_result attribute}} - x2->foo(); // expected-warning {{ignoring return value of function declared with warn_unused_result attribute}} -} - template<typename T> struct X0 { }; diff --git a/test/SemaObjC/auto-objective-c.m b/test/SemaObjC/auto-objective-c.m new file mode 100644 index 000000000000..5467e24a7951 --- /dev/null +++ b/test/SemaObjC/auto-objective-c.m @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -x objective-c -fblocks -fsyntax-only -verify %s + +@interface I +{ + id pi; +} +- (id) Meth; +@end + +// Objective-C does not support trailing return types, so check we don't get +// the C++ diagnostic suggesting we forgot one. +auto noTrailingReturnType(); // expected-error {{'auto' not allowed in function return type}} + +typedef int (^P) (int x); + +@implementation I +- (id) Meth { + auto p = [pi Meth]; + return p; +} + +- (P) bfunc { + auto my_block = ^int (int x) {return x; }; + my_block(1); + return my_block; +} +@end + + +// rdar://9036633 +int main() { + auto int auto_i = 7; // expected-warning {{'auto' storage class specifier is redundant and will be removed in future releases}} +} diff --git a/test/Sema/block-as-object.m b/test/SemaObjC/block-as-object.m index a85b6067571e..a85b6067571e 100644 --- a/test/Sema/block-as-object.m +++ b/test/SemaObjC/block-as-object.m diff --git a/test/SemaObjC/catch-stmt.m b/test/SemaObjC/catch-stmt.m index ef1da377094c..dcb47640e844 100644 --- a/test/SemaObjC/catch-stmt.m +++ b/test/SemaObjC/catch-stmt.m @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -verify %s +// RUN: %clang_cc1 -verify -fobjc-exceptions %s @interface A @end @protocol P; diff --git a/test/SemaObjC/conflict-nonfragile-abi2.m b/test/SemaObjC/conflict-nonfragile-abi2.m index 86947cf7643c..5d6b2810fc10 100644 --- a/test/SemaObjC/conflict-nonfragile-abi2.m +++ b/test/SemaObjC/conflict-nonfragile-abi2.m @@ -1,10 +1,10 @@ // RUN: %clang_cc1 -fobjc-nonfragile-abi -verify -fsyntax-only %s // rdar://8225011 -int glob; // expected-note {{global variable declared here}} +int glob; @interface I -@property int glob; // expected-note {{property declared here}} +@property int glob; @property int p; @property int le; @property int l; @@ -12,8 +12,10 @@ int glob; // expected-note {{global variable declared here}} @property int r; @end +// rdar://9027673 +// Warning on future name lookup rule is removed. @implementation I -- (int) Meth { return glob; } // expected-warning {{when default property synthesis is on, 'glob' lookup will access}} +- (int) Meth { return glob; } // no warning @synthesize glob; // rdar://8248681 - (int) Meth1: (int) p { diff --git a/test/SemaObjC/dist-object-modifiers.m b/test/SemaObjC/dist-object-modifiers.m new file mode 100644 index 000000000000..98a9ce6cdc52 --- /dev/null +++ b/test/SemaObjC/dist-object-modifiers.m @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// rdar://7076235 + +@protocol P +- (bycopy id)serverPID; // expected-note {{previous declaration is here}} +- (void)doStuff:(bycopy id)clientId; // expected-note {{previous declaration is here}} +- (bycopy id)Ok; ++ (oneway id) stillMore : (byref id)Arg : (bycopy oneway id)Arg1; // expected-note 3 {{previous declaration is here}} +@end + +@interface I <P> +- (id)Ok; +@end + +@implementation I +- (id)serverPID { return 0; } // expected-warning {{conflicting distributed object modifiers on return type in implementation of 'serverPID'}} +- (void)doStuff:(id)clientId { } // expected-warning {{conflicting distributed object modifiers on parameter type in implementation of 'doStuff:'}} +- (bycopy id)Ok { return 0; } ++ (id) stillMore : (id)Arg : (bycopy id)Arg1 { return Arg; } // expected-warning {{conflicting distributed object modifiers on return type in implementation of 'stillMore::'}} \ + // expected-warning 2{{conflicting distributed object modifiers on parameter type in implementation of 'stillMore::'}} +@end diff --git a/test/SemaObjC/invalid-code.m b/test/SemaObjC/invalid-code.m index 7a642fb10784..9b7f2c8a975a 100644 --- a/test/SemaObjC/invalid-code.m +++ b/test/SemaObjC/invalid-code.m @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -fsyntax-only -verify +// RUN: %clang_cc1 %s -fsyntax-only -verify -fobjc-exceptions // rdar://6124613 void test1() { diff --git a/test/SemaObjC/no-objc-exceptions.m b/test/SemaObjC/no-objc-exceptions.m index 78419a247557..d47f51a84ebf 100644 --- a/test/SemaObjC/no-objc-exceptions.m +++ b/test/SemaObjC/no-objc-exceptions.m @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fno-objc-exceptions -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -verify %s void f() { @throw @"Hello"; // expected-error {{cannot use '@throw' with Objective-C exceptions disabled}} diff --git a/test/SemaObjC/property-6.m b/test/SemaObjC/property-6.m index 72beb67b43e4..933a4f0673f8 100644 --- a/test/SemaObjC/property-6.m +++ b/test/SemaObjC/property-6.m @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -verify -fobjc-exceptions %s # 1 "<command line>" # 1 "/System/Library/Frameworks/Foundation.framework/Headers/Foundation.h" 1 3 typedef signed char BOOL; diff --git a/test/Sema/rdar6248119.m b/test/SemaObjC/rdar6248119.m index 6b120b284756..046992c52fe5 100644 --- a/test/Sema/rdar6248119.m +++ b/test/SemaObjC/rdar6248119.m @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only %s -verify +// RUN: %clang_cc1 -fsyntax-only %s -verify -fobjc-exceptions // Test case for: // <rdar://problem/6248119> @finally doesn't introduce a new scope diff --git a/test/SemaObjC/return.m b/test/SemaObjC/return.m index 116abd19e7e7..3a626e369603 100644 --- a/test/SemaObjC/return.m +++ b/test/SemaObjC/return.m @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -fsyntax-only -verify -Wmissing-noreturn +// RUN: %clang_cc1 %s -fsyntax-only -verify -Wmissing-noreturn -fobjc-exceptions int test1() { id a; diff --git a/test/SemaObjC/scope-check.m b/test/SemaObjC/scope-check.m index bba321e65766..3f474be6e8df 100644 --- a/test/SemaObjC/scope-check.m +++ b/test/SemaObjC/scope-check.m @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -verify -fobjc-exceptions %s @class A, B, C; diff --git a/test/SemaObjC/stmts.m b/test/SemaObjC/stmts.m index d1e2ad3612e0..d452db8c8b2c 100644 --- a/test/SemaObjC/stmts.m +++ b/test/SemaObjC/stmts.m @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -verify -fsyntax-only +// RUN: %clang_cc1 %s -verify -fsyntax-only -fobjc-exceptions struct some_struct; diff --git a/test/SemaObjC/try-catch.m b/test/SemaObjC/try-catch.m index 01fc4f4f2c56..da06eca47026 100644 --- a/test/SemaObjC/try-catch.m +++ b/test/SemaObjC/try-catch.m @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -verify -fobjc-exceptions %s typedef signed char BOOL; typedef struct _NSZone NSZone; diff --git a/test/SemaObjC/warn-unused-exception-param.m b/test/SemaObjC/warn-unused-exception-param.m index f649f8c81219..221e16ff6478 100644 --- a/test/SemaObjC/warn-unused-exception-param.m +++ b/test/SemaObjC/warn-unused-exception-param.m @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -Wunused-exception-parameter %s +// RUN: %clang_cc1 -fsyntax-only -verify -fobjc-exceptions -Wunused-exception-parameter %s void f0() { @try {} @catch(id a) {} // expected-warning{{unused exception parameter 'a'}} } diff --git a/test/SemaObjCXX/instantiate-stmt.mm b/test/SemaObjCXX/instantiate-stmt.mm index 5e8ec61573d4..ff72858afd3f 100644 --- a/test/SemaObjCXX/instantiate-stmt.mm +++ b/test/SemaObjCXX/instantiate-stmt.mm @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -verify -fobjc-exceptions %s @interface NSException @end diff --git a/tools/driver/CMakeLists.txt b/tools/driver/CMakeLists.txt index 6dc47d656cf9..552e7a534427 100644 --- a/tools/driver/CMakeLists.txt +++ b/tools/driver/CMakeLists.txt @@ -33,6 +33,8 @@ add_clang_executable(clang cc1as_main.cpp ) +set_target_properties(clang PROPERTIES VERSION ${CLANG_EXECUTABLE_VERSION}) + if(UNIX) set(CLANGXX_LINK_OR_COPY create_symlink) else() @@ -46,6 +48,8 @@ add_custom_target(clang++ ALL "${LLVM_BINARY_DIR}/bin/${CMAKE_CFG_INTDIR}/clang${CMAKE_EXECUTABLE_SUFFIX}" "${clang_pp}" DEPENDS clang) +set_target_properties(clang++ PROPERTIES FOLDER "Clang executables") + set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES ${clang_pp}) diff --git a/tools/driver/clang_symlink.cmake b/tools/driver/clang_symlink.cmake index 40a74824cf2b..c7341cb2fa61 100644 --- a/tools/driver/clang_symlink.cmake +++ b/tools/driver/clang_symlink.cmake @@ -9,9 +9,16 @@ else() set(CLANGXX_LINK_OR_COPY copy) endif() +# CMAKE_EXECUTABLE_SUFFIX is undefined on cmake scripts. See PR9286. +if( WIN32 ) + set(EXECUTABLE_SUFFIX ".exe") +else() + set(EXECUTABLE_SUFFIX "") +endif() + set(bindir "${CLANGXX_DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/") -set(clang "clang${CMAKE_EXECUTABLE_SUFFIX}") -set(clangxx "clang++${CMAKE_EXECUTABLE_SUFFIX}") +set(clang "clang${EXECUTABLE_SUFFIX}") +set(clangxx "clang++${EXECUTABLE_SUFFIX}") message("Creating clang++ executable based on ${clang}") diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index e2882953c080..cd1b8d66673a 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -140,6 +140,7 @@ public: DeclRefExprPartsKind, LabelRefVisitKind, ExplicitTemplateArgsVisitKind, NestedNameSpecifierVisitKind, + NestedNameSpecifierLocVisitKind, DeclarationNameInfoVisitKind, MemberRefVisitKind, SizeOfPackExprPartsKind }; protected: @@ -310,6 +311,7 @@ public: // Name visitor bool VisitDeclarationNameInfo(DeclarationNameInfo Name); bool VisitNestedNameSpecifier(NestedNameSpecifier *NNS, SourceRange Range); + bool VisitNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS); // Template visitors bool VisitTemplateParameters(const TemplateParameterList *Params); @@ -685,6 +687,11 @@ bool CursorVisitor::VisitDeclaratorDecl(DeclaratorDecl *DD) { if (Visit(TSInfo->getTypeLoc())) return true; + // Visit the nested-name-specifier, if present. + if (NestedNameSpecifierLoc QualifierLoc = DD->getQualifierLoc()) + if (VisitNestedNameSpecifierLoc(QualifierLoc)) + return true; + return false; } @@ -718,8 +725,8 @@ bool CursorVisitor::VisitFunctionDecl(FunctionDecl *ND) { return true; // Visit the nested-name-specifier, if present. - if (NestedNameSpecifier *Qualifier = ND->getQualifier()) - if (VisitNestedNameSpecifier(Qualifier, ND->getQualifierRange())) + if (NestedNameSpecifierLoc QualifierLoc = ND->getQualifierLoc()) + if (VisitNestedNameSpecifierLoc(QualifierLoc)) return true; // Visit the declaration name. @@ -1074,8 +1081,8 @@ bool CursorVisitor::VisitNamespaceDecl(NamespaceDecl *D) { bool CursorVisitor::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { // Visit nested-name-specifier. - if (NestedNameSpecifier *Qualifier = D->getQualifier()) - if (VisitNestedNameSpecifier(Qualifier, D->getQualifierRange())) + if (NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc()) + if (VisitNestedNameSpecifierLoc(QualifierLoc)) return true; return Visit(MakeCursorNamespaceRef(D->getAliasedNamespace(), @@ -1084,9 +1091,10 @@ bool CursorVisitor::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { bool CursorVisitor::VisitUsingDecl(UsingDecl *D) { // Visit nested-name-specifier. - if (NestedNameSpecifier *Qualifier = D->getTargetNestedNameDecl()) - if (VisitNestedNameSpecifier(Qualifier, D->getNestedNameRange())) + if (NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc()) { + if (VisitNestedNameSpecifierLoc(QualifierLoc)) return true; + } if (Visit(MakeCursorOverloadedDeclRef(D, D->getLocation(), TU))) return true; @@ -1096,8 +1104,8 @@ bool CursorVisitor::VisitUsingDecl(UsingDecl *D) { bool CursorVisitor::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { // Visit nested-name-specifier. - if (NestedNameSpecifier *Qualifier = D->getQualifier()) - if (VisitNestedNameSpecifier(Qualifier, D->getQualifierRange())) + if (NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc()) + if (VisitNestedNameSpecifierLoc(QualifierLoc)) return true; return Visit(MakeCursorNamespaceRef(D->getNominatedNamespaceAsWritten(), @@ -1106,9 +1114,10 @@ bool CursorVisitor::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { bool CursorVisitor::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) { // Visit nested-name-specifier. - if (NestedNameSpecifier *Qualifier = D->getTargetNestedNameSpecifier()) - if (VisitNestedNameSpecifier(Qualifier, D->getTargetNestedNameRange())) + if (NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc()) { + if (VisitNestedNameSpecifierLoc(QualifierLoc)) return true; + } return VisitDeclarationNameInfo(D->getNameInfo()); } @@ -1116,8 +1125,8 @@ bool CursorVisitor::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) { bool CursorVisitor::VisitUnresolvedUsingTypenameDecl( UnresolvedUsingTypenameDecl *D) { // Visit nested-name-specifier. - if (NestedNameSpecifier *Qualifier = D->getTargetNestedNameSpecifier()) - if (VisitNestedNameSpecifier(Qualifier, D->getTargetNestedNameRange())) + if (NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc()) + if (VisitNestedNameSpecifierLoc(QualifierLoc)) return true; return false; @@ -1163,11 +1172,13 @@ bool CursorVisitor::VisitNestedNameSpecifier(NestedNameSpecifier *NNS, switch (NNS->getKind()) { case NestedNameSpecifier::Namespace: - // FIXME: The token at this source location might actually have been a - // namespace alias, but we don't model that. Lame! return Visit(MakeCursorNamespaceRef(NNS->getAsNamespace(), Range.getBegin(), TU)); + case NestedNameSpecifier::NamespaceAlias: + return Visit(MakeCursorNamespaceRef(NNS->getAsNamespaceAlias(), + Range.getBegin(), TU)); + case NestedNameSpecifier::TypeSpec: { // If the type has a form where we know that the beginning of the source // range matches up with a reference cursor. Visit the appropriate reference @@ -1192,6 +1203,48 @@ bool CursorVisitor::VisitNestedNameSpecifier(NestedNameSpecifier *NNS, return false; } +bool +CursorVisitor::VisitNestedNameSpecifierLoc(NestedNameSpecifierLoc Qualifier) { + llvm::SmallVector<NestedNameSpecifierLoc, 4> Qualifiers; + for (; Qualifier; Qualifier = Qualifier.getPrefix()) + Qualifiers.push_back(Qualifier); + + while (!Qualifiers.empty()) { + NestedNameSpecifierLoc Q = Qualifiers.pop_back_val(); + NestedNameSpecifier *NNS = Q.getNestedNameSpecifier(); + switch (NNS->getKind()) { + case NestedNameSpecifier::Namespace: + if (Visit(MakeCursorNamespaceRef(NNS->getAsNamespace(), + Q.getLocalBeginLoc(), + TU))) + return true; + + break; + + case NestedNameSpecifier::NamespaceAlias: + if (Visit(MakeCursorNamespaceRef(NNS->getAsNamespaceAlias(), + Q.getLocalBeginLoc(), + TU))) + return true; + + break; + + case NestedNameSpecifier::TypeSpec: + case NestedNameSpecifier::TypeSpecWithTemplate: + if (Visit(Q.getTypeLoc())) + return true; + + break; + + case NestedNameSpecifier::Global: + case NestedNameSpecifier::Identifier: + break; + } + } + + return false; +} + bool CursorVisitor::VisitTemplateParameters( const TemplateParameterList *Params) { if (!Params) @@ -1455,6 +1508,11 @@ bool CursorVisitor::VisitPackExpansionTypeLoc(PackExpansionTypeLoc TL) { } bool CursorVisitor::VisitCXXRecordDecl(CXXRecordDecl *D) { + // Visit the nested-name-specifier, if present. + if (NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc()) + if (VisitNestedNameSpecifierLoc(QualifierLoc)) + return true; + if (D->isDefinition()) { for (CXXRecordDecl::base_class_iterator I = D->bases_begin(), E = D->bases_end(); I != E; ++I) { @@ -1558,6 +1616,24 @@ public: return SourceRange(A, B); } }; + +class NestedNameSpecifierLocVisit : public VisitorJob { +public: + NestedNameSpecifierLocVisit(NestedNameSpecifierLoc Qualifier, CXCursor parent) + : VisitorJob(parent, VisitorJob::NestedNameSpecifierLocVisitKind, + Qualifier.getNestedNameSpecifier(), + Qualifier.getOpaqueData()) { } + + static bool classof(const VisitorJob *VJ) { + return VJ->getKind() == VisitorJob::NestedNameSpecifierLocVisitKind; + } + + NestedNameSpecifierLoc get() const { + return NestedNameSpecifierLoc(static_cast<NestedNameSpecifier*>(data[0]), + data[1]); + } +}; + class DeclarationNameInfoVisit : public VisitorJob { public: DeclarationNameInfoVisit(Stmt *S, CXCursor parent) @@ -1640,6 +1716,7 @@ public: private: void AddDeclarationNameInfo(Stmt *S); void AddNestedNameSpecifier(NestedNameSpecifier *NS, SourceRange R); + void AddNestedNameSpecifierLoc(NestedNameSpecifierLoc Qualifier); void AddExplicitTemplateArgs(const ExplicitTemplateArgumentList *A); void AddMemberRef(FieldDecl *D, SourceLocation L); void AddStmt(Stmt *S); @@ -1659,6 +1736,13 @@ void EnqueueVisitor::AddNestedNameSpecifier(NestedNameSpecifier *N, if (N) WL.push_back(NestedNameSpecifierVisit(N, R, Parent)); } + +void +EnqueueVisitor::AddNestedNameSpecifierLoc(NestedNameSpecifierLoc Qualifier) { + if (Qualifier) + WL.push_back(NestedNameSpecifierLocVisit(Qualifier, Parent)); +} + void EnqueueVisitor::AddStmt(Stmt *S) { if (S) WL.push_back(StmtVisit(S, Parent)); @@ -1743,8 +1827,8 @@ void EnqueueVisitor::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) { // but isn't. AddTypeLoc(E->getScopeTypeInfo()); // Visit the nested-name-specifier. - if (NestedNameSpecifier *Qualifier = E->getQualifier()) - AddNestedNameSpecifier(Qualifier, E->getQualifierRange()); + if (NestedNameSpecifierLoc QualifierLoc = E->getQualifierLoc()) + AddNestedNameSpecifierLoc(QualifierLoc); // Visit base expression. AddStmt(E->getBase()); } @@ -1780,8 +1864,7 @@ void EnqueueVisitor::VisitDeclRefExpr(DeclRefExpr *DR) { void EnqueueVisitor::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) { AddExplicitTemplateArgs(E->getOptionalExplicitTemplateArgs()); AddDeclarationNameInfo(E); - if (NestedNameSpecifier *Qualifier = E->getQualifier()) - AddNestedNameSpecifier(Qualifier, E->getQualifierRange()); + AddNestedNameSpecifierLoc(E->getQualifierLoc()); } void EnqueueVisitor::VisitDeclStmt(DeclStmt *S) { unsigned size = WL.size(); @@ -1983,18 +2066,29 @@ bool CursorVisitor::RunVisitorWorkList(VisitorWorkList &WL) { } case VisitorJob::LabelRefVisitKind: { LabelDecl *LS = cast<LabelRefVisit>(&LI)->get(); - if (Visit(MakeCursorLabelRef(LS->getStmt(), - cast<LabelRefVisit>(&LI)->getLoc(), - TU))) - return true; + if (LabelStmt *stmt = LS->getStmt()) { + if (Visit(MakeCursorLabelRef(stmt, cast<LabelRefVisit>(&LI)->getLoc(), + TU))) { + return true; + } + } continue; } + case VisitorJob::NestedNameSpecifierVisitKind: { NestedNameSpecifierVisit *V = cast<NestedNameSpecifierVisit>(&LI); if (VisitNestedNameSpecifier(V->get(), V->getSourceRange())) return true; continue; } + + case VisitorJob::NestedNameSpecifierLocVisitKind: { + NestedNameSpecifierLocVisit *V = cast<NestedNameSpecifierLocVisit>(&LI); + if (VisitNestedNameSpecifierLoc(V->get())) + return true; + continue; + } + case VisitorJob::DeclarationNameInfoVisitKind: { if (VisitDeclarationNameInfo(cast<DeclarationNameInfoVisit>(&LI) ->get())) diff --git a/tools/libclang/CMakeLists.txt b/tools/libclang/CMakeLists.txt index da72f5a02d01..11759eefb6d3 100644 --- a/tools/libclang/CMakeLists.txt +++ b/tools/libclang/CMakeLists.txt @@ -30,15 +30,10 @@ add_clang_library(libclang ) if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - # dylib versioning information - # FIXME: Is there a more CMake-ish way to handle this? - set(LIBCLANG_VERSION 1 - CACHE STRING "Version number of the libclang library") - set(LIBCLANG_SUBVERSION 0 - CACHE STRING "Minor version number of the libclang library") - set(LIBCLANG_LINK_FLAGS - "-Wl,-current_version -Wl,${LIBCLANG_VERSION}.${LIBCLANG_SUBVERSION} -Wl,-compatibility_version -Wl,1") + # Darwin-specific linker flags + set(LIBCLANG_LINK_FLAGS "-Wl,-compatibility_version -Wl,1") + set(LIBCLANG_LINK_FLAGS "${LIBCLANG_LINK_FLAGS} -Wl,-dead_strip -Wl,-seg1addr -Wl,0xE0000000") @@ -48,6 +43,9 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") INSTALL_NAME_DIR "@executable_path/../lib") endif() +# Versioning information +set_target_properties(libclang PROPERTIES VERSION ${LIBCLANG_LIBRARY_VERSION}) + if(MSVC) # windows.h doesn't compile with /Za get_target_property(NON_ANSI_COMPILE_FLAGS libclang COMPILE_FLAGS) diff --git a/tools/scan-build/scan-build b/tools/scan-build/scan-build index 80585b1f7c7e..f7e521f49ecb 100755 --- a/tools/scan-build/scan-build +++ b/tools/scan-build/scan-build @@ -1005,12 +1005,95 @@ ADVANCED OPTIONS: cost of speed. ENDTEXT -# FIXME: Print out available analyesis. +# Query clang for list of checkers that are enabled. +my %EnabledCheckers; +foreach my $lang ("c", "objective-c", "objective-c++", "c++") { + pipe(FROM_CHILD, TO_PARENT); + my $pid = fork(); + if ($pid == 0) { + close FROM_CHILD; + open(STDOUT,">&", \*TO_PARENT); + open(STDERR,">&", \*TO_PARENT); + exec $Clang, ('--analyze', '-x', $lang, '-', '-###'); + } + close(TO_PARENT); + while(<FROM_CHILD>) { + foreach my $val (split /\s+/) { + $val =~ s/\"//g; + if ($val =~ /-analyzer-checker\=([^\s]+)/) { + $EnabledCheckers{$1} = 1; + } + } + } + waitpid($pid,0); + close(FROM_CHILD); +} + +# Query clang for complete list of checkers. +pipe(FROM_CHILD, TO_PARENT); +my $pid = fork(); +if ($pid == 0) { + close FROM_CHILD; + open(STDOUT,">&", \*TO_PARENT); + open(STDERR,">&", \*TO_PARENT); + exec $Clang, ('-cc1', '-analyzer-checker-help'); +} +close(TO_PARENT); +my $foundCheckers = 0; +while(<FROM_CHILD>) { + if (/CHECKERS:/) { + $foundCheckers = 1; + last; + } +} +if (!$foundCheckers) { + print " *** Could not query Clang for the list of available checkers."; +} +else { + print("\nAVAILABLE CHECKERS:\n\n"); + my $skip = 0; + while(<FROM_CHILD>) { + if (/core\.experimental/ or /debug\./ or /unix.experimental/ or /cocoa.experimental/) { + $skip = 1; + next; + } + if ($skip) { + next if (!/^\s\s[^\s]/); + $skip = 0; + } + s/^\s\s//; + if (/^([^\s]+)/) { + # Is the checker enabled? + my $checker = $1; + my $enabled = 0; + my $aggregate = ""; + foreach my $domain (split /\./, $checker) { + $aggregate .= $domain; + if ($EnabledCheckers{$aggregate}) { + $enabled =1; + last; + } + } + + if ($enabled) { + print " + "; + } + else { + print " "; + } + } + else { + print " "; + } + print $_; + } +} +waitpid($pid,0); +close(FROM_CHILD); print <<ENDTEXT - NOTE: "(+)" indicates that an analysis is enabled by default unless one - or more analysis options are specified + NOTE: "+" indicates that an analysis is enabled by default. BUILD OPTIONS @@ -1074,6 +1157,9 @@ if (!@ARGV) { exit 1; } + +my $displayHelp = 0; + while (@ARGV) { # Scan for options we recognize. @@ -1081,8 +1167,9 @@ while (@ARGV) { my $arg = $ARGV[0]; if ($arg eq "-h" or $arg eq "--help") { - DisplayHelp(); - exit 0; + $displayHelp = 1; + shift @ARGV; + next; } if ($arg eq '-analyze-headers') { @@ -1224,12 +1311,17 @@ while (@ARGV) { last; } -if (!@ARGV) { +if (!@ARGV and $displayHelp == 0) { Diag("No build command specified.\n\n"); + $displayHelp = 1; +} + +if ($displayHelp) { DisplayHelp(); exit 1; } +# Determine where results go. $CmdArgs = HtmlEscape(join(' ', map(ShellEscape($_), @ARGV))); $HtmlTitle = "${CurrentDirSuffix} - scan-build results" unless (defined($HtmlTitle)); @@ -1238,9 +1330,7 @@ $HtmlTitle = "${CurrentDirSuffix} - scan-build results" my $BaseDir = $HtmlDir; $HtmlDir = GetHTMLRunDir($HtmlDir); -# Set the appropriate environment variables. -SetHtmlEnv(\@ARGV, $HtmlDir); - +# Determine the location of ccc-analyzer. my $AbsRealBin = Cwd::realpath($RealBin); my $Cmd = "$AbsRealBin/libexec/ccc-analyzer"; my $CmdCXX = "$AbsRealBin/libexec/c++-analyzer"; @@ -1259,27 +1349,24 @@ if (!defined $ClangSB || ! -x $ClangSB) { Diag("Using 'clang' from path: $Clang\n"); } +# Set the appropriate environment variables. +SetHtmlEnv(\@ARGV, $HtmlDir); $ENV{'CC'} = $Cmd; $ENV{'CXX'} = $CmdCXX; $ENV{'CLANG'} = $Clang; $ENV{'CLANG_CXX'} = $ClangCXX; - if ($Verbose >= 2) { $ENV{'CCC_ANALYZER_VERBOSE'} = 1; } - if ($Verbose >= 3) { $ENV{'CCC_ANALYZER_LOG'} = 1; } - if ($AnalyzeHeaders) { push @AnalysesToRun,"-analyzer-opt-analyze-headers"; } - if ($AnalyzerStats) { push @AnalysesToRun, '-analyzer-stats'; } - if ($MaxLoop > 0) { push @AnalysesToRun, '-analyzer-max-loop ' . $MaxLoop; } @@ -1289,11 +1376,9 @@ $ENV{'CCC_ANALYZER_ANALYSIS'} = join ' ',@AnalysesToRun; if (defined $StoreModel) { $ENV{'CCC_ANALYZER_STORE_MODEL'} = $StoreModel; } - if (defined $ConstraintsModel) { $ENV{'CCC_ANALYZER_CONSTRAINTS_MODEL'} = $ConstraintsModel; } - if (defined $OutputFormat) { $ENV{'CCC_ANALYZER_OUTPUT_FORMAT'} = $OutputFormat; } diff --git a/tools/scan-view/ScanView.py b/tools/scan-view/ScanView.py index 837adae0f763..c6dddba6a764 100644 --- a/tools/scan-view/ScanView.py +++ b/tools/scan-view/ScanView.py @@ -641,7 +641,7 @@ File Bug</h3> def send_head(self, fields=None): if (self.server.options.onlyServeLocal and self.client_address[0] != '127.0.0.1'): - return self.send_error('401', 'Unauthorized host.') + return self.send_error(401, 'Unauthorized host.') if fields is None: fields = {} diff --git a/unittests/CMakeLists.txt b/unittests/CMakeLists.txt index d762aaf7f49b..112d6a0e509c 100644 --- a/unittests/CMakeLists.txt +++ b/unittests/CMakeLists.txt @@ -28,9 +28,11 @@ function(add_clang_unittest) endif() add_clang_executable(${test_name}Tests ${CLANG_UNITTEST_DEFAULT_ARGS}) add_dependencies(ClangUnitTests ${test_name}Tests) + set_target_properties(${test_name}Tests PROPERTIES FOLDER "Clang tests") endfunction() add_custom_target(ClangUnitTests) +set_target_properties(ClangUnitTests PROPERTIES FOLDER "Clang tests") include_directories(${LLVM_MAIN_SRC_DIR}/utils/unittest/googletest/include) add_definitions(-DGTEST_HAS_RTTI=0) diff --git a/www/cxx_status.html b/www/cxx_status.html index 942d0d3e7a29..e4a915a4b298 100644 --- a/www/cxx_status.html +++ b/www/cxx_status.html @@ -25,7 +25,7 @@ <!--*************************************************************************--> <h1>C++ and C++'0x Support in Clang</h1> <!--*************************************************************************--> -<p>Last updated: $Date: 2011-01-26 22:35:14 +0100 (Wed, 26 Jan 2011) $</p> +<p>Last updated: $Date: 2011-02-23 01:41:16 +0100 (Wed, 23 Feb 2011) $</p> <ul> <li><a href="#projects">Projects Building with Clang</a></li> @@ -216,10 +216,10 @@ welcome!</p> </tr> <tr> <td>auto type deduction</td> - <td></td> - <td></td> - <td></td> - <td></td> + <td class="complete" align="center"></td> + <td class="complete" align="center"></td> + <td class="complete" align="center"></td> + <td class="complete" align="center"></td> <td>7.1.6.2, 7.1.6.4</td> <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1984.pdf">N1984</a></td> </tr> |