diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2011-07-17 15:40:56 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2011-07-17 15:40:56 +0000 |
commit | 180abc3db9ae3b4fc63cd65b15697e6ffcc8a657 (patch) | |
tree | 2097d084eb235c0b12c0bff3445f4ec7bbaa8a12 | |
parent | 29cafa66ad3878dbb9f82615f19fa0bded2e443c (diff) | |
download | src-180abc3db9ae3b4fc63cd65b15697e6ffcc8a657.tar.gz src-180abc3db9ae3b4fc63cd65b15697e6ffcc8a657.zip |
Vendor import of clang trunk r135360:vendor/clang/clang-r135360
Notes
Notes:
svn path=/vendor/clang/dist/; revision=224135
svn path=/vendor/clang/clang-r135360/; revision=224136; tag=vendor/clang/clang-r135360
788 files changed, 45084 insertions, 11164 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index aa89823e76f8..3ad60eaff516 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,7 +20,11 @@ if( CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR ) endif() if( NOT EXISTS "${CLANG_PATH_TO_LLVM_BUILD}/bin/tblgen${CMAKE_EXECUTABLE_SUFFIX}" ) - message(FATAL_ERROR "Please set CLANG_PATH_TO_LLVM_BUILD to a directory containing a LLVM build.") + # Looking for bin/Debug/tblgen is a complete hack. How can we get + # around this? + if( NOT EXISTS "${CLANG_PATH_TO_LLVM_BUILD}/bin/Debug/tblgen${CMAKE_EXECUTABLE_SUFFIX}" ) + message(FATAL_ERROR "Please set CLANG_PATH_TO_LLVM_BUILD to a directory containing a LLVM build.") + endif() endif() list(APPEND CMAKE_MODULE_PATH "${CLANG_PATH_TO_LLVM_BUILD}/share/llvm/cmake") @@ -42,7 +46,12 @@ if( CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR ) include_directories("${PATH_TO_LLVM_BUILD}/include" "${LLVM_MAIN_INCLUDE_DIR}") link_directories("${PATH_TO_LLVM_BUILD}/lib") - set(LLVM_TABLEGEN_EXE "${PATH_TO_LLVM_BUILD}/bin/tblgen") + if( EXISTS "${CLANG_PATH_TO_LLVM_BUILD}/bin/tblgen${CMAKE_EXECUTABLE_SUFFIX}" ) + set(LLVM_TABLEGEN_EXE "${PATH_TO_LLVM_BUILD}/bin/tblgen") + else() + # FIXME: This is an utter hack. + set(LLVM_TABLEGEN_EXE "${PATH_TO_LLVM_BUILD}/bin/Debug/tblgen") + endif() set( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin ) set( CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib ) diff --git a/INPUTS/cfg-big-switch.c b/INPUTS/cfg-big-switch.c new file mode 100644 index 000000000000..a48b51a2e301 --- /dev/null +++ b/INPUTS/cfg-big-switch.c @@ -0,0 +1,27 @@ +#define EXPAND_2_CASES(i, x, y) CASE(i, x, y); CASE(i + 1, x, y); +#define EXPAND_4_CASES(i, x, y) EXPAND_2_CASES(i, x, y) EXPAND_2_CASES(i + 2, x, y) +#define EXPAND_8_CASES(i, x, y) EXPAND_4_CASES(i, x, y) EXPAND_4_CASES(i + 4, x, y) +#define EXPAND_16_CASES(i, x, y) EXPAND_8_CASES(i, x, y) EXPAND_8_CASES(i + 8, x, y) +#define EXPAND_32_CASES(i, x, y) EXPAND_16_CASES(i, x, y) EXPAND_16_CASES(i + 16, x, y) +#define EXPAND_64_CASES(i, x, y) EXPAND_32_CASES(i, x, y) EXPAND_32_CASES(i + 32, x, y) +#define EXPAND_128_CASES(i, x, y) EXPAND_64_CASES(i, x, y) EXPAND_64_CASES(i + 64, x, y) +#define EXPAND_256_CASES(i, x, y) EXPAND_128_CASES(i, x, y) EXPAND_128_CASES(i + 128, x, y) +#define EXPAND_512_CASES(i, x, y) EXPAND_256_CASES(i, x, y) EXPAND_256_CASES(i + 256, x, y) +#define EXPAND_1024_CASES(i, x, y) EXPAND_512_CASES(i, x, y) EXPAND_512_CASES(i + 512, x, y) +#define EXPAND_2048_CASES(i, x, y) EXPAND_1024_CASES(i, x, y) EXPAND_1024_CASES(i + 1024, x, y) +#define EXPAND_4096_CASES(i, x, y) EXPAND_2048_CASES(i, x, y) EXPAND_2048_CASES(i + 2048, x, y) + +// This has a *monstrous* single fan-out in the CFG, across 8000 blocks inside +// the while loop. +unsigned cfg_big_switch(int x) { + unsigned y = 0; + while (x > 0) { + switch(x) { +#define CASE(i, x, y) \ + case i: { int case_var = 3*x + i; y += case_var - 1; break; } +EXPAND_4096_CASES(0, x, y); + } + --x; + } + return y; +} diff --git a/INPUTS/cfg-long-chain1.c b/INPUTS/cfg-long-chain1.c new file mode 100644 index 000000000000..2f55b2ada205 --- /dev/null +++ b/INPUTS/cfg-long-chain1.c @@ -0,0 +1,20 @@ +#define EXPAND_2_BRANCHES(i, x, y) BRANCH(i, x, y); BRANCH(i + 1, x, y); +#define EXPAND_4_BRANCHES(i, x, y) EXPAND_2_BRANCHES(i, x, y) EXPAND_2_BRANCHES(i + 2, x, y) +#define EXPAND_8_BRANCHES(i, x, y) EXPAND_4_BRANCHES(i, x, y) EXPAND_4_BRANCHES(i + 4, x, y) +#define EXPAND_16_BRANCHES(i, x, y) EXPAND_8_BRANCHES(i, x, y) EXPAND_8_BRANCHES(i + 8, x, y) +#define EXPAND_32_BRANCHES(i, x, y) EXPAND_16_BRANCHES(i, x, y) EXPAND_16_BRANCHES(i + 16, x, y) +#define EXPAND_64_BRANCHES(i, x, y) EXPAND_32_BRANCHES(i, x, y) EXPAND_32_BRANCHES(i + 32, x, y) +#define EXPAND_128_BRANCHES(i, x, y) EXPAND_64_BRANCHES(i, x, y) EXPAND_64_BRANCHES(i + 64, x, y) +#define EXPAND_256_BRANCHES(i, x, y) EXPAND_128_BRANCHES(i, x, y) EXPAND_128_BRANCHES(i + 128, x, y) +#define EXPAND_512_BRANCHES(i, x, y) EXPAND_256_BRANCHES(i, x, y) EXPAND_256_BRANCHES(i + 256, x, y) +#define EXPAND_1024_BRANCHES(i, x, y) EXPAND_512_BRANCHES(i, x, y) EXPAND_512_BRANCHES(i + 512, x, y) +#define EXPAND_2048_BRANCHES(i, x, y) EXPAND_1024_BRANCHES(i, x, y) EXPAND_1024_BRANCHES(i + 1024, x, y) +#define EXPAND_4096_BRANCHES(i, x, y) EXPAND_2048_BRANCHES(i, x, y) EXPAND_2048_BRANCHES(i + 2048, x, y) + +unsigned cfg_long_chain_single_exit(unsigned x) { + unsigned y = 0; +#define BRANCH(i, x, y) if ((x % 13171) < i) { int var = x / 13171; y ^= var; } + EXPAND_4096_BRANCHES(1, x, y); +#undef BRANCH + return y; +} diff --git a/INPUTS/cfg-long-chain2.c b/INPUTS/cfg-long-chain2.c new file mode 100644 index 000000000000..150a084e57b9 --- /dev/null +++ b/INPUTS/cfg-long-chain2.c @@ -0,0 +1,20 @@ +#define EXPAND_2_BRANCHES(i, x, y) BRANCH(i, x, y); BRANCH(i + 1, x, y); +#define EXPAND_4_BRANCHES(i, x, y) EXPAND_2_BRANCHES(i, x, y) EXPAND_2_BRANCHES(i + 2, x, y) +#define EXPAND_8_BRANCHES(i, x, y) EXPAND_4_BRANCHES(i, x, y) EXPAND_4_BRANCHES(i + 4, x, y) +#define EXPAND_16_BRANCHES(i, x, y) EXPAND_8_BRANCHES(i, x, y) EXPAND_8_BRANCHES(i + 8, x, y) +#define EXPAND_32_BRANCHES(i, x, y) EXPAND_16_BRANCHES(i, x, y) EXPAND_16_BRANCHES(i + 16, x, y) +#define EXPAND_64_BRANCHES(i, x, y) EXPAND_32_BRANCHES(i, x, y) EXPAND_32_BRANCHES(i + 32, x, y) +#define EXPAND_128_BRANCHES(i, x, y) EXPAND_64_BRANCHES(i, x, y) EXPAND_64_BRANCHES(i + 64, x, y) +#define EXPAND_256_BRANCHES(i, x, y) EXPAND_128_BRANCHES(i, x, y) EXPAND_128_BRANCHES(i + 128, x, y) +#define EXPAND_512_BRANCHES(i, x, y) EXPAND_256_BRANCHES(i, x, y) EXPAND_256_BRANCHES(i + 256, x, y) +#define EXPAND_1024_BRANCHES(i, x, y) EXPAND_512_BRANCHES(i, x, y) EXPAND_512_BRANCHES(i + 512, x, y) +#define EXPAND_2048_BRANCHES(i, x, y) EXPAND_1024_BRANCHES(i, x, y) EXPAND_1024_BRANCHES(i + 1024, x, y) +#define EXPAND_4096_BRANCHES(i, x, y) EXPAND_2048_BRANCHES(i, x, y) EXPAND_2048_BRANCHES(i + 2048, x, y) + +unsigned cfg_long_chain_multiple_exit(unsigned x) { + unsigned y = 0; +#define BRANCH(i, x, y) if (((x % 13171) + ++y) < i) { int var = x / 13171 + y; return var; } + EXPAND_4096_BRANCHES(1, x, y); +#undef BRANCH + return 42; +} diff --git a/INPUTS/cfg-long-chain3.c b/INPUTS/cfg-long-chain3.c new file mode 100644 index 000000000000..cca4bdcf1ac9 --- /dev/null +++ b/INPUTS/cfg-long-chain3.c @@ -0,0 +1,21 @@ +#define EXPAND_2_BRANCHES(i, x, y) BRANCH(i, x, y); BRANCH(i + 1, x, y); +#define EXPAND_4_BRANCHES(i, x, y) EXPAND_2_BRANCHES(i, x, y) EXPAND_2_BRANCHES(i + 2, x, y) +#define EXPAND_8_BRANCHES(i, x, y) EXPAND_4_BRANCHES(i, x, y) EXPAND_4_BRANCHES(i + 4, x, y) +#define EXPAND_16_BRANCHES(i, x, y) EXPAND_8_BRANCHES(i, x, y) EXPAND_8_BRANCHES(i + 8, x, y) +#define EXPAND_32_BRANCHES(i, x, y) EXPAND_16_BRANCHES(i, x, y) EXPAND_16_BRANCHES(i + 16, x, y) +#define EXPAND_64_BRANCHES(i, x, y) EXPAND_32_BRANCHES(i, x, y) EXPAND_32_BRANCHES(i + 32, x, y) +#define EXPAND_128_BRANCHES(i, x, y) EXPAND_64_BRANCHES(i, x, y) EXPAND_64_BRANCHES(i + 64, x, y) +#define EXPAND_256_BRANCHES(i, x, y) EXPAND_128_BRANCHES(i, x, y) EXPAND_128_BRANCHES(i + 128, x, y) +#define EXPAND_512_BRANCHES(i, x, y) EXPAND_256_BRANCHES(i, x, y) EXPAND_256_BRANCHES(i + 256, x, y) +#define EXPAND_1024_BRANCHES(i, x, y) EXPAND_512_BRANCHES(i, x, y) EXPAND_512_BRANCHES(i + 512, x, y) +#define EXPAND_2048_BRANCHES(i, x, y) EXPAND_1024_BRANCHES(i, x, y) EXPAND_1024_BRANCHES(i + 1024, x, y) +#define EXPAND_4096_BRANCHES(i, x, y) EXPAND_2048_BRANCHES(i, x, y) EXPAND_2048_BRANCHES(i + 2048, x, y) + +unsigned cfg_long_chain_many_preds(unsigned x) { + unsigned y = 0; +#define BRANCH(i, x, y) if ((x % 13171) < i) { int var = x / 13171; y ^= var; } else + EXPAND_4096_BRANCHES(1, x, y); +#undef BRANCH + int var = x / 13171; y^= var; + return y; +} diff --git a/INPUTS/cfg-nested-switches.c b/INPUTS/cfg-nested-switches.c new file mode 100644 index 000000000000..3db10b443d21 --- /dev/null +++ b/INPUTS/cfg-nested-switches.c @@ -0,0 +1,36 @@ +#define EXPAND_2_INNER_CASES(i, x, y) INNER_CASE(i, x, y); INNER_CASE(i + 1, x, y); +#define EXPAND_4_INNER_CASES(i, x, y) EXPAND_2_INNER_CASES(i, x, y) EXPAND_2_INNER_CASES(i + 2, x, y) +#define EXPAND_8_INNER_CASES(i, x, y) EXPAND_4_INNER_CASES(i, x, y) EXPAND_4_INNER_CASES(i + 4, x, y) +#define EXPAND_16_INNER_CASES(i, x, y) EXPAND_8_INNER_CASES(i, x, y) EXPAND_8_INNER_CASES(i + 8, x, y) +#define EXPAND_32_INNER_CASES(i, x, y) EXPAND_16_INNER_CASES(i, x, y) EXPAND_16_INNER_CASES(i + 16, x, y) +#define EXPAND_64_INNER_CASES(i, x, y) EXPAND_32_INNER_CASES(i, x, y) EXPAND_32_INNER_CASES(i + 32, x, y) + +#define EXPAND_2_OUTER_CASES(i, x, y) OUTER_CASE(i, x, y); OUTER_CASE(i + 1, x, y); +#define EXPAND_4_OUTER_CASES(i, x, y) EXPAND_2_OUTER_CASES(i, x, y) EXPAND_2_OUTER_CASES(i + 2, x, y) +#define EXPAND_8_OUTER_CASES(i, x, y) EXPAND_4_OUTER_CASES(i, x, y) EXPAND_4_OUTER_CASES(i + 4, x, y) +#define EXPAND_16_OUTER_CASES(i, x, y) EXPAND_8_OUTER_CASES(i, x, y) EXPAND_8_OUTER_CASES(i + 8, x, y) +#define EXPAND_32_OUTER_CASES(i, x, y) EXPAND_16_OUTER_CASES(i, x, y) EXPAND_16_OUTER_CASES(i + 16, x, y) +#define EXPAND_64_OUTER_CASES(i, x, y) EXPAND_32_OUTER_CASES(i, x, y) EXPAND_32_OUTER_CASES(i + 32, x, y) + +// Rather than a single monstrous fan-out, this fans out in smaller increments, +// but to a similar size. +unsigned cfg_nested_switch(int x) { + unsigned y = 0; + while (x > 0) { + switch (x) { +#define INNER_CASE(i, x, y) \ + case i: { int case_var = 3*x + i; y += case_var - 1; break; } +#define OUTER_CASE(i, x, y) \ + case i: { \ + int case_var = y >> 8; \ + switch (case_var) { \ + EXPAND_64_INNER_CASES(0, x, y); \ + } \ + break; \ + } +EXPAND_64_OUTER_CASES(0, x, y); + } + --x; + } + return y; +} diff --git a/LICENSE.TXT b/LICENSE.TXT index a378a5f7fd51..91895eba029d 100644 --- a/LICENSE.TXT +++ b/LICENSE.TXT @@ -4,7 +4,7 @@ LLVM Release License University of Illinois/NCSA Open Source License -Copyright (c) 2007-2010 University of Illinois at Urbana-Champaign. +Copyright (c) 2007-2011 University of Illinois at Urbana-Champaign. All rights reserved. Developed by: diff --git a/bindings/python/clang/cindex.py b/bindings/python/clang/cindex.py index 08ad80234e09..8cadcaa7ad06 100644 --- a/bindings/python/clang/cindex.py +++ b/bindings/python/clang/cindex.py @@ -321,6 +321,10 @@ class CursorKind(object): """Test if this is a statement kind.""" return CursorKind_is_stmt(self) + def is_attribute(self): + """Test if this is an attribute kind.""" + return CursorKind_is_attribute(self) + def is_invalid(self): """Test if this is an invalid kind.""" return CursorKind_is_inv(self) @@ -978,8 +982,9 @@ class TranslationUnit(ClangObject): headers. """ def visitor(fobj, lptr, depth, includes): - loc = lptr.contents - includes.append(FileInclusion(loc.file, File(fobj), loc, depth)) + if depth > 0: + loc = lptr.contents + includes.append(FileInclusion(loc.file, File(fobj), loc, depth)) # Automatically adapt CIndex/ctype pointers to python objects includes = [] @@ -1074,7 +1079,7 @@ class File(ClangObject): @property def name(self): """Return the complete file and path name of the file.""" - return File_name(self) + return _CXString_getCString(File_name(self)) @property def time(self): @@ -1147,6 +1152,10 @@ CursorKind_is_stmt = lib.clang_isStatement CursorKind_is_stmt.argtypes = [CursorKind] CursorKind_is_stmt.restype = bool +CursorKind_is_attribute = lib.clang_isAttribute +CursorKind_is_attribute.argtypes = [CursorKind] +CursorKind_is_attribute.restype = bool + CursorKind_is_inv = lib.clang_isInvalid CursorKind_is_inv.argtypes = [CursorKind] CursorKind_is_inv.restype = bool @@ -1183,6 +1192,11 @@ Cursor_spelling.argtypes = [Cursor] Cursor_spelling.restype = _CXString Cursor_spelling.errcheck = _CXString.from_result +Cursor_displayname = lib.clang_getCursorDisplayName +Cursor_displayname.argtypes = [Cursor] +Cursor_displayname.restype = _CXString +Cursor_displayname.errcheck = _CXString.from_result + Cursor_loc = lib.clang_getCursorLocation Cursor_loc.argtypes = [Cursor] Cursor_loc.restype = SourceLocation @@ -1253,7 +1267,7 @@ TranslationUnit_includes.argtypes = [TranslationUnit, # File Functions File_name = lib.clang_getFileName File_name.argtypes = [File] -File_name.restype = c_char_p +File_name.restype = _CXString File_time = lib.clang_getFileTime File_time.argtypes = [File] diff --git a/bindings/python/tests/cindex/test_cursor_kind.py b/bindings/python/tests/cindex/test_cursor_kind.py index bdfa31855835..d7a1cfad8f94 100644 --- a/bindings/python/tests/cindex/test_cursor_kind.py +++ b/bindings/python/tests/cindex/test_cursor_kind.py @@ -18,10 +18,14 @@ def test_kind_groups(): for k in CursorKind.get_all_kinds(): group = [n for n in ('is_declaration', 'is_reference', 'is_expression', - 'is_statement', 'is_invalid') + 'is_statement', 'is_invalid', 'is_attribute') if getattr(k, n)()] - if k == CursorKind.TRANSLATION_UNIT: + if k in ( CursorKind.TRANSLATION_UNIT, + CursorKind.MACRO_DEFINITION, + CursorKind.MACRO_INSTANTIATION, + CursorKind.INCLUSION_DIRECTIVE, + CursorKind.PREPROCESSING_DIRECTIVE): assert len(group) == 0 else: assert len(group) == 1 diff --git a/bindings/python/tests/cindex/test_translation_unit.py b/bindings/python/tests/cindex/test_translation_unit.py index f130db6aeb06..2e65d9518da0 100644 --- a/bindings/python/tests/cindex/test_translation_unit.py +++ b/bindings/python/tests/cindex/test_translation_unit.py @@ -58,24 +58,27 @@ def test_unsaved_files_2(): spellings = [c.spelling for c in tu.cursor.get_children()] assert spellings[-1] == 'x' +def normpaths_equal(path1, path2): + """ Compares two paths for equality after normalizing them with + os.path.normpath + """ + return os.path.normpath(path1) == os.path.normpath(path2) def test_includes(): def eq(expected, actual): if not actual.is_input_file: - return expected[0] == actual.source.name and \ - expected[1] == actual.include.name + return normpaths_equal(expected[0], actual.source.name) and \ + normpaths_equal(expected[1], actual.include.name) else: - return expected[1] == actual.include.name + return normpaths_equal(expected[1], actual.include.name) src = os.path.join(kInputsDir, 'include.cpp') h1 = os.path.join(kInputsDir, "header1.h") h2 = os.path.join(kInputsDir, "header2.h") h3 = os.path.join(kInputsDir, "header3.h") - inc = [(None, src), (src, h1), (h1, h3), (src, h2), (h2, h3)] + inc = [(src, h1), (h1, h3), (src, h2), (h2, h3)] index = Index.create() tu = index.parse(src) for i in zip(inc, tu.get_includes()): assert eq(i[0], i[1]) - - diff --git a/clang.xcodeproj/project.pbxproj b/clang.xcodeproj/project.pbxproj index 1612d122f516..832e07ab44f2 100644 --- a/clang.xcodeproj/project.pbxproj +++ b/clang.xcodeproj/project.pbxproj @@ -373,6 +373,12 @@ 90FD6D90103C3D80005F5B73 /* TypeXML.def */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = TypeXML.def; path = clang/Frontend/TypeXML.def; sourceTree = "<group>"; }; 90FD6D91103C3D80005F5B73 /* Utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Utils.h; path = clang/Frontend/Utils.h; sourceTree = "<group>"; }; 90FD6DB5103D977E005F5B73 /* index-test.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "index-test.cpp"; path = "tools/index-test/index-test.cpp"; sourceTree = "<group>"; }; + BB20603B131EDDBF003C3343 /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = "<group>"; }; + BB20603C131EDDBF003C3343 /* Makefile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = "<group>"; }; + BB206041131EDDDA003C3343 /* ARRMT.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ARRMT.h; sourceTree = "<group>"; }; + BB206043131EDE03003C3343 /* arrmt-test.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "arrmt-test.cpp"; sourceTree = "<group>"; }; + BB206044131EDE03003C3343 /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = "<group>"; }; + BB206045131EDE03003C3343 /* Makefile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = "<group>"; }; BB5C372812A5057500259F53 /* DumpXML.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DumpXML.cpp; path = /Volumes/Data/llvm/tools/clang/lib/AST/DumpXML.cpp; sourceTree = "<absolute>"; }; BBA5AB141309C2FA000B38F1 /* AdjustedReturnValueChecker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AdjustedReturnValueChecker.cpp; sourceTree = "<group>"; }; BBA5AB151309C2FA000B38F1 /* AnalyzerStatsChecker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AnalyzerStatsChecker.cpp; sourceTree = "<group>"; }; @@ -561,7 +567,6 @@ BF9FEE321225E898003A8B71 /* ItaniumCXXABI.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ItaniumCXXABI.cpp; path = lib/CodeGen/ItaniumCXXABI.cpp; sourceTree = "<group>"; }; BF9FEE341225E8B1003A8B71 /* MicrosoftCXXABI.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MicrosoftCXXABI.cpp; path = lib/CodeGen/MicrosoftCXXABI.cpp; sourceTree = "<group>"; }; BF9FEE361225E8CF003A8B71 /* README.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = README.txt; path = lib/CodeGen/README.txt; sourceTree = "<group>"; }; - BF9FEE371225E925003A8B71 /* BoostConAction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BoostConAction.cpp; path = lib/Frontend/BoostConAction.cpp; sourceTree = "<group>"; }; BF9FEE451225EA24003A8B71 /* DelayedDiagnostic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DelayedDiagnostic.h; path = clang/Sema/DelayedDiagnostic.h; sourceTree = "<group>"; }; BF9FEE511226FE9F003A8B71 /* ParseAST.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ParseAST.cpp; path = lib/Parse/ParseAST.cpp; sourceTree = "<group>"; }; BF9FEE531226FEC1003A8B71 /* RAIIObjectsForParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RAIIObjectsForParser.h; path = lib/Parse/RAIIObjectsForParser.h; sourceTree = "<group>"; }; @@ -777,6 +782,7 @@ 08FB7795FE84155DC02AAC07 /* Libraries */ = { isa = PBXGroup; children = ( + BB20603A131EDDBF003C3343 /* ARRMigrate */, BBA5AB121309C2FA000B38F1 /* StaticAnalyzer */, 57EB5660121B034300ECA335 /* Serialization */, BFE2F67911DA95590007EDC0 /* Rewrite */, @@ -899,7 +905,6 @@ 352246E00F5C6BC000D0D279 /* Frontend */ = { isa = PBXGroup; children = ( - BF9FEE371225E925003A8B71 /* BoostConAction.cpp */, 1AFDD8701161085D00AE030A /* ASTMerge.cpp */, 9012911C1048068D0083456D /* ASTUnit.cpp */, 1A2A54A50FD1DD1C00F4CE45 /* ASTConsumers.cpp */, @@ -1105,6 +1110,38 @@ name = "index-test"; sourceTree = "<group>"; }; + BB20603A131EDDBF003C3343 /* ARRMigrate */ = { + isa = PBXGroup; + children = ( + BB20603B131EDDBF003C3343 /* CMakeLists.txt */, + BB20603C131EDDBF003C3343 /* Makefile */, + BDDF60E91337BF40009F1764 /* Transforms.cpp */, + ); + name = ARRMigrate; + path = lib/ARRMigrate; + sourceTree = "<group>"; + }; + BB206040131EDDDA003C3343 /* ARRMigrate */ = { + isa = PBXGroup; + children = ( + BB206041131EDDDA003C3343 /* ARRMT.h */, + ); + name = ARRMigrate; + path = clang/ARRMigrate; + sourceTree = "<group>"; + }; + BB206042131EDE03003C3343 /* arrmt-test */ = { + isa = PBXGroup; + children = ( + BD8A47E7133D32660066FE40 /* ARRMT.cpp */, + BB206043131EDE03003C3343 /* arrmt-test.cpp */, + BB206044131EDE03003C3343 /* CMakeLists.txt */, + BB206045131EDE03003C3343 /* Makefile */, + ); + name = "arrmt-test"; + path = "tools/arrmt-test"; + sourceTree = "<group>"; + }; BBA5AB121309C2FA000B38F1 /* StaticAnalyzer */ = { isa = PBXGroup; children = ( @@ -1575,6 +1612,7 @@ DED7D72E0A524295003AD0FB /* include */ = { isa = PBXGroup; children = ( + BB206040131EDDDA003C3343 /* ARRMigrate */, DED7D7300A524295003AD0FB /* Basic */, DED7D7390A524295003AD0FB /* Lex */, DE1F21F20A7D84E800FBF588 /* Parse */, @@ -1724,6 +1762,7 @@ DEDFE61F0F7B3AE10035BD10 /* Tools */ = { isa = PBXGroup; children = ( + BB206042131EDE03003C3343 /* arrmt-test */, 90F9EFA8104ABDC400D09A15 /* c-index-test */, 9012911E104812DA0083456D /* CIndex */, 90FD6DB4103D9763005F5B73 /* index-test */, diff --git a/docs/AutomaticReferenceCounting.html b/docs/AutomaticReferenceCounting.html new file mode 100644 index 000000000000..5090fa2b7952 --- /dev/null +++ b/docs/AutomaticReferenceCounting.html @@ -0,0 +1,1857 @@ +<html> +<head> +<title>Objective-C Automatic Reference Counting (ARC)</title> +<link type="text/css" rel="stylesheet" href="../menu.css" /> +<link type="text/css" rel="stylesheet" href="../content.css" /> +<style type="text/css"> +/* Collapse the items in the ToC to the left. */ +div#toc ul { + padding-left: 0 +} + +/* Rationales appear in italic. */ +div.rationale { + font-style: italic +} + +div.rationale em { + font-style: normal +} + +div h1 { font-size: 2em; margin: .67em 0 } +div div h1 { font-size: 1.5em; margin: .75em 0 } +div div div h1 { font-size: 1.17em; margin: .83em 0 } +div div div div h1 { margin: 1.12em 0 } + +span.term { font-style: italic; font-weight: bold } +</style> + +<script lang="javascript"> +/// A little script to recursively build a table of contents. +function buildTOC(div, toc, ancestry) { + var children = div.childNodes; + var len = children.length; + + var childNumber = 0; + + var list = null; + for (var i = 0; i < len; ++i) { + var child = children[i]; + if (child.nodeName != "DIV") continue; + if (child.getAttribute("class") == "rationale") continue; + if (child.id == "toc") continue; + + // Okay, we're actually going to build a list node. + if (list === null) list = document.createElement("ul"); + + var childAncestry = ancestry + ++childNumber + "."; + + var headerNode = child.childNodes[1]; + var title = headerNode.innerHTML; + headerNode.insertBefore(document.createTextNode(childAncestry + " "), + headerNode.firstChild); + + var item = document.createElement("li"); + item.appendChild(document.createTextNode(childAncestry + " ")); + + var anchor = document.createElement("a"); + anchor.href = "#" + child.id; + anchor.innerHTML = title; + item.appendChild(anchor); + + buildTOC(child, item, childAncestry); + + list.appendChild(item); + } + if (list) toc.appendChild(list); +} + +function onLoad() { + var toc = document.getElementById("toc"); + var content = document.getElementById("content"); + buildTOC(content, toc, ""); +} +window.onload = onLoad; + +</script> +</head> +<body> + +<!--#include virtual="../menu.html.incl"--> + +<div id="content"> +<h1>Automatic Reference Counting</h1> + +<div id="toc"> +</div> + +<div id="meta"> +<h1>About this document</h1> + +<div id="meta.purpose"> +<h1>Purpose</h1> + +<p>The first and primary purpose of this document is to serve as a +complete technical specification of Automatic Reference Counting. +Given a core Objective-C compiler and runtime, it should be possible +to write a compiler and runtime which implements these new +semantics.</p> + +<p>The secondary purpose is to act as a rationale for why ARC was +designed in this way. This should remain tightly focused on the +technical design and should not stray into marketing speculation.</p> + +</div> <!-- meta.purpose --> + +<div id="meta.background"> +<h1>Background</h1> + +<p>This document assumes a basic familiarity with C.</p> + +<p><span class="term">Blocks</span> are a C language extension for +creating anonymous functions. Users interact with and transfer block +objects using <span class="term">block pointers</span>, which are +represented like a normal pointer. A block may capture values from +local variables; when this occurs, memory must be dynamically +allocated. The initial allocation is done on the stack, but the +runtime provides a <tt>Block_copy</tt> function which, given a block +pointer, either copies the underlying block object to the heap, +setting its reference count to 1 and returning the new block pointer, +or (if the block object is already on the heap) increases its +reference count by 1. The paired function is <tt>Block_release</tt>, +which decreases the reference count by 1 and destroys the object if +the count reaches zero and is on the heap.</p> + +<p>Objective-C is a set of language extensions, significant enough to +be considered a different language. It is a strict superset of C. +The extensions can also be imposed on C++, producing a language called +Objective-C++. The primary feature is a single-inheritance object +system; we briefly describe the modern dialect.</p> + +<p>Objective-C defines a new type kind, collectively called +the <span class="term">object pointer types</span>. This kind has two +notable builtin members, <tt>id</tt> and <tt>Class</tt>; <tt>id</tt> +is the final supertype of all object pointers. The validity of +conversions between object pointer types is not checked at runtime. +Users may define <span class="term">classes</span>; each class is a +type, and the pointer to that type is an object pointer type. A class +may have a superclass; its pointer type is a subtype of its +superclass's pointer type. A class has a set +of <span class="term">ivars</span>, fields which appear on all +instances of that class. For every class <i>T</i> there's an +associated metaclass; it has no fields, its superclass is the +metaclass of <i>T</i>'s superclass, and its metaclass is a global +class. Every class has a global object whose class is the +class's metaclass; metaclasses have no associated type, so pointers to +this object have type <tt>Class</tt>.</p> + +<p>A class declaration (<tt>@interface</tt>) declares a set +of <span class="term">methods</span>. A method has a return type, a +list of argument types, and a <span class="term">selector</span>: a +name like <tt>foo:bar:baz:</tt>, where the number of colons +corresponds to the number of formal arguments. A method may be an +instance method, in which case it can be invoked on objects of the +class, or a class method, in which case it can be invoked on objects +of the metaclass. A method may be invoked by providing an object +(called the <span class="term">receiver</span>) and a list of formal +arguments interspersed with the selector, like so:</p> + +<pre>[receiver foo: fooArg bar: barArg baz: bazArg]</pre> + +<p>This looks in the dynamic class of the receiver for a method with +this name, then in that class's superclass, etc., until it finds +something it can execute. The receiver <q>expression</q> may also be +the name of a class, in which case the actual receiver is the class +object for that class, or (within method definitions) it may +be <tt>super</tt>, in which case the lookup algorithm starts with the +static superclass instead of the dynamic class. The actual methods +dynamically found in a class are not those declared in the +<tt>@interface</tt>, but those defined in a separate +<tt>@implementation</tt> declaration; however, when compiling a +call, typechecking is done based on the methods declared in the +<tt>@interface</tt>.</p> + +<p>Method declarations may also be grouped into +<span class="term">protocols</span>, which are not inherently +associated with any class, but which classes may claim to follow. +Object pointer types may be qualified with additional protocols that +the object is known to support.</p> + +<p><span class="term">Class extensions</span> are collections of ivars +and methods, designed to allow a class's <tt>@interface</tt> to be +split across multiple files; however, there is still a primary +implementation file which must see the <tt>@interface</tt>s of all +class extensions. +<span class="term">Categories</span> allow methods (but not ivars) to +be declared <i>post hoc</i> on an arbitrary class; the methods in the +category's <tt>@implementation</tt> will be dynamically added to that +class's method tables which the category is loaded at runtime, +replacing those methods in case of a collision.</p> + +<p>In the standard environment, objects are allocated on the heap, and +their lifetime is manually managed using a reference count. This is +done using two instance methods which all classes are expected to +implement: <tt>retain</tt> increases the object's reference count by +1, whereas <tt>release</tt> decreases it by 1 and calls the instance +method <tt>dealloc</tt> if the count reaches 0. To simplify certain +operations, there is also an <span class="term">autorelease +pool</span>, a thread-local list of objects to call <tt>release</tt> +on later; an object can be added to this pool by +calling <tt>autorelease</tt> on it.</p> + +<p>Block pointers may be converted to type <tt>id</tt>; block objects +are laid out in a way that makes them compatible with Objective-C +objects. There is a builtin class that all block objects are +considered to be objects of; this class implements <tt>retain</tt> by +adjusting the reference count, not by calling <tt>Block_copy</tt>.</p> + +</div> <!-- meta.background --> + +</div> <!-- meta --> + +<div id="general"> +<h1>General</h1> + +<p>Automatic Reference Counting implements automatic memory management +for Objective-C objects and blocks, freeing the programmer from the +need explicitly insert retains and releases. It does not provide a +cycle collector; users must explicitly manage lifetime instead.</p> + +<p>ARC may be explicitly enabled with the compiler +flag <tt>-fobjc-arc</tt>. It may also be explicitly disabled with the +compiler flag <tt>-fno-objc-arc</tt>. The last of these two flags +appearing on the compile line <q>wins</q>.</p> + +<p>If ARC is enabled, <tt>__has_feature(objc_arc)</tt> will expand to +1 in the preprocessor. For more information about <tt>__has_feature</tt>, +see the <a href="LanguageExtensions.html#__has_feature_extension">language +extensions</a> document.</p> + +</div> + +<div id="objects"> +<h1>Retainable object pointers</h1> + +<p>This section describes retainable object pointers, their basic +operations, and the restrictions imposed on their use under ARC. Note +in particular that it covers the rules for pointer <em>values</em> +(patterns of bits indicating the location of a pointed-to object), not +pointer +<em>objects</em> (locations in memory which store pointer values). +The rules for objects are covered in the next section.</p> + +<p>A <span class="term">retainable object pointer</span> +(or <q>retainable pointer</q>) is a value of +a <span class="term">retainable object pointer type</span> +(<q>retainable type</q>). There are three kinds of retainable object +pointer types:</p> +<ul> +<li>block pointers (formed by applying the caret (<tt>^</tt>) +declarator sigil to a function type)</li> +<li>Objective-C object pointers (<tt>id</tt>, <tt>Class</tt>, <tt>NSFoo*</tt>, etc.)</li> +<li>typedefs marked with <tt>__attribute__((NSObject))</tt></li> +</ul> + +<p>Other pointer types, such as <tt>int*</tt> and <tt>CFStringRef</tt>, +are not subject to ARC's semantics and restrictions.</p> + +<div class="rationale"> + +<p>Rationale: We are not at liberty to require +all code to be recompiled with ARC; therefore, ARC must interoperate +with Objective-C code which manages retains and releases manually. In +general, there are three requirements in order for a +compiler-supported reference-count system to provide reliable +interoperation:</p> + +<ul> +<li>The type system must reliably identify which objects are to be +managed. An <tt>int*</tt> might be a pointer to a <tt>malloc</tt>'ed +array, or it might be a interior pointer to such an array, or it might +point to some field or local variable. In contrast, values of the +retainable object pointer types are never interior.</li> +<li>The type system must reliably indicate how to +manage objects of a type. This usually means that the type must imply +a procedure for incrementing and decrementing retain counts. +Supporting single-ownership objects requires a lot more explicit +mediation in the language.</li> +<li>There must be reliable conventions for whether and +when <q>ownership</q> is passed between caller and callee, for both +arguments and return values. Objective-C methods follow such a +convention very reliably, at least for system libraries on Mac OS X, +and functions always pass objects at +0. The C-based APIs for Core +Foundation objects, on the other hand, have much more varied transfer +semantics.</li> +</ul> +</div> <!-- rationale --> + +<p>The use of <tt>__attribute__((NSObject))</tt> typedefs is not +recommended. If it's absolutely necessary to use this attribute, be +very explicit about using the typedef, and do not assume that it will +be preserved by language features like <tt>__typeof</tt> and C++ +template argument substitution.</p> + +<div class="rationale"><p>Rationale: any compiler operation which +incidentally strips type <q>sugar</q> from a type will yield a type +without the attribute, which may result in unexpected +behavior.</p></div> + +<div id="objects.retains"> +<h1>Retain count semantics</h1> + +<p>A retainable object pointer is either a <span class="term">null +pointer</span> or a pointer to a valid object. Furthermore, if it has +block pointer type and is not <tt>null</tt> then it must actually be a +pointer to a block object, and if it has <tt>Class</tt> type (possibly +protocol-qualified) then it must actually be a pointer to a class +object. Otherwise ARC does not enforce the Objective-C type system as +long as the implementing methods follow the signature of the static +type. It is undefined behavior if ARC is exposed to an invalid +pointer.</p> + +<p>For ARC's purposes, a valid object is one with <q>well-behaved</q> +retaining operations. Specifically, the object must be laid out such +that the Objective-C message send machinery can successfully send it +the following messages:</p> + +<ul> +<li><tt>retain</tt>, taking no arguments and returning a pointer to +the object.</li> +<li><tt>release</tt>, taking no arguments and returning <tt>void</tt>.</li> +<li><tt>autorelease</tt>, taking no arguments and returning a pointer +to the object.</li> +</ul> + +<p>The behavior of these methods is constrained in the following ways. +The term <span class="term">high-level semantics</span> is an +intentionally vague term; the intent is that programmers must +implement these methods in a way such that the compiler, modifying +code in ways it deems safe according to these constraints, will not +violate their requirements. For example, if the user puts logging +statements in <tt>retain</tt>, they should not be surprised if those +statements are executed more or less often depending on optimization +settings. These constraints are not exhaustive of the optimization +opportunities: values held in local variables are subject to +additional restrictions, described later in this document.</p> + +<p>It is undefined behavior if a computation history featuring a send +of <tt>retain</tt> followed by a send of <tt>release</tt> to the same +object, with no intervening <tt>release</tt> on that object, is not +equivalent under the high-level semantics to a computation +history in which these sends are removed. Note that this implies that +these methods may not raise exceptions.</p> + +<p>It is undefined behavior if a computation history features any use +whatsoever of an object following the completion of a send +of <tt>release</tt> that is not preceded by a send of <tt>retain</tt> +to the same object.</p> + +<p>The behavior of <tt>autorelease</tt> must be equivalent to sending +<tt>release</tt> when one of the autorelease pools currently in scope +is popped. It may not throw an exception.</p> + +<p>When the semantics call for performing one of these operations on a +retainable object pointer, if that pointer is <tt>null</tt> then the +effect is a no-op.</p> + +<p>All of the semantics described in this document are subject to +additional <a href="#optimization">optimization rules</a> which permit +the removal or optimization of operations based on local knowledge of +data flow. The semantics describe the high-level behaviors that the +compiler implements, not an exact sequence of operations that a +program will be compiled into.</p> + +</div> <!-- objects.retains --> + +<div id="objects.operands"> +<h1>Retainable object pointers as operands and arguments</h1> + +<p>In general, ARC does not perform retain or release operations when +simply using a retainable object pointer as an operand within an +expression. This includes:</p> +<ul> +<li>loading a retainable pointer from an object with non-weak +<a href="#ownership">ownership</a>,</li> +<li>passing a retainable pointer as an argument to a function or +method, and</li> +<li>receiving a retainable pointer as the result of a function or +method call.</li> +</ul> + +<div class="rationale"><p>Rationale: while this might seem +uncontroversial, it is actually unsafe when multiple expressions are +evaluated in <q>parallel</q>, as with binary operators and calls, +because (for example) one expression might load from an object while +another writes to it. However, C and C++ already call this undefined +behavior because the evaluations are unsequenced, and ARC simply +exploits that here to avoid needing to retain arguments across a large +number of calls.</p></div> + +<p>The remainder of this section describes exceptions to these rules, +how those exceptions are detected, and what those exceptions imply +semantically.</p> + +<div id="objects.operands.consumed"> +<h1>Consumed parameters</h1> + +<p>A function or method parameter of retainable object pointer type +may be marked as <span class="term">consumed</span>, signifying that +the callee expects to take ownership of a +1 retain count. This is +done by adding the <tt>ns_consumed</tt> attribute to the parameter +declaration, like so:</p> + +<pre>void foo(__attribute((ns_consumed)) id x); +- (void) foo: (id) __attribute((ns_consumed)) x;</pre> + +<p>This attribute is part of the type of the function or method, not +the type of the parameter. It controls only how the argument is +passed and received.</p> + +<p>When passing such an argument, ARC retains the argument prior to +making the call.</p> + +<p>When receiving such an argument, ARC releases the argument at the +end of the function, subject to the usual optimizations for local +values.</p> + +<div class="rationale"><p>Rationale: this formalizes direct transfers +of ownership from a caller to a callee. The most common scenario here +is passing the <tt>self</tt> parameter to <tt>init</tt>, but it is +useful to generalize. Typically, local optimization will remove any +extra retains and releases: on the caller side the retain will be +merged with a +1 source, and on the callee side the release will be +rolled into the initialization of the parameter.</p></div> + +<p>The implicit <tt>self</tt> parameter of a method may be marked as +consumed by adding <tt>__attribute__((ns_consumes_self))</tt> to the +method declaration. Methods in the <tt>init</tt> +<a href="#family">family</a> are treated as if they were implicitly +marked with this attribute.</p> + +<p>It is undefined behavior if an Objective-C message send to a method +with <tt>ns_consumed</tt> parameters (other than self) is made with a +null receiver. It is undefined behavior if the method to which an +Objective-C message send statically resolves to has a different set +of <tt>ns_consumed</tt> parameters than the method it dynamically +resolves to. It is undefined behavior if a block or function call is +made through a static type with a different set of <tt>ns_consumed</tt> +parameters than the implementation of the called block or function.</p> + +<div class="rationale"><p>Rationale: consumed parameters with null +receiver are a guaranteed leak. Mismatches with consumed parameters +will cause over-retains or over-releases, depending on the direction. +The rule about function calls is really just an application of the +existing C/C++ rule about calling functions through an incompatible +function type, but it's useful to state it explicitly.</p></div> + +</div> + +<div id="objects.operands.retained_returns"> +<h1>Retained return values</h1> + +<p>A function or method which returns a retainable object pointer type +may be marked as returning a retained value, signifying that the +caller expects to take ownership of a +1 retain count. This is done +by adding the <tt>ns_returns_retained</tt> attribute to the function or +method declaration, like so:</p> + +<pre>id foo(void) __attribute((ns_returns_retained)); +- (id) foo __attribute((ns_returns_retained));</pre> + +<p>This attribute is part of the type of the function or method.</p> + +<p>When returning from such a function or method, ARC retains the +value at the point of evaluation of the return statement, before +leaving all local scopes.</p> + +<p>When receiving a return result from such a function or method, ARC +releases the value at the end of the full-expression it is contained +within, subject to the usual optimizations for local values.</p> + +<div class="rationale"><p>Rationale: this formalizes direct transfers of +ownership from a callee to a caller. The most common scenario this +models is the retained return from <tt>init</tt>, <tt>alloc</tt>, +<tt>new</tt>, and <tt>copy</tt> methods, but there are other cases in +the frameworks. After optimization there are typically no extra +retains and releases required.</p></div> + +<p>Methods in +the <tt>alloc</tt>, <tt>copy</tt>, <tt>init</tt>, <tt>mutableCopy</tt>, +and <tt>new</tt> <a href="#family">families</a> are implicitly marked +<tt>__attribute__((ns_returns_retained))</tt>. This may be suppressed +by explicitly marking the +method <tt>__attribute__((ns_returns_not_retained))</tt>.</p> +</div> + +<p>It is undefined behavior if the method to which an Objective-C +message send statically resolves has different retain semantics on its +result from the method it dynamically resolves to. It is undefined +behavior if a block or function call is made through a static type +with different retain semantics on its result from the implementation +of the called block or function.</p> + +<div class="rationale"><p>Rationale: Mismatches with returned results +will cause over-retains or over-releases, depending on the direction. +Again, the rule about function calls is really just an application of +the existing C/C++ rule about calling functions through an +incompatible function type.</p></div> + + +<div id="objects.operands.other-returns"> +<h1>Unretained return values</h1> + +<p>A method or function which returns a retainable object type but +does not return a retained value must ensure that the object is +still valid across the return boundary.</p> + +<p>When returning from such a function or method, ARC retains the +value at the point of evaluation of the return statement, then leaves +all local scopes, and then balances out the retain while ensuring that +the value lives across the call boundary. In the worst case, this may +involve an <tt>autorelease</tt>, but callers must not assume that the +value is actually in the autorelease pool.</p> + +<p>ARC performs no extra mandatory work on the caller side, although +it may elect to do something to shorten the lifetime of the returned +value.</p> + +<div class="rationale"><p>Rationale: it is common in non-ARC code to not +return an autoreleased value; therefore the convention does not force +either path. It is convenient to not be required to do unnecessary +retains and autoreleases; this permits optimizations such as eliding +retain/autoreleases when it can be shown that the original pointer +will still be valid at the point of return.</p></div> + +<p>A method or function may be marked +with <tt>__attribute__((ns_returns_autoreleased))</tt> to indicate +that it returns a pointer which is guaranteed to be valid at least as +long as the innermost autorelease pool. There are no additional +semantics enforced in the definition of such a method; it merely +enables optimizations in callers.</p> +</div> + +<div id="objects.operands.casts"> +<h1>Bridged casts</h1> + +<p>A <span class="term">bridged cast</span> is a C-style cast +annotated with one of three keywords:</p> + +<ul> +<li><tt>(__bridge T) op</tt> casts the operand to the destination +type <tt>T</tt>. If <tt>T</tt> is a retainable object pointer type, +then <tt>op</tt> must have a non-retainable pointer type. +If <tt>T</tt> is a non-retainable pointer type, then <tt>op</tt> must +have a retainable object pointer type. Otherwise the cast is +ill-formed. There is no transfer of ownership, and ARC inserts +no retain operations.</li> + +<li><tt>(__bridge_retained T) op</tt> casts the operand, which must +have retainable object pointer type, to the destination type, which +must be a non-retainable pointer type. ARC retains the value, subject +to the usual optimizations on local values, and the recipient is +responsible for balancing that +1.</li> + +<li><tt>(__bridge_transfer T) op</tt> casts the operand, which must +have non-retainable pointer type, to the destination type, which must +be a retainable object pointer type. ARC will release the value at +the end of the enclosing full-expression, subject to the usual +optimizations on local values.</li> +</ul> + +<p>These casts are required in order to transfer objects in and out of +ARC control; see the rationale in the section +on <a href="#objects.restrictions.conversion">conversion of retainable +object pointers</a>.</p> + +<p>Using a <tt>__bridge_retained</tt> or <tt>__bridge_transfer</tt> +cast purely to convince ARC to emit an unbalanced retain or release, +respectively, is poor form.</p> + +</div> + +</div> + +<div id="objects.restrictions"> +<h1>Restrictions</h1> + +<div id="objects.restrictions.conversion"> +<h1>Conversion of retainable object pointers</h1> + +<p>In general, a program which attempts to implicitly or explicitly +convert a value of retainable object pointer type to any +non-retainable type, or vice-versa, is ill-formed. For example, an +Objective-C object pointer shall not be converted to <tt>void*</tt>. +As an exception, cast to <tt>intptr_t</tt> is allowed becuase such +casts are not transferring ownership. The <a href="#objects.operands.casts">bridged +casts</a> may be used to perform these conversions where +necessary.</p> + +<div class="rationale"><p>Rationale: we cannot ensure the correct +management of the lifetime of objects if they may be freely passed +around as unmanaged types. The bridged casts are provided so that the +programmer may explicitly describe whether the cast transfers control +into or out of ARC.</p></div> +</div> + +<p>An unbridged cast to a retainable object pointer type of the return +value of a Objective-C message send which yields a non-retainable +pointer is treated as a <tt>__bridge_transfer</tt> cast +if:</p> + +<ul> +<li>the method has the <tt>cf_returns_retained</tt> attribute, or if +not that,</li> +<li>the method does not have the <tt>cf_returns_not_retained</tt> +attribute and</li> +<li>the method's <a href="#family">selector family</a> would imply +the <tt>ns_returns_retained</tt> attribute on a method which returned +a retainable object pointer type.</li> +</ul> + +<p>Otherwise the cast is treated as a <tt>__bridge</tt> cast.</p> + +</div> + +</div> + +<div id="ownership"> +<h1>Ownership qualification</h1> + +<p>This section describes the behavior of <em>objects</em> of +retainable object pointer type; that is, locations in memory which +store retainable object pointers.</p> + +<p>A type is a <span class="term">retainable object owner type</span> +if it is a retainable object pointer type or an array type whose +element type is a retainable object owner type.</p> + +<p>An <span class="term">ownership qualifier</span> is a type +qualifier which applies only to retainable object owner types. An array type is +ownership-qualified according to its element type, and adding an ownership +qualifier to an array type so qualifies its element type.</p> + +<p>A program is ill-formed if it attempts to apply an ownership qualifier +to a type which is already ownership-qualified, even if it is the same +qualifier. There is a single exception to this rule: an ownership qualifier +may be applied to a substituted template type parameter, which overrides the +ownership qualifier provided by the template argument.</p> + +<p>Except as described under +the <a href="#ownership.inference">inference rules</a>, a program is +ill-formed if it attempts to form a pointer or reference type to a +retainable object owner type which lacks an ownership qualifier.</p> + +<div class="rationale"><p>Rationale: these rules, together with the +inference rules, ensure that all objects and lvalues of retainable +object pointer type have an ownership qualifier. The ability to override an ownership qualifier during template substitution is required to counteract the <a href="#ownership.inference.template_arguments">inference of <tt>__strong</tt> for template type arguments</a>. </p></div> + +<p>There are four ownership qualifiers:</p> + +<ul> +<li><tt>__autoreleasing</tt></li> +<li><tt>__strong</tt></li> +<li><tt>__unsafe_unretained</tt></li> +<li><tt>__weak</tt></li> +</ul> + +<p>A type is <span class="term">nontrivially ownership-qualified</span> +if it is qualified with <tt>__autoreleasing</tt>, <tt>__strong</tt>, or +<tt>__weak</tt>.</p> + +<div id="ownership.spelling"> +<h1>Spelling</h1> + +<p>The names of the ownership qualifiers are reserved for the +implementation. A program may not assume that they are or are not +implemented with macros, or what those macros expand to.</p> + +<p>An ownership qualifier may be written anywhere that any other type +qualifier may be written.</p> + +<p>If an ownership qualifier appears in +the <i>declaration-specifiers</i>, the following rules apply:</p> + +<ul> +<li>if the type specifier is a retainable object owner type, the +qualifier applies to that type;</li> +<li>if the outermost non-array part of the declarator is a pointer or +block pointer, the qualifier applies to that type;</li> +<li>otherwise the program is ill-formed.</li> +</ul> + +<p>If an ownership qualifier appears on the declarator name, or on the +declared object, it is applied to outermost pointer or block-pointer +type.</p> + +<p>If an ownership qualifier appears anywhere else in a declarator, it +applies to the type there.</p> + +<div id="ownership.spelling.property"> +<h1>Property declarations</h1> + +<p>A property of retainable object pointer type may have ownership. +If the property's type is ownership-qualified, then the property has +that ownership. If the property has one of the following modifiers, +then the property has the corresponding ownership. A property is +ill-formed if it has conflicting sources of ownership, or if it has +redundant ownership modifiers, or if it has <tt>__autoreleasing</tt> +ownership.</p> + +<ul> +<li><tt>assign</tt> implies <tt>__unsafe_unretained</tt> ownership.</li> +<li><tt>copy</tt> implies <tt>__strong</tt> ownership, as well as the + usual behavior of copy semantics on the setter.</li> +<li><tt>retain</tt> implies <tt>__strong</tt> ownership.</li> +<li><tt>strong</tt> implies <tt>__strong</tt> ownership.</li> +<li><tt>unsafe_unretained</tt> implies <tt>__unsafe_unretained</tt> + ownership.</li> +<li><tt>weak</tt> implies <tt>__weak</tt> ownership.</li> +</ul> + +<p>With the exception of <tt>weak</tt>, these modifiers are available +in non-ARC modes.</p> + +<p>A property's specified ownership is preserved in its metadata, but +otherwise the meaning is purely conventional unless the property is +synthesized. If a property is synthesized, then the +<span class="term">associated instance variable</span> is the +instance variable which is named, possibly implicitly, by the +<tt>@synthesize</tt> declaration. If the associated instance variable +already exists, then its ownership qualification must equal the +ownership of the property; otherwise, the instance variable is created +with that ownership qualification.</p> + +</div> <!-- ownership.spelling.property --> + +</div> <!-- ownership.spelling --> + +<div id="ownership.semantics"> +<h1>Semantics</h1> + +<p>There are five <span class="term">managed operations</span> which +may be performed on an object of retainable object pointer type. Each +qualifier specifies different semantics for each of these operations. +It is still undefined behavior to access an object outside of its +lifetime.</p> + +<p>A load or store with <q>primitive semantics</q> has the same +semantics as the respective operation would have on an <tt>void*</tt> +lvalue with the same alignment and non-ownership qualification.</p> + +<p><span class="term">Reading</span> occurs when performing a +lvalue-to-rvalue conversion on an object lvalue. + +<ul> +<li>For <tt>__weak</tt> objects, the current pointee is retained and +then released at the end of the current full-expression. This must +execute atomically with respect to assignments and to the final +release of the pointee.</li> +<li>For all other objects, the lvalue is loaded with primitive +semantics.</li> +</ul> +</p> + +<p><span class="term">Assignment</span> occurs when evaluating +an assignment operator. The semantics vary based on the qualification: +<ul> +<li>For <tt>__strong</tt> objects, the new pointee is first retained; +second, the lvalue is loaded with primitive semantics; third, the new +pointee is stored into the lvalue with primitive semantics; and +finally, the old pointee is released. This is not performed +atomically; external synchronization must be used to make this safe in +the face of concurrent loads and stores.</li> +<li>For <tt>__weak</tt> objects, the lvalue is updated to point to the +new pointee, unless that object is currently undergoing deallocation, +in which case it the lvalue is updated to a null pointer. This must +execute atomically with respect to other assignments to the object, to +reads from the object, and to the final release of the new pointed-to +value.</li> +<li>For <tt>__unsafe_unretained</tt> objects, the new pointee is +stored into the lvalue using primitive semantics.</li> +<li>For <tt>__autoreleasing</tt> objects, the new pointee is retained, +autoreleased, and stored into the lvalue using primitive semantics.</li> +</ul> +</p> + +<p><span class="term">Initialization</span> occurs when an object's +lifetime begins, which depends on its storage duration. +Initialization proceeds in two stages: +<ol> +<li>First, a null pointer is stored into the lvalue using primitive +semantics. This step is skipped if the object +is <tt>__unsafe_unretained</tt>.</li> +<li>Second, if the object has an initializer, that expression is +evaluated and then assigned into the object using the usual assignment +semantics.</li> +</ol> +</p> + +<p><span class="term">Destruction</span> occurs when an object's +lifetime ends. In all cases it is semantically equivalent to +assigning a null pointer to the object, with the proviso that of +course the object cannot be legally read after the object's lifetime +ends.</p> + +<p><span class="term">Moving</span> occurs in specific situations +where an lvalue is <q>moved from</q>, meaning that its current pointee +will be used but the object may be left in a different (but still +valid) state. This arises with <tt>__block</tt> variables and rvalue +references in C++. For <tt>__strong</tt> lvalues, moving is equivalent +to loading the lvalue with primitive semantics, writing a null pointer +to it with primitive semantics, and then releasing the result of the +load at the end of the current full-expression. For all other +lvalues, moving is equivalent to reading the object.</p> + +</div> <!-- ownership.semantics --> + +<div id="ownership.restrictions"> +<h1>Restrictions</h1> + +<div id="ownership.restrictions.weak"> +<h1>Weak-unavailable types</h1> + +<p>It is explicitly permitted for Objective-C classes to not +support <tt>__weak</tt> references. It is undefined behavior to +perform an operation with weak assignment semantics with a pointer to +an Objective-C object whose class does not support <tt>__weak</tt> +references.</p> + +<div class="rationale"><p>Rationale: historically, it has been +possible for a class to provide its own reference-count implementation +by overriding <tt>retain</tt>, <tt>release</tt>, etc. However, weak +references to an object require coordination with its class's +reference-count implementation because, among other things, weak loads +and stores must be atomic with respect to the final release. +Therefore, existing custom reference-count implementations will +generally not support weak references without additional effort. This +is unavoidable without breaking binary compatibility.</p></div> + +<p>A class may indicate that it does not support weak references by +providing the <tt>objc_arc_weak_unavailable</tt> attribute on the +class's interface declaration. A retainable object pointer type +is <span class="term">weak-unavailable</span> if is a pointer to an +(optionally protocol-qualified) Objective-C class <tt>T</tt> +where <tt>T</tt> or one of its superclasses has +the <tt>objc_arc_weak_unavailable</tt> attribute. A program is +ill-formed if it applies the <tt>__weak</tt> ownership qualifier to a +weak-unavailable type or if the value operand of a weak assignment +operation has a weak-unavailable type.</p> +</div> <!-- ownership.restrictions.weak --> + +<div id="ownership.restrictions.autoreleasing"> +<h1>Storage duration of <tt>__autoreleasing</tt> objects</h1> + +<p>A program is ill-formed if it declares an <tt>__autoreleasing</tt> +object of non-automatic storage duration.</p> + +<div class="rationale"><p>Rationale: autorelease pools are tied to the +current thread and scope by their nature. While it is possible to +have temporary objects whose instance variables are filled with +autoreleased objects, there is no way that ARC can provide any sort of +safety guarantee there.</p></div> + +<p>It is undefined behavior if a non-null pointer is assigned to +an <tt>__autoreleasing</tt> object while an autorelease pool is in +scope and then that object is read after the autorelease pool's scope +is left.</p> + +</div> + +<div id="ownership.restrictions.conversion.indirect"> +<h1>Conversion of pointers to ownership-qualified types</h1> + +<p>A program is ill-formed if an expression of type <tt>T*</tt> is +converted, explicitly or implicitly, to the type <tt>U*</tt>, +where <tt>T</tt> and <tt>U</tt> have different ownership +qualification, unless: +<ul> +<li><tt>T</tt> is qualified with <tt>__strong</tt>, + <tt>__autoreleasing</tt>, or <tt>__unsafe_unretained</tt>, and + <tt>U</tt> is qualified with both <tt>const</tt> and + <tt>__unsafe_unretained</tt>; or</li> +<li>either <tt>T</tt> or <tt>U</tt> is <tt>cv void</tt>, where +<tt>cv</tt> is an optional sequence of non-ownership qualifiers; or</li> +<li>the conversion is requested with a <tt>reinterpret_cast</tt> in + Objective-C++; or</li> +<li>the conversion is a +well-formed <a href="#ownership.restrictions.pass_by_writeback">pass-by-writeback</a>.</li> +</ul> +</p> + +<p>The analogous rule applies to <tt>T&</tt> and <tt>U&</tt> in +Objective-C++.</p> + +<div class="rationale"><p>Rationale: these rules provide a reasonable +level of type-safety for indirect pointers, as long as the underlying +memory is not deallocated. The conversion to <tt>const +__unsafe_unretained</tt> is permitted because the semantics of reads +are equivalent across all these ownership semantics, and that's a very +useful and common pattern. The interconversion with <tt>void*</tt> is +useful for allocating memory or otherwise escaping the type system, +but use it carefully. <tt>reinterpret_cast</tt> is considered to be +an obvious enough sign of taking responsibility for any +problems.</p></div> + +<p>It is undefined behavior to access an ownership-qualified object +through an lvalue of a differently-qualified type, except that any +non-<tt>__weak</tt> object may be read through +an <tt>__unsafe_unretained</tt> lvalue.</p> + +<p>It is undefined behavior if a managed operation is performed on +a <tt>__strong</tt> or <tt>__weak</tt> object without a guarantee that +it contains a primitive zero bit-pattern, or if the storage for such +an object is freed or reused without the object being first assigned a +null pointer.</p> + +<div class="rationale"><p>Rationale: ARC cannot differentiate between +an assignment operator which is intended to <q>initialize</q> dynamic +memory and one which is intended to potentially replace a value. +Therefore the object's pointer must be valid before letting ARC at it. +Similarly, C and Objective-C do not provide any language hooks for +destroying objects held in dynamic memory, so it is the programmer's +responsibility to avoid leaks (<tt>__strong</tt> objects) and +consistency errors (<tt>__weak</tt> objects).</p> + +<p>These requirements are followed automatically in Objective-C++ when +creating objects of retainable object owner type with <tt>new</tt> +or <tt>new[]</tt> and destroying them with <tt>delete</tt>, +<tt>delete[]</tt>, or a pseudo-destructor expression. Note that +arrays of nontrivially-ownership-qualified type are not ABI compatible +with non-ARC code because the element type is non-POD: such arrays +that are <tt>new[]</tt>'d in ARC translation units cannot +be <tt>delete[]</tt>'d in non-ARC translation units and +vice-versa.</p></div> + +</div> + +<div id="ownership.restrictions.pass_by_writeback"> +<h1>Passing to an out parameter by writeback</h1> + +<p>If the argument passed to a parameter of type +<tt>T __autoreleasing *</tt> has type <tt>U oq *</tt>, +where <tt>oq</tt> is an ownership qualifier, then the argument is a +candidate for <span class="term">pass-by-writeback</span> if:</p> + +<ul> +<li><tt>oq</tt> is <tt>__strong</tt> or <tt>__weak</tt>, and +<li>it would be legal to initialize a <tt>T __strong *</tt> with +a <tt>U __strong *</tt>.</li> +</ul> + +<p>For purposes of overload resolution, an implicit conversion +sequence requiring a pass-by-writeback is always worse than an +implicit conversion sequence not requiring a pass-by-writeback.</p> + +<p>The pass-by-writeback is ill-formed if the argument expression does +not have a legal form:</p> + +<ul> +<li><tt>&var</tt>, where <tt>var</tt> is a scalar variable of +automatic storage duration with retainable object pointer type</li> +<li>a conditional expression where the second and third operands are +both legal forms</li> +<li>a cast whose operand is a legal form</li> +<li>a null pointer constant</li> +</ul> + +<div class="rationale"><p>Rationale: the restriction in the form of +the argument serves two purposes. First, it makes it impossible to +pass the address of an array to the argument, which serves to protect +against an otherwise serious risk of mis-inferring an <q>array</q> +argument as an out-parameter. Second, it makes it much less likely +that the user will see confusing aliasing problems due to the +implementation, below, where their store to the writeback temporary is +not immediately seen in the original argument variable.</p></div> + +<p>A pass-by-writeback is evaluated as follows: +<ol> +<li>The argument is evaluated to yield a pointer <tt>p</tt> of + type <tt>U oq *</tt>.</li> +<li>If <tt>p</tt> is a null pointer, then a null pointer is passed as + the argument, and no further work is required for the pass-by-writeback.</li> +<li>Otherwise, a temporary of type <tt>T __autoreleasing</tt> is + created and initialized to a null pointer.</li> +<li>If the argument is not an Objective-C method parameter marked + <tt>out</tt>, then <tt>*p</tt> is read, and the result is written + into the temporary with primitive semantics.</li> +<li>The address of the temporary is passed as the argument to the + actual call.</li> +<li>After the call completes, the temporary is loaded with primitive + semantics, and that value is assigned into <tt>*p</tt>.</li> +</ol></p> + +<div class="rationale"><p>Rationale: this is all admittedly +convoluted. In an ideal world, we would see that a local variable is +being passed to an out-parameter and retroactively modify its type to +be <tt>__autoreleasing</tt> rather than <tt>__strong</tt>. This would +be remarkably difficult and not always well-founded under the C type +system. However, it was judged unacceptably invasive to require +programmers to write <tt>__autoreleasing</tt> on all the variables +they intend to use for out-parameters. This was the least bad +solution.</p></div> + +</div> + +<div id="ownership.restrictions.records"> +<h1>Ownership-qualified fields of structs and unions</h1> + +<p>A program is ill-formed if it declares a member of a C struct or +union to have a nontrivially ownership-qualified type.</p> + +<div class="rationale"><p>Rationale: the resulting type would be +non-POD in the C++ sense, but C does not give us very good language +tools for managing the lifetime of aggregates, so it is more +convenient to simply forbid them. It is still possible to manage this +with a <tt>void*</tt> or an <tt>__unsafe_unretained</tt> +object.</p></div> + +<p>This restriction does not apply in Objective-C++. However, +nontrivally ownership-qualified types are considered non-POD: in C++0x +terms, they are not trivially default constructible, copy +constructible, move constructible, copy assignable, move assignable, +or destructible. It is a violation of C++ One Definition Rule to use +a class outside of ARC that, under ARC, would have an +ownership-qualified member.</p> + +<div class="rationale"><p>Rationale: unlike in C, we can express all +the necessary ARC semantics for ownership-qualified subobjects as +suboperations of the (default) special member functions for the class. +These functions then become non-trivial. This has the non-obvious +repercussion that the class will have a non-trivial copy constructor +and non-trivial destructor; if it wouldn't outside of ARC, this means +that objects of the type will be passed and returned in an +ABI-incompatible manner.</p></div> + +</div> + +</div> + +<div id="ownership.inference"> +<h1>Ownership inference</h1> + +<div id="ownership.inference.variables"> +<h1>Objects</h1> + +<p>If an object is declared with retainable object owner type, but +without an explicit ownership qualifier, its type is implicitly +adjusted to have <tt>__strong</tt> qualification.</p> + +<p>As a special case, if the object's base type is <tt>Class</tt> +(possibly protocol-qualified), the type is adjusted to +have <tt>__unsafe_unretained</tt> qualification instead.</p> + +</div> + +<div id="ownership.inference.indirect_parameters"> +<h1>Indirect parameters</h1> + +<p>If a function or method parameter has type <tt>T*</tt>, where +<tt>T</tt> is an ownership-unqualified retainable object pointer type, +then:</p> + +<ul> +<li>if <tt>T</tt> is <tt>const</tt>-qualified or <tt>Class</tt>, then +it is implicitly qualified with <tt>__unsafe_unretained</tt>;</li> +<li>otherwise, it is implicitly qualified +with <tt>__autoreleasing</tt>.</li> +</ul> +</p> + +<div class="rationale"><p>Rationale: <tt>__autoreleasing</tt> exists +mostly for this case, the Cocoa convention for out-parameters. Since +a pointer to <tt>const</tt> is obviously not an out-parameter, we +instead use a type more useful for passing arrays. If the user +instead intends to pass in a <em>mutable</em> array, inferring +<tt>__autoreleasing</tt> is the wrong thing to do; this directs some +of the caution in the following rules about writeback.</p></div> + +<p>Such a type written anywhere else would be ill-formed by the +general rule requiring ownership qualifiers.</p> + +<p>This rule does not apply in Objective-C++ if a parameter's type is +dependent in a template pattern and is only <em>instantiated</em> to +a type which would be a pointer to an unqualified retainable object +pointer type. Such code is still ill-formed.</p> + +<div class="rationale"><p>Rationale: the convention is very unlikely +to be intentional in template code.</p></div> + +</div> <!-- ownership.inference.indirect_parameters --> + +<div id="ownership.inference.template_arguments"> +<h1>Template arguments</h1> + +<p>If a template argument for a template type parameter is an +retainable object owner type that does not have an explicit ownership +qualifier, it is adjusted to have <tt>__strong</tt> +qualification. This adjustment occurs regardless of whether the +template argument was deduced or explicitly specified. </p> + +<div class="rationale"><p>Rationale: <tt>__strong</tt> is a useful default for containers (e.g., <tt>std::vector<id></tt>), which would otherwise require explicit qualification. Moreover, unqualified retainable object pointer types are unlikely to be useful within templates, since they generally need to have a qualifier applied to the before being used.</p></div> + +</div> <!-- ownership.inference.template_arguments --> +</div> <!-- ownership.inference --> +</div> <!-- ownership --> + + +<div id="family"> +<h1>Method families</h1> + +<p>An Objective-C method may fall into a <span class="term">method +family</span>, which is a conventional set of behaviors ascribed to it +by the Cocoa conventions.</p> + +<p>A method is in a certain method family if: +<ul> +<li>it has a <tt>objc_method_family</tt> attribute placing it in that + family; or if not that,</li> +<li>it does not have an <tt>objc_method_family</tt> attribute placing + it in a different or no family, and</li> +<li>its selector falls into the corresponding selector family, and</li> +<li>its signature obeys the added restrictions of the method family.</li> +</ul></p> + +<p>A selector is in a certain selector family if, ignoring any leading +underscores, the first component of the selector either consists +entirely of the name of the method family or it begins with that name +followed by a character other than a lowercase letter. For +example, <tt>_perform:with:</tt> and <tt>performWith:</tt> would fall +into the <tt>perform</tt> family (if we recognized one), +but <tt>performing:with</tt> would not.</p> + +<p>The families and their added restrictions are:</p> + +<ul> +<li><tt>alloc</tt> methods must return a retainable object pointer type.</li> +<li><tt>copy</tt> methods must return a retainable object pointer type.</li> +<li><tt>mutableCopy</tt> methods must return a retainable object pointer type.</li> +<li><tt>new</tt> methods must return a retainable object pointer type.</li> +<li><tt>init</tt> methods must be instance methods and must return an +Objective-C pointer type. Additionally, a program is ill-formed if it +declares or contains a call to an <tt>init</tt> method whose return +type is neither <tt>id</tt> nor a pointer to a super-class or +sub-class of the declaring class (if the method was declared on +a class) or the static receiver type of the call (if it was declared +on a protocol).</p> + +<div class="rationale"><p>Rationale: there are a fair number of existing +methods with <tt>init</tt>-like selectors which nonetheless don't +follow the <tt>init</tt> conventions. Typically these are either +accidental naming collisions or helper methods called during +initialization. Because of the peculiar retain/release behavior +of <tt>init</tt> methods, it's very important not to treat these +methods as <tt>init</tt> methods if they aren't meant to be. It was +felt that implicitly defining these methods out of the family based on +the exact relationship between the return type and the declaring class +would be much too subtle and fragile. Therefore we identify a small +number of legitimate-seeming return types and call everything else an +error. This serves the secondary purpose of encouraging programmers +not to accidentally give methods names in the <tt>init</tt> family.</p> + +<p>Note that a method with an <tt>init</tt>-family selector which +returns a non-Objective-C type (e.g. <tt>void</tt>) is perfectly +well-formed; it simply isn't in the <tt>init</tt> family.</p></div> +</li> +</ul> + +<p>A program is ill-formed if a method's declarations, +implementations, and overrides do not all have the same method +family.</p> + +<div id="family.attribute"> +<h1>Explicit method family control</h1> + +<p>A method may be annotated with the <tt>objc_method_family</tt> +attribute to precisely control which method family it belongs to. If +a method in an <tt>@implementation</tt> does not have this attribute, +but there is a method declared in the corresponding <tt>@interface</tt> +that does, then the attribute is copied to the declaration in the +<tt>@implementation</tt>. The attribute is available outside of ARC, +and may be tested for with the preprocessor query +<tt>__has_attribute(objc_method_family)</tt>.</p> + +<p>The attribute is spelled +<tt>__attribute__((objc_method_family(<i>family</i>)))</tt>. +If <i>family</i> is <tt>none</tt>, the method has no family, even if +it would otherwise be considered to have one based on its selector and +type. Otherwise, <i>family</i> must be one +of <tt>alloc</tt>, <tt>copy</tt>, <tt>init</tt>, +<tt>mutableCopy</tt>, or <tt>new</tt>, in which case the method is +considered to belong to the corresponding family regardless of its +selector. It is an error if a method that is explicitly added to a +family in this way does not meet the requirements of the family other +than the selector naming convention.</p> + +<div class="rationale"><p>Rationale: the rules codified in this document +describe the standard conventions of Objective-C. However, as these +conventions have not heretofore been enforced by an unforgiving +mechanical system, they are only imperfectly kept, especially as they +haven't always even been precisely defined. While it is possible to +define low-level ownership semantics with attributes like +<tt>ns_returns_retained</tt>, this attribute allows the user to +communicate semantic intent, which of use both to ARC (which, e.g., +treats calls to <tt>init</tt> specially) and the static analyzer.</p></div> +</div> + +<div id="family.semantics"> +<h1>Semantics of method families</h1> + +<p>A method's membership in a method family may imply non-standard +semantics for its parameters and return type.</p> + +<p>Methods in the <tt>alloc</tt>, <tt>copy</tt>, <tt>mutableCopy</tt>, +and <tt>new</tt> families — that is, methods in all the +currently-defined families except <tt>init</tt> — implicitly +<a href="#objects.operands.retained_returns">return a retained +object</a> as if they were annotated with +the <tt>ns_returns_retained</tt> attribute. This can be overridden by +annotating the method with either of +the <tt>ns_returns_autoreleased</tt> or +<tt>ns_returns_not_retained</tt> attributes.</p> + +<p>Properties also follow same naming rules as methods. This means that +those in the <tt>alloc</tt>, <tt>copy</tt>, <tt>mutableCopy</tt>, +and <tt>new</tt> families provide access to +<a href="#objects.operands.retained_returns">retained objects</a>. +This can be overridden by annotating the property with +<tt>ns_returns_not_retained</tt> attribute.</p> + +<div id="family.semantics.init"> +<h1>Semantics of <tt>init</tt></h1> +<p>Methods in the <tt>init</tt> family implicitly +<a href="#objects.operands.consumed">consume</a> their <tt>self</tt> +parameter and <a href="#objects.operands.retained_returns">return a +retained object</a>. Neither of these properties can be altered +through attributes.</p> + +<p>A call to an <tt>init</tt> method with a receiver that is either +<tt>self</tt> (possibly parenthesized or casted) or <tt>super</tt> is +called a <span class="term">delegate init call</span>. It is an error +for a delegate init call to be made except from an <tt>init</tt> +method, and excluding blocks within such methods.</p> + +<p>As an exception to the <a href="misc.self">usual rule</a>, the +variable <tt>self</tt> is mutable in an <tt>init</tt> method and has +the usual semantics for a <tt>__strong</tt> variable. However, it is +undefined behavior and the program is ill-formed, no diagnostic +required, if an <tt>init</tt> method attempts to use the previous +value of <tt>self</tt> after the completion of a delegate init call. +It is conventional, but not required, for an <tt>init</tt> method to +return <tt>self</tt>.</p> + +<p>It is undefined behavior for a program to cause two or more calls +to <tt>init</tt> methods on the same object, except that +each <tt>init</tt> method invocation may perform at most one delegate +init call.</p> + +</div> <!-- family.semantics.init --> + +<div id="family.semantics.result_type"> +<h1>Related result types</h1> + +<p>Certain methods are candidates to have <span class="term">related +result types</span>:</p> +<ul> +<li>class methods in the <tt>alloc</tt> and <tt>new</tt> method families</li> +<li>instance methods in the <tt>init</tt> family</li> +<li>the instance method <tt>self</tt></li> +<li>outside of ARC, the instance methods <tt>retain</tt> and <tt>autorelease</tt></li> +</ul> + +<p>If the formal result type of such a method is <tt>id</tt> or +protocol-qualified <tt>id</tt>, or a type equal to the declaring class +or a superclass, then it is said to have a related result type. In +this case, when invoked in an explicit message send, it is assumed to +return a type related to the type of the receiver:</p> + +<ul> +<li>if it is a class method, and the receiver is a class +name <tt>T</tt>, the message send expression has type <tt>T*</tt>; +otherwise</li> +<li>if it is an instance method, and the receiver has type <tt>T</tt>, +the message send expression has type <tt>T</tt>; otherwise</li> +<li>the message send expression has the normal result type of the +method.</li> +</ul> + +<p>This is a new rule of the Objective-C language and applies outside +of ARC.</p> + +<div class="rationale"><p>Rationale: ARC's automatic code emission is +more prone than most code to signature errors, i.e. errors where a +call was emitted against one method signature, but the implementing +method has an incompatible signature. Having more precise type +information helps drastically lower this risks, as well as catching +a number of latent bugs.</p></div> + +</div> <!-- family.semantics.result_type --> +</div> <!-- family.semantics --> +</div> <!-- family --> + +<div id="optimization"> +<h1>Optimization</h1> + +<p>ARC applies aggressive rules for the optimization of local +behavior. These rules are based around a core assumption of +<span class="term">local balancing</span>: that other code will +perform retains and releases as necessary (and only as necessary) for +its own safety, and so the optimizer does not need to consider global +properties of the retain and release sequence. For example, if a +retain and release immediately bracket a call, the optimizer can +delete the retain and release on the assumption that the called +function will not do a constant number of unmotivated releases +followed by a constant number of <q>balancing</q> retains, such that +the local retain/release pair is the only thing preventing the called +function from ending up with a dangling reference.</p> + +<p>The optimizer assumes that when a new value enters local control, +e.g. from a load of a non-local object or as the result of a function +call, it is instaneously valid. Subsequently, a retain and release of +a value are necessary on a computation path only if there is a use of +that value before the release and after any operation which might +cause a release of the value (including indirectly or non-locally), +and only if the value is not demonstrably already retained.</p> + +<p>The complete optimization rules are quite complicated, but it would +still be useful to document them here.</p> + +</div> + +<div id="misc"> +<h1>Miscellaneous</h1> + +<div id="misc.special_methods"> +<h1>Special methods</h1> + +<div id="misc.special_methods.retain"> +<h1>Memory management methods</h1> + +<p>A program is ill-formed if it contains a method definition, message +send, or <tt>@selector</tt> expression for any of the following +selectors: +<ul> +<li><tt>autorelease</tt></li> +<li><tt>release</tt></li> +<li><tt>retain</tt></li> +<li><tt>retainCount</tt></li> +</ul> +</p> + +<div class="rationale"><p>Rationale: <tt>retainCount</tt> is banned +because ARC robs it of consistent semantics. The others were banned +after weighing three options for how to deal with message sends:</p> + +<p><b>Honoring</b> them would work out very poorly if a programmer +naively or accidentally tried to incorporate code written for manual +retain/release code into an ARC program. At best, such code would do +twice as much work as necessary; quite frequently, however, ARC and +the explicit code would both try to balance the same retain, leading +to crashes. The cost is losing the ability to perform <q>unrooted</q> +retains, i.e. retains not logically corresponding to a strong +reference in the object graph.</p> + +<p><b>Ignoring</b> them would badly violate user expectations about their +code. While it <em>would</em> make it easier to develop code simultaneously +for ARC and non-ARC, there is very little reason to do so except for +certain library developers. ARC and non-ARC translation units share +an execution model and can seamlessly interoperate. Within a +translation unit, a developer who faithfully maintains their code in +non-ARC mode is suffering all the restrictions of ARC for zero +benefit, while a developer who isn't testing the non-ARC mode is +likely to be unpleasantly surprised if they try to go back to it.</p> + +<p><b>Banning</b> them has the disadvantage of making it very awkward +to migrate existing code to ARC. The best answer to that, given a +number of other changes and restrictions in ARC, is to provide a +specialized tool to assist users in that migration.</p> + +<p>Implementing these methods was banned because they are too integral +to the semantics of ARC; many tricks which worked tolerably under +manual reference counting will misbehave if ARC performs an ephemeral +extra retain or two. If absolutely required, it is still possible to +implement them in non-ARC code, for example in a category; the +implementations must obey the <a href="#objects.retains">semantics</a> +laid out elsewhere in this document.</p> + +</div> +</div> <!-- misc.special_methods.retain --> + +<div id="misc.special_methods.dealloc"> +<h1><tt>dealloc</tt></h1> + +<p>A program is ill-formed if it contains a message send +or <tt>@selector</tt> expression for the selector <tt>dealloc</tt>.</p> + +<div class="rationale"><p>Rationale: there are no legitimate reasons +to call <tt>dealloc</tt> directly.</p></div> + +<p>A class may provide a method definition for an instance method +named <tt>dealloc</tt>. This method will be called after the final +<tt>release</tt> of the object but before it is deallocated or any of +its instance variables are destroyed. The superclass's implementation +of <tt>dealloc</tt> will be called automatically when the method +returns.</p> + +<div class="rationale"><p>Rationale: even though ARC destroys instance +variables automatically, there are still legitimate reasons to write +a <tt>dealloc</tt> method, such as freeing non-retainable resources. +Failing to call <tt>[super dealloc]</tt> in such a method is nearly +always a bug. Sometimes, the object is simply trying to prevent +itself from being destroyed, but <tt>dealloc</tt> is really far too +late for the object to be raising such objections. Somewhat more +legitimately, an object may have been pool-allocated and should not be +deallocated with <tt>free</tt>; for now, this can only be supported +with a <tt>dealloc</tt> implementation outside of ARC. Such an +implementation must be very careful to do all the other work +that <tt>NSObject</tt>'s <tt>dealloc</tt> would, which is outside the +scope of this document to describe.</p></div> + +</div> + +</div> <!-- misc.special_methods --> + +<div id="autoreleasepool"> +<h1><tt>@autoreleasepool</tt></h1> + +<p>To simplify the use of autorelease pools, and to bring them under +the control of the compiler, a new kind of statement is available in +Objective-C. It is written <tt>@autoreleasepool</tt> followed by +a <i>compound-statement</i>, i.e. by a new scope delimited by curly +braces. Upon entry to this block, the current state of the +autorelease pool is captured. When the block is exited normally, +whether by fallthrough or directed control flow (such +as <tt>return</tt> or <tt>break</tt>), the autorelease pool is +restored to the saved state, releasing all the objects in it. When +the block is exited with an exception, the pool is not drained.</p> + +<p><tt>@autoreleasepool</tt> may be used in non-ARC translation units, +with equivalent semantics.</p> + +<p>A program is ill-formed if it refers to the +<tt>NSAutoreleasePool</tt> class.</p> + +<div class="rationale"><p>Rationale: autorelease pools are clearly +important for the compiler to reason about, but it is far too much to +expect the compiler to accurately reason about control dependencies +between two calls. It is also very easy to accidentally forget to +drain an autorelease pool when using the manual API, and this can +significantly inflate the process's high-water-mark. The introduction +of a new scope is unfortunate but basically required for sane +interaction with the rest of the language. Not draining the pool +during an unwind is apparently required by the Objective-C exceptions +implementation.</p></div> + +</div> <!-- autoreleasepool --> + +<div id="misc.self"> +<h1><tt>self</tt></h1> + +<p>The <tt>self</tt> parameter variable of an Objective-C method is +never actually retained by the implementation. It is undefined +behavior, or at least dangerous, to cause an object to be deallocated +during a message send to that object. To make this +safe, <tt>self</tt> is implicitly <tt>const</tt> unless the method is +in the <a href="#family.semantics.init"><tt>init</tt> family</a>.</p> + +<div class="rationale"><p>Rationale: the cost of +retaining <tt>self</tt> in all methods was found to be prohibitive, as +it tends to be live across calls, preventing the optimizer from +proving that the retain and release are unnecessary — for good +reason, as it's quite possible in theory to cause an object to be +deallocated during its execution without this retain and release. +Since it's extremely uncommon to actually do so, even unintentionally, +and since there's no natural way for the programmer to remove this +retain/release pair otherwise (as there is for other parameters by, +say, making the variable <tt>__unsafe_unretained</tt>), we chose to +make this optimizing assumption and shift some amount of risk to the +user.</p></div> + +</div> <!-- misc.self --> + +<div id="misc.enumeration"> +<h1>Fast enumeration iteration variables</h1> + +<p>If a variable is declared in the condition of an Objective-C fast +enumeration loop, and the variable has no explicit ownership +qualifier, then it is qualified with <tt>const __strong</tt> and +objects encountered during the enumeration are not actually +retained.</p> + +<div class="rationale"><p>Rationale: this is an optimization made +possible because fast enumeration loops promise to keep the objects +retained during enumeration, and the collection itself cannot be +synchronously modified. It can be overridden by explicitly qualifying +the variable with <tt>__strong</tt>, which will make the variable +mutable again and cause the loop to retain the objects it +encounters.</div> + +</div> + +<div id="misc.blocks"> +<h1>Blocks</h1> + +<p>The implicit <tt>const</tt> capture variables created when +evaluating a block literal expression have the same ownership +semantics as the local variables they capture. The capture is +performed by reading from the captured variable and initializing the +capture variable with that value; the capture variable is destroyed +when the block literal is, i.e. at the end of the enclosing scope.</p> + +<p>The <a href="#ownership.inference">inference</a> rules apply +equally to <tt>__block</tt> variables, which is a shift in semantics +from non-ARC, where <tt>__block</tt> variables did not implicitly +retain during capture.</p> + +<p><tt>__block</tt> variables of retainable object owner type are +moved off the stack by initializing the heap copy with the result of +moving from the stack copy.</tt></p> + +<p>With the exception of retains done as part of initializing +a <tt>__strong</tt> parameter variable or reading a <tt>__weak</tt> +variable, whenever these semantics call for retaining a value of +block-pointer type, it has the effect of a <tt>Block_copy</tt>. The +optimizer may remove such copies when it sees that the result is +used only as an argument to a call.</p> + +</div> <!-- misc.blocks --> + +<div id="misc.exceptions"> +<h1>Exceptions</h1> + +<p>By default in Objective C, ARC is not exception-safe for normal +releases: +<ul> +<li>It does not end the lifetime of <tt>__strong</tt> variables when +their scopes are abnormally terminated by an exception.</li> +<li>It does not perform releases which would occur at the end of +a full-expression if that full-expression throws an exception.</li> +</ul> + +<p>A program may be compiled with the option +<tt>-fobjc-arc-exceptions</tt> in order to enable these, or with the +option <tt>-fno-objc-arc-exceptions</tt> to explicitly disable them, +with the last such argument <q>winning</q>.</p> + +<div class="rationale"><p>Rationale: the standard Cocoa convention is +that exceptions signal programmer error and are not intended to be +recovered from. Making code exceptions-safe by default would impose +severe runtime and code size penalties on code that typically does not +actually care about exceptions safety. Therefore, ARC-generated code +leaks by default on exceptions, which is just fine if the process is +going to be immediately terminated anyway. Programs which do care +about recovering from exceptions should enable the option.</p></div> + +<p>In Objective-C++, <tt>-fobjc-arc-exceptions</tt> is enabled by +default.</p> + +<div class="rationale"><p>Rationale: C++ already introduces pervasive +exceptions-cleanup code of the sort that ARC introduces. C++ +programmers who have not already disabled exceptions are much more +likely to actual require exception-safety.</p></div> + +<p>ARC does end the lifetimes of <tt>__weak</tt> objects when an +exception terminates their scope unless exceptions are disabled in the +compiler.</p> + +<div class="rationale"><p>Rationale: the consequence of a +local <tt>__weak</tt> object not being destroyed is very likely to be +corruption of the Objective-C runtime, so we want to be safer here. +Of course, potentially massive leaks are about as likely to take down +the process as this corruption is if the program does try to recover +from exceptions.</p></div> + +</div> <!-- misc.exceptions --> + +</div> <!-- misc --> + +<div id="runtime"> +<h1>Runtime support</h1> + +<p>This section describes the interaction between the ARC runtime and +the code generated by the ARC compiler. This is not part of the ARC +language specification; instead, it is effectively a language-specific +ABI supplement, akin to the <q>Itanium</q> generic ABI for C++.</p> + +<p>Ownership qualification does not alter the storage requirements for +objects, except that it is undefined behavior if a <tt>__weak</tt> +object is inadequately aligned for an object of type <tt>id</tt>. The +other qualifiers may be used on explicitly under-aligned memory.</p> + +<p>The runtime tracks <tt>__weak</tt> objects which holds non-null +values. It is undefined behavior to direct modify a <tt>__weak</tt> +object which is being tracked by the runtime except through an +<a href="#runtime.objc_storeWeak"><tt>objc_storeWeak</tt></a>, +<a href="#runtime.objc_destroyWeak"><tt>objc_destroyWeak</tt></a>, +or <a href="#runtime.objc_moveWeak"><tt>objc_moveWeak</tt></a> +call.</p> + +<p>The runtime must provide a number of new entrypoints which the +compiler may emit, which are described in the remainder of this +section.</p> + +<div class="rationale"><p>Rationale: Several of these functions are +semantically equivalent to a message send; we emit calls to C +functions instead because:</p> +<ul> +<li>the machine code to do so is significantly smaller,</li> +<li>it is much easier to recognize the C functions in the ARC optimizer, and</li> +<li>a sufficient sophisticated runtime may be able to avoid the +message send in common cases.</li> +</ul> + +<p>Several other of these functions are <q>fused</q> operations which +can be described entirely in terms of other operations. We use the +fused operations primarily as a code-size optimization, although in +some cases there is also a real potential for avoiding redundant +operations in the runtime.</p> + +</div> + +<div id="runtime.objc_autorelease"> +<h1><tt>id objc_autorelease(id value);</tt></h1> +<p><i>Precondition:</i> <tt>value</tt> is null or a pointer to a +valid object.</p> +<p>If <tt>value</tt> is null, this call has no effect. Otherwise, it +adds the object to the innermost autorelease pool exactly as if the +object had been sent the <tt>autorelease</tt> message.</p> +<p>Always returns <tt>value</tt>.</p> +</div> <!-- runtime.objc_autorelease --> + +<div id="runtime.objc_autoreleasePoolPop"> +<h1><tt>void objc_autoreleasePoolPop(void *pool);</tt></h1> +<p><i>Precondition:</i> <tt>pool</tt> is the result of a previous call to +<a href="runtime.objc_autoreleasePoolPush"><tt>objc_autoreleasePoolPush</tt></a> +on the current thread, where neither <tt>pool</tt> nor any enclosing +pool have previously been popped.</p> +<p>Releases all the objects added to the given autorelease pool and +any autorelease pools it encloses, then sets the current autorelease +pool to the pool directly enclosing <tt>pool</tt>.</p> +</div> <!-- runtime.objc_autoreleasePoolPop --> + +<div id="runtime.objc_autoreleasePoolPush"> +<h1><tt>void *objc_autoreleasePoolPush(void);</tt></h1> +<p>Creates a new autorelease pool that is enclosed by the current +pool, makes that the current pool, and returns an opaque <q>handle</q> +to it.</p> + +<div class="rationale"><p>Rationale: while the interface is described +as an explicit hierarchy of pools, the rules allow the implementation +to just keep a stack of objects, using the stack depth as the opaque +pool handle.</p></div> + +</div> <!-- runtime.objc_autoreleasePoolPush --> + +<div id="runtime.objc_autoreleaseReturnValue"> +<h1><tt>id objc_autoreleaseReturnValue(id value);</tt></h1> +<p><i>Precondition:</i> <tt>value</tt> is null or a pointer to a +valid object.</p> +<p>If <tt>value</tt> is null, this call has no effect. Otherwise, it +makes a best effort to hand off ownership of a retain count on the +object to a call +to <a href="runtime.objc_retainAutoreleasedReturnValue"><tt>objc_retainAutoreleasedReturnValue</tt></a> +for the same object in an enclosing call frame. If this is not +possible, the object is autoreleased as above.</p> +<p>Always returns <tt>value</tt>.</p> +</div> <!-- runtime.objc_autoreleaseReturnValue --> + +<div id="runtime.objc_copyWeak"> +<h1><tt>void objc_copyWeak(id *dest, id *src);</tt></h1> +<p><i>Precondition:</i> <tt>src</tt> is a valid pointer which either +contains a null pointer or has been registered as a <tt>__weak</tt> +object. <tt>dest</tt> is a valid pointer which has not been +registered as a <tt>__weak</tt> object.</p> +<p><tt>dest</tt> is initialized to be equivalent to <tt>src</tt>, +potentially registering it with the runtime. Equivalent to the +following code:</p> +<pre>void objc_copyWeak(id *dest, id *src) { + objc_release(objc_initWeak(dest, objc_loadWeakRetained(src))); +}</pre> +<p>Must be atomic with respect to calls to <tt>objc_storeWeak</tt> +on <tt>src</tt>.</p> +</div> <!-- runtime.objc_copyWeak --> + +<div id="runtime.objc_destroyWeak"> +<h1><tt>void objc_destroyWeak(id *object);</tt></h1> +<p><i>Precondition:</i> <tt>object</tt> is a valid pointer which +either contains a null pointer or has been registered as +a <tt>__weak</tt> object.</p> +<p><tt>object</tt> is unregistered as a weak object, if it ever was. +The current value of <tt>object</tt> is left unspecified; otherwise, +equivalent to the following code:</p> +<pre>void objc_destroyWeak(id *object) { + objc_storeWeak(object, nil); +}</pre> +<p>Does not need to be atomic with respect to calls +to <tt>objc_storeWeak</tt> on <tt>object</tt>.</p> +</div> <!-- runtime.objc_destroyWeak --> + +<div id="runtime.objc_initWeak"> +<h1><tt>id objc_initWeak(id *object, id value);</tt></h1> +<p><i>Precondition:</i> <tt>object</tt> is a valid pointer which has +not been registered as a <tt>__weak</tt> object. <tt>value</tt> is +null or a pointer to a valid object.</p> +<p>If <tt>value</tt> is a null pointer or the object to which it +points has begun deallocation, <tt>object</tt> is zero-initialized. +Otherwise, <tt>object</tt> is registered as a <tt>__weak</tt> object +pointing to <tt>value</tt>. Equivalent to the following code:</p> +<pre>id objc_initWeak(id *object, id value) { + *object = nil; + return objc_storeWeak(object, value); +}</pre> +<p>Returns the value of <tt>object</tt> after the call.</p> +<p>Does not need to be atomic with respect to calls +to <tt>objc_storeWeak</tt> on <tt>object</tt>.</p> +</div> <!-- runtime.objc_initWeak --> + +<div id="runtime.objc_loadWeak"> +<h1><tt>id objc_loadWeak(id *object);</tt></h1> +<p><i>Precondition:</i> <tt>object</tt> is a valid pointer which +either contains a null pointer or has been registered as +a <tt>__weak</tt> object.</p> +<p>If <tt>object</tt> is registered as a <tt>__weak</tt> object, and +the last value stored into <tt>object</tt> has not yet been +deallocated or begun deallocation, retains and autoreleases that value +and returns it. Otherwise returns null. Equivalent to the following +code:</p> +<pre>id objc_loadWeak(id *object) { + return objc_autorelease(objc_loadWeakRetained(object)); +}</pre> +<p>Must be atomic with respect to calls to <tt>objc_storeWeak</tt> +on <tt>object</tt>.</p> +<div class="rationale">Rationale: loading weak references would be +inherently prone to race conditions without the retain.</div> +</div> <!-- runtime.objc_loadWeak --> + +<div id="runtime.objc_loadWeakRetained"> +<h1><tt>id objc_loadWeakRetained(id *object);</tt></h1> +<p><i>Precondition:</i> <tt>object</tt> is a valid pointer which +either contains a null pointer or has been registered as +a <tt>__weak</tt> object.</p> +<p>If <tt>object</tt> is registered as a <tt>__weak</tt> object, and +the last value stored into <tt>object</tt> has not yet been +deallocated or begun deallocation, retains that value and returns it. +Otherwise returns null.</p> +<p>Must be atomic with respect to calls to <tt>objc_storeWeak</tt> +on <tt>object</tt>.</p> +</div> <!-- runtime.objc_loadWeakRetained --> + +<div id="runtime.objc_moveWeak"> +<h1><tt>void objc_moveWeak(id *dest, id *src);</tt></h1> +<p><i>Precondition:</i> <tt>src</tt> is a valid pointer which either +contains a null pointer or has been registered as a <tt>__weak</tt> +object. <tt>dest</tt> is a valid pointer which has not been +registered as a <tt>__weak</tt> object.</p> +<p><tt>dest</tt> is initialized to be equivalent to <tt>src</tt>, +potentially registering it with the runtime. <tt>src</tt> may then be +left in its original state, in which case this call is equivalent +to <a href="#runtime.objc_copyWeak"><tt>objc_copyWeak</tt></a>, or it +may be left as null.</p> +<p>Must be atomic with respect to calls to <tt>objc_storeWeak</tt> +on <tt>src</tt>.</p> +</div> <!-- runtime.objc_moveWeak --> + +<div id="runtime.objc_release"> +<h1><tt>void objc_release(id value);</tt></h1> +<p><i>Precondition:</i> <tt>value</tt> is null or a pointer to a +valid object.</p> +<p>If <tt>value</tt> is null, this call has no effect. Otherwise, it +performs a release operation exactly as if the object had been sent +the <tt>release</tt> message.</p> +</div> <!-- runtime.objc_release --> + +<div id="runtime.objc_retain"> +<h1><tt>id objc_retain(id value);</tt></h1> +<p><i>Precondition:</i> <tt>value</tt> is null or a pointer to a +valid object.</p> +<p>If <tt>value</tt> is null, this call has no effect. Otherwise, it +performs a retain operation exactly as if the object had been sent +the <tt>retain</tt> message.</p> +<p>Always returns <tt>value</tt>.</p> +</div> <!-- runtime.objc_retain --> + +<div id="runtime.objc_retainAutorelease"> +<h1><tt>id objc_retainAutorelease(id value);</tt></h1> +<p><i>Precondition:</i> <tt>value</tt> is null or a pointer to a +valid object.</p> +<p>If <tt>value</tt> is null, this call has no effect. Otherwise, it +performs a retain operation followed by an autorelease operation. +Equivalent to the following code:</p> +<pre>id objc_retainAutorelease(id value) { + return objc_autorelease(objc_retain(value)); +}</pre> +<p>Always returns <tt>value</tt>.</p> +</div> <!-- runtime.objc_retainAutorelease --> + +<div id="runtime.objc_retainAutoreleaseReturnValue"> +<h1><tt>id objc_retainAutoreleaseReturnValue(id value);</tt></h1> +<p><i>Precondition:</i> <tt>value</tt> is null or a pointer to a +valid object.</p> +<p>If <tt>value</tt> is null, this call has no effect. Otherwise, it +performs a retain operation followed by the operation described in +<a href="#runtime.objc_autoreleaseReturnValue"><tt>objc_autoreleaseReturnValue</tt></a>. +Equivalent to the following code:</p> +<pre>id objc_retainAutoreleaseReturnValue(id value) { + return objc_autoreleaseReturnValue(objc_retain(value)); +}</pre> +<p>Always returns <tt>value</tt>.</p> +</div> <!-- runtime.objc_retainAutoreleaseReturnValue --> + +<div id="runtime.objc_retainAutoreleasedReturnValue"> +<h1><tt>id objc_retainAutoreleasedReturnValue(id value);</tt></h1> +<p><i>Precondition:</i> <tt>value</tt> is null or a pointer to a +valid object.</p> +<p>If <tt>value</tt> is null, this call has no effect. Otherwise, it +attempts to accept a hand off of a retain count from a call to +<a href="#runtime.objc_autoreleaseReturnValue"><tt>objc_autoreleaseReturnValue</tt></a> +on <tt>value</tt> in a recently-called function or something it +calls. If that fails, it performs a retain operation exactly +like <a href="#runtime.objc_retain"><tt>objc_retain</tt></a>.</p> +<p>Always returns <tt>value</tt>.</p> +</div> <!-- runtime.objc_retainAutoreleasedReturnValue --> + +<div id="runtime.objc_retainBlock"> +<h1><tt>id objc_retainBlock(id value);</tt></h1> +<p><i>Precondition:</i> <tt>value</tt> is null or a pointer to a +valid block object.</p> +<p>If <tt>value</tt> is null, this call has no effect. Otherwise, if +the block pointed to by <tt>value</tt> is still on the stack, it is +copied to the heap and the address of the copy is returned. Otherwise +a retain operation is performed on the block exactly as if it had been +sent the <tt>retain</tt> message.</p> +</div> <!-- runtime.objc_retainBlock --> + +<div id="runtime.objc_storeStrong"> +<h1><tt>id objc_storeStrong(id *object, id value);</tt></h1> +<p><i>Precondition:</i> <tt>object</tt> is a valid pointer to +a <tt>__strong</tt> object which is adequately aligned for a +pointer. <tt>value</tt> is null or a pointer to a valid object.</p> +<p>Performs the complete sequence for assigning to a <tt>__strong</tt> +object of non-block type. Equivalent to the following code:</p> +<pre>id objc_storeStrong(id *object, id value) { + value = [value retain]; + id oldValue = *object; + *object = value; + [oldValue release]; + return value; +}</pre> +<p>Always returns <tt>value</tt>.</p> +</div> <!-- runtime.objc_storeStrong --> + +<div id="runtime.objc_storeWeak"> +<h1><tt>id objc_storeWeak(id *object, id value);</tt></h1> +<p><i>Precondition:</i> <tt>object</tt> is a valid pointer which +either contains a null pointer or has been registered as +a <tt>__weak</tt> object. <tt>value</tt> is null or a pointer to a +valid object.</p> +<p>If <tt>value</tt> is a null pointer or the object to which it +points has begun deallocation, <tt>object</tt> is assigned null +and unregistered as a <tt>__weak</tt> object. Otherwise, +<tt>object</tt> is registered as a <tt>__weak</tt> object or has its +registration updated to point to <tt>value</tt>.</p> +<p>Returns the value of <tt>object</tt> after the call.</p> +</div> <!-- runtime.objc_storeWeak --> + +</div> <!-- runtime --> +</div> <!-- root --> +</body> +</html> diff --git a/docs/Block-ABI-Apple.txt b/docs/Block-ABI-Apple.txt index 4a97aa9bd65e..661ed50594de 100644 --- a/docs/Block-ABI-Apple.txt +++ b/docs/Block-ABI-Apple.txt @@ -317,7 +317,7 @@ would be rewritten to be: int flags; //refcount; int size; int captured_i; - } i = { NULL, &i, 0, sizeof(struct _block_byref_i), 11 }; + } i = { NULL, &i, 0, sizeof(struct _block_byref_i), 10 }; i.forwarding->captured_i = 11; @@ -476,7 +476,7 @@ struct _block_byref_obj { int size; void (*byref_keep)(struct _block_byref_i *dst, struct _block_byref_i *src); void (*byref_dispose)(struct _block_byref_i *); - int captured_obj; + id captured_obj; }; void _block_byref_obj_keep(struct _block_byref_voidBlock *dst, struct _block_byref_voidBlock *src) { diff --git a/docs/BlockLanguageSpec.txt b/docs/BlockLanguageSpec.txt index a612fd28892b..f7bbda365184 100644 --- a/docs/BlockLanguageSpec.txt +++ b/docs/BlockLanguageSpec.txt @@ -151,7 +151,7 @@ For example, given class Foo with member function fighter(void): ...a Block that used foo would import the variables as const variations: const Foo block_foo = foo; // const copy constructor const Foo &block_fooRef = fooRef; - const Foo *block_fooPtr = fooPtr; + Foo *const block_fooPtr = fooPtr; Stack-local objects are copied into a Block via a copy const constructor. If no such constructor exists, it is considered an error to reference such objects from within the Block compound statements. A destructor is run as control leaves the compound statement that contains the Block literal expression. diff --git a/docs/DriverInternals.html b/docs/DriverInternals.html index 4f5f0ae112f9..380de9909af0 100644 --- a/docs/DriverInternals.html +++ b/docs/DriverInternals.html @@ -405,7 +405,7 @@ to each compilation sequence. For example, the list of used temporary files (which must be removed once compilation is finished) and result files (which should be removed if - compilation files).</p> + compilation fails).</p> <h4 id="int_unified_parsing">Unified Parsing & Pipelining</h4> diff --git a/docs/InternalsManual.html b/docs/InternalsManual.html index 961198938f20..5d97609373b7 100644 --- a/docs/InternalsManual.html +++ b/docs/InternalsManual.html @@ -68,7 +68,6 @@ td { <li><a href="#Constants">Constant Folding in the Clang AST</a></li> </ul> </li> -<li><a href="libIndex.html">The Index Library</a></li> <li><a href="#Howtos">Howto guides</a> <ul> <li><a href="#AddingAttributes">How to add an attribute</a></li> @@ -1213,8 +1212,8 @@ void g(); void g(int); </pre> <p>the <code>DeclContext::lookup</code> operation will return - an <code>OverloadedFunctionDecl</code> that contains both - declarations of "g". Clients that perform semantic analysis on a + a <code>DeclContext::lookup_result</code> that contains a range of iterators + over declarations of "g". Clients that perform semantic analysis on a program that is not concerned with the actual source code will primarily use this semantics-centric view.</p> @@ -1396,8 +1395,8 @@ namespace N { nodes in Snippet #1, each of which is a declaration context that contains a single declaration of "f". However, the semantics-centric view provided by name lookup into the namespace <code>N</code> for - "f" will return an <code>OverloadedFunctionDecl</code> that contains - both declarations of "f".</p> + "f" will return a <code>DeclContext::lookup_result</code> that contains + a range of iterators over declarations of "f".</p> <p><code>DeclContext</code> manages multiply-defined declaration contexts internally. The diff --git a/docs/LanguageExtensions.html b/docs/LanguageExtensions.html index 8f43725d82a2..7ee8f010a32b 100644 --- a/docs/LanguageExtensions.html +++ b/docs/LanguageExtensions.html @@ -1,13 +1,17 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" + "http://www.w3.org/TR/html4/strict.dtd"> +<!-- Material used from: HTML 4.01 specs: http://www.w3.org/TR/html401/ --> <html> <head> -<title>Clang Language Extensions</title> -<link type="text/css" rel="stylesheet" href="../menu.css" /> -<link type="text/css" rel="stylesheet" href="../content.css" /> -<style type="text/css"> -td { - vertical-align: top; -} -</style> + <META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> + <title>Clang LanguageExtensions</title> + <link type="text/css" rel="stylesheet" href="../menu.css"> + <link type="text/css" rel="stylesheet" href="../content.css"> + <style type="text/css"> + td { + vertical-align: top; + } + </style> </head> <body> @@ -25,12 +29,12 @@ td { <li><a href="#vectors">Vectors and Extended Vectors</a></li> <li><a href="#deprecated">Messages on <tt>deprecated</tt> and <tt>unavailable</tt> attributes</a></li> <li><a href="#attributes-on-enumerators">Attributes on enumerators</a></li> -<li><a href="#checking_language_features">Checks for Standard Language Features</a></li> +<li><a href="#checking_language_features">Checks for Standard Language Features</a> <ul> <li><a href="#cxx_exceptions">C++ exceptions</a></li> <li><a href="#cxx_rtti">C++ RTTI</a></li> - </ul> -<li><a href="#checking_upcoming_features">Checks for Upcoming Standard Language Features</a></li> + </ul></li> +<li><a href="#checking_upcoming_features">Checks for Upcoming Standard Language Features</a> <ul> <li><a href="#cxx0x">C++0x</a> <ul> @@ -39,6 +43,7 @@ td { <li><a href="#cxx_alias_templates">C++0x alias templates</a></li> <li><a href="#cxx_attributes">C++0x attributes</a></li> <li><a href="#cxx_default_function_template_args">C++0x default template arguments in function templates</a></li> + <li><a href="#cxx_delegating_constructor">C++0x delegating constructors</a></li> <li><a href="#cxx_deleted_functions">C++0x deleted functions</a></li> <li><a href="#cxx_lambdas">C++0x lambdas</a></li> <li><a href="#cxx_nullptr">C++0x nullptr</a></li> @@ -53,18 +58,19 @@ td { <li><a href="#cxx_strong_enums">C++0x strongly-typed enumerations</a></li> <li><a href="#cxx_trailing_return">C++0x trailing return type</a></li> <li><a href="#cxx_noexcept">C++0x noexcept specification</a></li> - </ul> + </ul></li> <li><a href="#c1x">C1X</a> <ul> <li><a href="#c_generic_selections">C1X generic selections</a></li> <li><a href="#c_static_assert">C1X <tt>_Static_assert()</tt></a></li> - </ul> - </ul> + </ul></li> + </ul> </li> <li><a href="#checking_type_traits">Checks for Type Traits</a></li> <li><a href="#blocks">Blocks</a></li> <li><a href="#objc_features">Objective-C Features</a> <ul> <li><a href="#objc_instancetype">Related result types</a></li> + <li><a href="#objc_arc">Automatic reference counting</a></li> </ul> </li> <li><a href="#overloading-in-c">Function Overloading in C</a></li> @@ -104,7 +110,7 @@ code without having to resort to something like autoconf or fragile "compiler version checks".</p> <!-- ======================================================================= --> -<h3 id="__has_builtin">__has_builtin</h3> +<h3><a name="__has_builtin">__has_builtin</a></h3> <!-- ======================================================================= --> <p>This function-like macro takes a single identifier argument that is the name @@ -129,7 +135,7 @@ not. It can be used like this:</p> <!-- ======================================================================= --> -<h3 id="__has_feature_extension">__has_feature and __has_extension</h3> +<h3><a name="__has_feature_extension"> __has_feature and __has_extension</a></h3> <!-- ======================================================================= --> <p>These function-like macros take a single identifier argument that is the @@ -174,7 +180,7 @@ non-standardized features, i.e. features not prefixed <code>c_</code>, <p>The feature tag is described along with the language feature below.</p> <!-- ======================================================================= --> -<h3 id="__has_attribute">__has_attribute</h3> +<h3><a name="__has_attribute">__has_attribute</a></h3> <!-- ======================================================================= --> <p>This function-like macro takes a single identifier argument that is the name @@ -208,7 +214,7 @@ check for the existence of an include file before doing a possibly failing #include directive.</p> <!-- ======================================================================= --> -<h3 id="__has_include">__has_include</h3> +<h3><a name="__has_include">__has_include</a></h3> <!-- ======================================================================= --> <p>This function-like macro takes a single file name string argument that @@ -218,12 +224,12 @@ be found using the include paths, or 0 otherwise:</p> <blockquote> <pre> // Note the two possible file name string formats. -#if __has_include("myinclude.h") && __has_include(<stdint.h>) +#if __has_include("myinclude.h") && __has_include(<stdint.h>) # include "myinclude.h" #endif // To avoid problem with non-clang compilers not having this macro. -#if defined(__has_include) && __has_include("myinclude.h") +#if defined(__has_include) && __has_include("myinclude.h") # include "myinclude.h" #endif </pre> @@ -232,7 +238,7 @@ be found using the include paths, or 0 otherwise:</p> <p>To test for this feature, use #if defined(__has_include).</p> <!-- ======================================================================= --> -<h3 id="__has_include_next">__has_include_next</h3> +<h3><a name="__has_include_next">__has_include_next</a></h3> <!-- ======================================================================= --> <p>This function-like macro takes a single file name string argument that @@ -244,12 +250,12 @@ be found using the include paths, or 0 otherwise:</p> <blockquote> <pre> // Note the two possible file name string formats. -#if __has_include_next("myinclude.h") && __has_include_next(<stdint.h>) +#if __has_include_next("myinclude.h") && __has_include_next(<stdint.h>) # include_next "myinclude.h" #endif // To avoid problem with non-clang compilers not having this macro. -#if defined(__has_include_next) && __has_include_next("myinclude.h") +#if defined(__has_include_next) && __has_include_next("myinclude.h") # include_next "myinclude.h" #endif </pre> @@ -410,115 +416,120 @@ noted.</p> C++0x standard. As a result, all these features are enabled with the <tt>-std=c++0x</tt> option when compiling C++ code.</p> -<h4 id="cxx_decltype">C++0x <tt>decltype()</tt></h3> +<h4 id="cxx_decltype">C++0x <tt>decltype()</tt></h4> <p>Use <tt>__has_feature(cxx_decltype)</tt> or <tt>__has_extension(cxx_decltype)</tt> to determine if support for the <tt>decltype()</tt> specifier is enabled.</p> -<h4 id="cxx_access_control_sfinae">C++0x SFINAE includes access control</h3> +<h4 id="cxx_access_control_sfinae">C++0x SFINAE includes access control</h4> <p>Use <tt>__has_feature(cxx_access_control_sfinae)</tt> or <tt>__has_extension(cxx_access_control_sfinae)</tt> to determine whether access-control errors (e.g., calling a private constructor) are considered to be template argument deduction errors (aka SFINAE errors), per <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1170">C++ DR1170</a>.</p> -<h4 id="cxx_alias_templates">C++0x alias templates</h3> +<h4 id="cxx_alias_templates">C++0x alias templates</h4> <p>Use <tt>__has_feature(cxx_alias_templates)</tt> or <tt>__has_extension(cxx_alias_templates)</tt> to determine if support for C++0x's alias declarations and alias templates is enabled.</p> -<h4 id="cxx_attributes">C++0x attributes</h3> +<h4 id="cxx_attributes">C++0x attributes</h4> <p>Use <tt>__has_feature(cxx_attributes)</tt> or <tt>__has_extension(cxx_attributes)</tt> to determine if support for attribute parsing with C++0x's square bracket notation is enabled.</p> -<h4 id="cxx_default_function_template_args">C++0x default template arguments in function templates</h3> +<h4 id="cxx_default_function_template_args">C++0x default template arguments in function templates</h4> <p>Use <tt>__has_feature(cxx_default_function_template_args)</tt> or <tt>__has_extension(cxx_default_function_template_args)</tt> to determine if support for default template arguments in function templates is enabled.</p> -<h4 id="cxx_deleted_functions">C++0x deleted functions</tt></h3> +<h4 id="cxx_delegating_constructors">C++0x delegating constructors</h4> + +<p>Use <tt>__has_feature(cxx_delegating_constructors)</tt> to determine if +support for delegating constructors is enabled.</p> + +<h4 id="cxx_deleted_functions">C++0x <tt>delete</tt>d functions</h4> <p>Use <tt>__has_feature(cxx_deleted_functions)</tt> or <tt>__has_extension(cxx_deleted_functions)</tt> to determine if support for deleted function definitions (with <tt>= delete</tt>) is enabled.</p> -<h4 id="cxx_lambdas">C++0x lambdas</h3> +<h4 id="cxx_lambdas">C++0x lambdas</h4> <p>Use <tt>__has_feature(cxx_lambdas)</tt> or <tt>__has_extension(cxx_lambdas)</tt> to determine if support for lambdas is enabled. clang does not currently implement this feature.</p> -<h4 id="cxx_nullptr">C++0x <tt>nullptr</tt></h3> +<h4 id="cxx_nullptr">C++0x <tt>nullptr</tt></h4> <p>Use <tt>__has_feature(cxx_nullptr)</tt> or <tt>__has_extension(cxx_nullptr)</tt> to determine if support for <tt>nullptr</tt> is enabled.</p> -<h4 id="cxx_override_control">C++0x <tt>override control</tt></h3> +<h4 id="cxx_override_control">C++0x <tt>override control</tt></h4> <p>Use <tt>__has_feature(cxx_override_control)</tt> or <tt>__has_extension(cxx_override_control)</tt> to determine if support for the override control keywords is enabled.</p> -<h4 id="cxx_reference_qualified_functions">C++0x reference-qualified functions</h3> +<h4 id="cxx_reference_qualified_functions">C++0x reference-qualified functions</h4> <p>Use <tt>__has_feature(cxx_reference_qualified_functions)</tt> or <tt>__has_extension(cxx_reference_qualified_functions)</tt> to determine if support for reference-qualified functions (e.g., member functions with <code>&</code> or <code>&&</code> applied to <code>*this</code>) is enabled.</p> -<h4 id="cxx_range_for">C++0x range-based for loop</tt></h3> +<h4 id="cxx_range_for">C++0x range-based <tt>for</tt> loop</h4> <p>Use <tt>__has_feature(cxx_range_for)</tt> or <tt>__has_extension(cxx_range_for)</tt> to determine if support for the range-based for loop is enabled. </p> -<h4 id="cxx_rvalue_references">C++0x rvalue references</tt></h3> +<h4 id="cxx_rvalue_references">C++0x rvalue references</h4> <p>Use <tt>__has_feature(cxx_rvalue_references)</tt> or <tt>__has_extension(cxx_rvalue_references)</tt> to determine if support for rvalue references is enabled. </p> -<h4 id="cxx_static_assert">C++0x <tt>static_assert()</tt></h3> +<h4 id="cxx_static_assert">C++0x <tt>static_assert()</tt></h4> <p>Use <tt>__has_feature(cxx_static_assert)</tt> or <tt>__has_extension(cxx_static_assert)</tt> to determine if support for compile-time assertions using <tt>static_assert</tt> is enabled.</p> -<h4 id="cxx_auto_type">C++0x type inference</h3> +<h4 id="cxx_auto_type">C++0x type inference</h4> <p>Use <tt>__has_feature(cxx_auto_type)</tt> or <tt>__has_extension(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.</p> -<h4 id="cxx_variadic_templates">C++0x variadic templates</h3> +<h4 id="cxx_variadic_templates">C++0x variadic templates</h4> <p>Use <tt>__has_feature(cxx_variadic_templates)</tt> or <tt>__has_extension(cxx_variadic_templates)</tt> to determine if support for variadic templates is enabled.</p> -<h4 id="cxx_inline_namespaces">C++0x inline namespaces</h3> +<h4 id="cxx_inline_namespaces">C++0x inline namespaces</h4> <p>Use <tt>__has_feature(cxx_inline_namespaces)</tt> or <tt>__has_extension(cxx_inline_namespaces)</tt> to determine if support for inline namespaces is enabled.</p> -<h4 id="cxx_trailing_return">C++0x trailing return type</h3> +<h4 id="cxx_trailing_return">C++0x trailing return type</h4> <p>Use <tt>__has_feature(cxx_trailing_return)</tt> or <tt>__has_extension(cxx_trailing_return)</tt> to determine if support for the alternate function declaration syntax with trailing return type is enabled.</p> -<h4 id="cxx_noexcept">C++0x noexcept</h3> +<h4 id="cxx_noexcept">C++0x noexcept</h4> <p>Use <tt>__has_feature(cxx_noexcept)</tt> or <tt>__has_extension(cxx_noexcept)</tt> to determine if support for noexcept exception specifications is enabled.</p> -<h4 id="cxx_strong_enums">C++0x strongly typed enumerations</h3> +<h4 id="cxx_strong_enums">C++0x strongly typed enumerations</h4> <p>Use <tt>__has_feature(cxx_strong_enums)</tt> or <tt>__has_extension(cxx_strong_enums)</tt> to determine if support for @@ -530,7 +541,7 @@ strongly typed, scoped enumerations is enabled.</p> C1X standard. As a result, all these features are enabled with the <tt>-std=c1x</tt> option when compiling C code.</p> -<h4 id="c_generic_selections">C1X generic selections</h2> +<h4 id="c_generic_selections">C1X generic selections</h4> <p>Use <tt>__has_feature(c_generic_selections)</tt> or <tt>__has_extension(c_generic_selections)</tt> to determine if support for @@ -544,7 +555,7 @@ C1X draft standard.</p> appropriate standard, but in C++, which lacks the type compatibility rules used in C, types are considered compatible only if they are equivalent.</p> -<h4 id="c_static_assert">C1X <tt>_Static_assert()</tt></h3> +<h4 id="c_static_assert">C1X <tt>_Static_assert()</tt></h4> <p>Use <tt>__has_feature(c_static_assert)</tt> or <tt>__has_extension(c_static_assert)</tt> to determine if support for @@ -554,7 +565,7 @@ compile-time assertions using <tt>_Static_assert</tt> is enabled.</p> <h2 id="checking_type_traits">Checks for Type Traits</h2> <!-- ======================================================================= --> -<p>Clang supports the <a hef="http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html">GNU C++ type traits</a> and a subset of the <a href="http://msdn.microsoft.com/en-us/library/ms177194(v=VS.100).aspx">Microsoft Visual C++ Type traits</a>. For each supported type trait <code>__X</code>, <code>__has_extension(X)</code> indicates the presence of the type trait. For example: +<p>Clang supports the <a href="http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html">GNU C++ type traits</a> and a subset of the <a href="http://msdn.microsoft.com/en-us/library/ms177194(v=VS.100).aspx">Microsoft Visual C++ Type traits</a>. For each supported type trait <code>__X</code>, <code>__has_extension(X)</code> indicates the presence of the type trait. For example: <blockquote> <pre> #if __has_extension(is_convertible_to) @@ -640,7 +651,7 @@ to have the type <code>NSArray *</code>. If neither <code>alloc</code> nor <code <p>To determine whether a method has a related result type, the first word in the camel-case selector (e.g., "init" in "initWithObjects") is considered, and the method will a related result type if its return -type is compatible with the type of its class and if +type is compatible with the type of its class and if</p> <ul> @@ -650,7 +661,7 @@ type is compatible with the type of its class and if <li>the first word is "autorelease", "init", "retain", or "self", and the method is an instance method.</li> -</ul></p> +</ul> <p>If a method with a related result type is overridden by a subclass method, the subclass method must also return a type that is compatible @@ -670,6 +681,12 @@ with a related result type is treated the same way as method without a related result type.</p> <!-- ======================================================================= --> +<h2 id="objc_arc">Automatic reference counting </h2> +<!-- ======================================================================= --> + +<p>Clang provides support for <a href="AutomaticReferenceCounting.html">automated reference counting</a> in Objective-C, which eliminates the need for manual retain/release/autorelease message sends. There are two feature macros associated with automatic reference counting: <code>__has_feature(objc_arc)</code> indicates the availability of automated reference counting in general, while <code>__has_feature(objc_arc_weak)</code> indicates that automated reference counting also includes support for <code>__weak</code> pointers to Objective-C objects.</p> + +<!-- ======================================================================= --> <h2 id="overloading-in-c">Function Overloading in C</h2> <!-- ======================================================================= --> @@ -790,7 +807,7 @@ vector support</a> instead of builtins, in order to reduce the number of builtins that we need to implement.</p> <!-- ======================================================================= --> -<h3 id="__builtin_shufflevector">__builtin_shufflevector</h3> +<h3><a name="__builtin_shufflevector">__builtin_shufflevector</a></h3> <!-- ======================================================================= --> <p><tt>__builtin_shufflevector</tt> is used to express generic vector @@ -842,7 +859,7 @@ the number of indices specified. <p>Query for this feature with __has_builtin(__builtin_shufflevector).</p> <!-- ======================================================================= --> -<h3 id="__builtin_unreachable">__builtin_unreachable</h3> +<h3><a name="__builtin_unreachable">__builtin_unreachable</a></h3> <!-- ======================================================================= --> <p><tt>__builtin_unreachable</tt> is used to indicate that a specific point in @@ -880,7 +897,7 @@ no arguments and produces a void result. <p>Query for this feature with __has_builtin(__builtin_unreachable).</p> <!-- ======================================================================= --> -<h3 id="__sync_swap">__sync_swap</h3> +<h3><a name="__sync_swap">__sync_swap</a></h3> <!-- ======================================================================= --> <p><tt>__sync_swap</tt> is used to atomically swap integers or pointers in @@ -896,7 +913,7 @@ memory. <p><b>Example of Use:</b></p> <pre> -int old_value = __sync_swap(&value, new_value); +int old_value = __sync_swap(&value, new_value); </pre> <p><b>Description:</b></p> diff --git a/docs/UsersManual.html b/docs/UsersManual.html index 4962a9211066..639892714ef8 100644 --- a/docs/UsersManual.html +++ b/docs/UsersManual.html @@ -846,6 +846,10 @@ variants "__asm__" and "__typeof__" are recognized in all modes.</li> <li>The Apple "blocks" extension is recognized by default in gnu* modes on some platforms; it can be enabled in any mode with the "-fblocks" option.</li> +<li>Arrays that are VLA's according to the standard, but which can be constant + folded by the frontend are treated as fixed size arrays. This occurs for + things like "int X[(1, 2)];", which is technically a VLA. c* modes are + strictly compliant and treat these as VLAs.</li> </ul> <p>Differences between *89 and *99 modes:</p> @@ -882,11 +886,6 @@ extensions are not implemented yet:</p> the uses described in the bug, this is likely to be implemented at some point, at least partially.</li> -<li>clang does not support code generation for local variables pinned to -registers (<a href="http://llvm.org/bugs/show_bug.cgi?id=3933">bug 3933</a>). -This is a relatively small feature, so it is likely to be implemented -relatively soon.</li> - <li>clang does not support decimal floating point types (_Decimal32 and friends) or fixed-point types (_Fract and friends); nobody has expressed interest in these features yet, so it's hard to say when they will be @@ -937,16 +936,9 @@ extension appears to be rarely used. Note that clang <em>does</em> support flexible array members (arrays with a zero or unspecified size at the end of a structure).</li> -<li>clang does not support duplicate definitions of a function where one is -inline. This complicates clients of the AST which normally can expect there is -at most one definition for each function. Source code using this feature should -be changed to define the inline and out-of-line definitions in separate -translation units.</li> - <li>clang does not have an equivalent to gcc's "fold"; this means that clang doesn't accept some constructs gcc might accept in contexts where a -constant expression is required, like "x-x" where x is a variable, or calls -to C library functions like strlen.</li> +constant expression is required, like "x-x" where x is a variable.</li> <li>clang does not support multiple alternative constraints in inline asm; this is an extremely obscure feature which would be complicated to implement diff --git a/docs/index.html b/docs/index.html deleted file mode 100644 index d741b68a4160..000000000000 --- a/docs/index.html +++ /dev/null @@ -1,4 +0,0 @@ -<title>'clang' C frontend documentation</title> - -None yet, sorry :( - diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h index cb0b3c1babcb..4852ded7f883 100644 --- a/include/clang-c/Index.h +++ b/include/clang-c/Index.h @@ -833,14 +833,24 @@ enum CXTranslationUnit_Flags { /** * \brief Used to indicate that the "detailed" preprocessing record, - * if requested, should also contain nested macro instantiations. + * if requested, should also contain nested macro expansions. * - * Nested macro instantiations (i.e., macro instantiations that occur - * inside another macro instantiation) can, in some code bases, require + * Nested macro expansions (i.e., macro expansions that occur + * inside another macro expansion) can, in some code bases, require * a large amount of storage to due preprocessor metaprogramming. Moreover, * its fairly rare that this information is useful for libclang clients. */ - CXTranslationUnit_NestedMacroInstantiations = 0x40 + CXTranslationUnit_NestedMacroExpansions = 0x40, + + /** + * \brief Legacy name to indicate that the "detailed" preprocessing record, + * if requested, should contain nested macro expansions. + * + * \see CXTranslationUnit_NestedMacroExpansions for the current name for this + * value, and its semantics. This is just an alias. + */ + CXTranslationUnit_NestedMacroInstantiations = + CXTranslationUnit_NestedMacroExpansions }; /** @@ -933,6 +943,41 @@ enum CXSaveTranslationUnit_Flags { CINDEX_LINKAGE unsigned clang_defaultSaveOptions(CXTranslationUnit TU); /** + * \brief Describes the kind of error that occurred (if any) in a call to + * \c clang_saveTranslationUnit(). + */ +enum CXSaveError { + /** + * \brief Indicates that no error occurred while saving a translation unit. + */ + CXSaveError_None = 0, + + /** + * \brief Indicates that an unknown error occurred while attempting to save + * the file. + * + * This error typically indicates that file I/O failed when attempting to + * write the file. + */ + CXSaveError_Unknown = 1, + + /** + * \brief Indicates that errors during translation prevented this attempt + * to save the translation unit. + * + * Errors that prevent the translation unit from being saved can be + * extracted using \c clang_getNumDiagnostics() and \c clang_getDiagnostic(). + */ + CXSaveError_TranslationErrors = 2, + + /** + * \brief Indicates that the translation unit to be saved was somehow + * invalid (e.g., NULL). + */ + CXSaveError_InvalidTU = 3 +}; + +/** * \brief Saves a translation unit into a serialized representation of * that translation unit on disk. * @@ -951,8 +996,9 @@ CINDEX_LINKAGE unsigned clang_defaultSaveOptions(CXTranslationUnit TU); * is saved. This should be a bitwise OR of the * CXSaveTranslationUnit_XXX flags. * - * \returns Zero if the translation unit was saved successfully, a - * non-zero value otherwise. + * \returns A value that will match one of the enumerators of the CXSaveError + * enumeration. Zero (CXSaveError_None) indicates that the translation unit was + * saved successfully, while a non-zero value indicates that a problem occurred. */ CINDEX_LINKAGE int clang_saveTranslationUnit(CXTranslationUnit TU, const char *FileName, @@ -1385,7 +1431,8 @@ enum CXCursorKind { /* Preprocessing */ CXCursor_PreprocessingDirective = 500, CXCursor_MacroDefinition = 501, - CXCursor_MacroInstantiation = 502, + CXCursor_MacroExpansion = 502, + CXCursor_MacroInstantiation = CXCursor_MacroExpansion, CXCursor_InclusionDirective = 503, CXCursor_FirstPreprocessing = CXCursor_PreprocessingDirective, CXCursor_LastPreprocessing = CXCursor_InclusionDirective @@ -1474,6 +1521,11 @@ CINDEX_LINKAGE unsigned clang_isExpression(enum CXCursorKind); CINDEX_LINKAGE unsigned clang_isStatement(enum CXCursorKind); /** + * \brief Determine whether the given cursor kind represents an attribute. + */ +CINDEX_LINKAGE unsigned clang_isAttribute(enum CXCursorKind); + +/** * \brief Determine whether the given cursor kind represents an invalid * cursor. */ @@ -2830,6 +2882,137 @@ enum CXCodeComplete_Flags { }; /** + * \brief Bits that represent the context under which completion is occurring. + * + * The enumerators in this enumeration may be bitwise-OR'd together if multiple + * contexts are occurring simultaneously. + */ +enum CXCompletionContext { + /** + * \brief The context for completions is unexposed, as only Clang results + * should be included. (This is equivalent to having no context bits set.) + */ + CXCompletionContext_Unexposed = 0, + + /** + * \brief Completions for any possible type should be included in the results. + */ + CXCompletionContext_AnyType = 1 << 0, + + /** + * \brief Completions for any possible value (variables, function calls, etc.) + * should be included in the results. + */ + CXCompletionContext_AnyValue = 1 << 1, + /** + * \brief Completions for values that resolve to an Objective-C object should + * be included in the results. + */ + CXCompletionContext_ObjCObjectValue = 1 << 2, + /** + * \brief Completions for values that resolve to an Objective-C selector + * should be included in the results. + */ + CXCompletionContext_ObjCSelectorValue = 1 << 3, + /** + * \brief Completions for values that resolve to a C++ class type should be + * included in the results. + */ + CXCompletionContext_CXXClassTypeValue = 1 << 4, + + /** + * \brief Completions for fields of the member being accessed using the dot + * operator should be included in the results. + */ + CXCompletionContext_DotMemberAccess = 1 << 5, + /** + * \brief Completions for fields of the member being accessed using the arrow + * operator should be included in the results. + */ + CXCompletionContext_ArrowMemberAccess = 1 << 6, + /** + * \brief Completions for properties of the Objective-C object being accessed + * using the dot operator should be included in the results. + */ + CXCompletionContext_ObjCPropertyAccess = 1 << 7, + + /** + * \brief Completions for enum tags should be included in the results. + */ + CXCompletionContext_EnumTag = 1 << 8, + /** + * \brief Completions for union tags should be included in the results. + */ + CXCompletionContext_UnionTag = 1 << 9, + /** + * \brief Completions for struct tags should be included in the results. + */ + CXCompletionContext_StructTag = 1 << 10, + + /** + * \brief Completions for C++ class names should be included in the results. + */ + CXCompletionContext_ClassTag = 1 << 11, + /** + * \brief Completions for C++ namespaces and namespace aliases should be + * included in the results. + */ + CXCompletionContext_Namespace = 1 << 12, + /** + * \brief Completions for C++ nested name specifiers should be included in + * the results. + */ + CXCompletionContext_NestedNameSpecifier = 1 << 13, + + /** + * \brief Completions for Objective-C interfaces (classes) should be included + * in the results. + */ + CXCompletionContext_ObjCInterface = 1 << 14, + /** + * \brief Completions for Objective-C protocols should be included in + * the results. + */ + CXCompletionContext_ObjCProtocol = 1 << 15, + /** + * \brief Completions for Objective-C categories should be included in + * the results. + */ + CXCompletionContext_ObjCCategory = 1 << 16, + /** + * \brief Completions for Objective-C instance messages should be included + * in the results. + */ + CXCompletionContext_ObjCInstanceMessage = 1 << 17, + /** + * \brief Completions for Objective-C class messages should be included in + * the results. + */ + CXCompletionContext_ObjCClassMessage = 1 << 18, + /** + * \brief Completions for Objective-C selector names should be included in + * the results. + */ + CXCompletionContext_ObjCSelectorName = 1 << 19, + + /** + * \brief Completions for preprocessor macro names should be included in + * the results. + */ + CXCompletionContext_MacroName = 1 << 20, + + /** + * \brief Natural language completions should be included in the results. + */ + CXCompletionContext_NaturalLanguage = 1 << 21, + + /** + * \brief The current context is unknown, so set all contexts. + */ + CXCompletionContext_Unknown = ((1 << 22) - 1) +}; + +/** * \brief Returns a default set of code-completion options that can be * passed to\c clang_codeCompleteAt(). */ @@ -2950,6 +3133,19 @@ CXDiagnostic clang_codeCompleteGetDiagnostic(CXCodeCompleteResults *Results, unsigned Index); /** + * \brief Determines what compeltions are appropriate for the context + * the given code completion. + * + * \param Results the code completion results to query + * + * \returns the kinds of completions that are appropriate for use + * along with the given code completion results. + */ +CINDEX_LINKAGE +unsigned long long clang_codeCompleteGetContexts( + CXCodeCompleteResults *Results); + +/** * @} */ @@ -3005,6 +3201,51 @@ CINDEX_LINKAGE void clang_getInclusions(CXTranslationUnit tu, * @} */ +/** \defgroup CINDEX_REMAPPING Remapping functions + * + * @{ + */ + +/** + * \brief A remapping of original source files and their translated files. + */ +typedef void *CXRemapping; + +/** + * \brief Retrieve a remapping. + * + * \param path the path that contains metadata about remappings. + * + * \returns the requested remapping. This remapping must be freed + * via a call to \c clang_remap_dispose(). Can return NULL if an error occurred. + */ +CINDEX_LINKAGE CXRemapping clang_getRemappings(const char *path); + +/** + * \brief Determine the number of remappings. + */ +CINDEX_LINKAGE unsigned clang_remap_getNumFiles(CXRemapping); + +/** + * \brief Get the original and the associated filename from the remapping. + * + * \param original If non-NULL, will be set to the original filename. + * + * \param transformed If non-NULL, will be set to the filename that the original + * is associated with. + */ +CINDEX_LINKAGE void clang_remap_getFilenames(CXRemapping, unsigned index, + CXString *original, CXString *transformed); + +/** + * \brief Dispose the remapping. + */ +CINDEX_LINKAGE void clang_remap_dispose(CXRemapping); + +/** + * @} + */ + /** * @} */ diff --git a/include/clang/ARCMigrate/ARCMT.h b/include/clang/ARCMigrate/ARCMT.h new file mode 100644 index 000000000000..ad5cf4a2c16c --- /dev/null +++ b/include/clang/ARCMigrate/ARCMT.h @@ -0,0 +1,94 @@ +//===-- ARCMT.h - ARC Migration Rewriter ------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ARCMIGRATE_ARCMT_H +#define LLVM_CLANG_ARCMIGRATE_ARCMT_H + +#include "clang/ARCMigrate/FileRemapper.h" +#include "clang/Frontend/CompilerInvocation.h" + +namespace clang { + class ASTContext; + class DiagnosticClient; + +namespace arcmt { + class MigrationPass; + +/// \brief Creates an AST with the provided CompilerInvocation but with these +/// changes: +/// -if a PCH/PTH is set, the original header is used instead +/// -Automatic Reference Counting mode is enabled +/// +/// It then checks the AST and produces errors/warning for ARC migration issues +/// that the user needs to handle manually. +/// +/// \returns false if no error is produced, true otherwise. +bool checkForManualIssues(CompilerInvocation &CI, + llvm::StringRef Filename, InputKind Kind, + DiagnosticClient *DiagClient); + +/// \brief Works similar to checkForManualIssues but instead of checking, it +/// applies automatic modifications to source files to conform to ARC. +/// +/// \returns false if no error is produced, true otherwise. +bool applyTransformations(CompilerInvocation &origCI, + llvm::StringRef Filename, InputKind Kind, + DiagnosticClient *DiagClient); + +/// \brief Applies automatic modifications and produces temporary files +/// and metadata into the \arg outputDir path. +/// +/// \returns false if no error is produced, true otherwise. +bool migrateWithTemporaryFiles(CompilerInvocation &origCI, + llvm::StringRef Filename, InputKind Kind, + DiagnosticClient *DiagClient, + llvm::StringRef outputDir); + +/// \brief Get the set of file remappings from the \arg outputDir path that +/// migrateWithTemporaryFiles produced. +/// +/// \returns false if no error is produced, true otherwise. +bool getFileRemappings(std::vector<std::pair<std::string,std::string> > &remap, + llvm::StringRef outputDir, + DiagnosticClient *DiagClient); + +typedef void (*TransformFn)(MigrationPass &pass); + +std::vector<TransformFn> getAllTransformations(); + +class MigrationProcess { + CompilerInvocation OrigCI; + DiagnosticClient *DiagClient; + FileRemapper Remapper; + +public: + MigrationProcess(const CompilerInvocation &CI, DiagnosticClient *diagClient, + llvm::StringRef outputDir = llvm::StringRef()); + + class RewriteListener { + public: + virtual ~RewriteListener(); + + virtual void start(ASTContext &Ctx) { } + virtual void finish() { } + + virtual void insert(SourceLocation loc, llvm::StringRef text) { } + virtual void remove(CharSourceRange range) { } + }; + + bool applyTransform(TransformFn trans, RewriteListener *listener = 0); + + FileRemapper &getRemapper() { return Remapper; } +}; + +} // end namespace arcmt + +} // end namespace clang + +#endif diff --git a/include/clang/ARCMigrate/ARCMTActions.h b/include/clang/ARCMigrate/ARCMTActions.h new file mode 100644 index 000000000000..4c714f55b390 --- /dev/null +++ b/include/clang/ARCMigrate/ARCMTActions.h @@ -0,0 +1,47 @@ +//===--- ARCMTActions.h - ARC Migrate Tool Frontend Actions -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ARCMIGRATE_ARCMT_ACTION_H +#define LLVM_CLANG_ARCMIGRATE_ARCMT_ACTION_H + +#include "clang/Frontend/FrontendAction.h" +#include "llvm/ADT/OwningPtr.h" + +namespace clang { +namespace arcmt { + +class CheckAction : public WrapperFrontendAction { +protected: + virtual bool BeginInvocation(CompilerInstance &CI); + +public: + CheckAction(FrontendAction *WrappedAction); +}; + +class ModifyAction : public WrapperFrontendAction { +protected: + virtual bool BeginInvocation(CompilerInstance &CI); + +public: + ModifyAction(FrontendAction *WrappedAction); +}; + +class MigrateAction : public WrapperFrontendAction { + std::string MigrateDir; +protected: + virtual bool BeginInvocation(CompilerInstance &CI); + +public: + MigrateAction(FrontendAction *WrappedAction, llvm::StringRef migrateDir); +}; + +} +} + +#endif diff --git a/include/clang/ARCMigrate/FileRemapper.h b/include/clang/ARCMigrate/FileRemapper.h new file mode 100644 index 000000000000..809f6a5f71be --- /dev/null +++ b/include/clang/ARCMigrate/FileRemapper.h @@ -0,0 +1,76 @@ +//===-- FileRemapper.h - File Remapping Helper ------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ARCMIGRATE_FILEREMAPPER_H +#define LLVM_CLANG_ARCMIGRATE_FILEREMAPPER_H + +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/StringRef.h" + +namespace llvm { + class MemoryBuffer; +} + +namespace clang { + class FileManager; + class FileEntry; + class Diagnostic; + class CompilerInvocation; + +namespace arcmt { + +class FileRemapper { + // FIXME: Reuse the same FileManager for multiple ASTContexts. + llvm::OwningPtr<FileManager> FileMgr; + + typedef llvm::PointerUnion<const FileEntry *, llvm::MemoryBuffer *> Target; + typedef llvm::DenseMap<const FileEntry *, Target> MappingsTy; + MappingsTy FromToMappings; + + llvm::DenseMap<const FileEntry *, const FileEntry *> ToFromMappings; + +public: + FileRemapper(); + ~FileRemapper(); + + bool initFromDisk(llvm::StringRef outputDir, Diagnostic &Diag, + bool ignoreIfFilesChanged); + bool flushToDisk(llvm::StringRef outputDir, Diagnostic &Diag); + + bool overwriteOriginal(Diagnostic &Diag, + llvm::StringRef outputDir = llvm::StringRef()); + + void remap(llvm::StringRef filePath, llvm::MemoryBuffer *memBuf); + void remap(llvm::StringRef filePath, llvm::StringRef newPath); + + void applyMappings(CompilerInvocation &CI) const; + + void transferMappingsAndClear(CompilerInvocation &CI); + + void clear(llvm::StringRef outputDir = llvm::StringRef()); + +private: + void remap(const FileEntry *file, llvm::MemoryBuffer *memBuf); + void remap(const FileEntry *file, const FileEntry *newfile); + + const FileEntry *getOriginalFile(llvm::StringRef filePath); + void resetTarget(Target &targ); + + bool report(const std::string &err, Diagnostic &Diag); + + std::string getRemapInfoFile(llvm::StringRef outputDir); +}; + +} // end namespace arcmt + +} // end namespace clang + +#endif diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 517c25df24bb..1526f36ba2fb 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -124,7 +124,10 @@ class ASTContext : public llvm::RefCountedBase<ASTContext> { mutable llvm::FoldingSet<QualifiedTemplateName> QualifiedTemplateNames; mutable llvm::FoldingSet<DependentTemplateName> DependentTemplateNames; - mutable llvm::FoldingSet<SubstTemplateTemplateParmPackStorage> + mutable llvm::FoldingSet<SubstTemplateTemplateParmStorage> + SubstTemplateTemplateParms; + mutable llvm::ContextualFoldingSet<SubstTemplateTemplateParmPackStorage, + ASTContext&> SubstTemplateTemplateParmPacks; /// \brief The set of nested name specifiers. @@ -993,6 +996,18 @@ public: return getExtQualType(T, Qs); } + /// getLifetimeQualifiedType - Returns a type with the given + /// lifetime qualifier. + QualType getLifetimeQualifiedType(QualType type, + Qualifiers::ObjCLifetime lifetime) { + assert(type.getObjCLifetime() == Qualifiers::OCL_None); + assert(lifetime != Qualifiers::OCL_None); + + Qualifiers qs; + qs.addObjCLifetime(lifetime); + return getQualifiedType(type, qs); + } + DeclarationNameInfo getNameForTemplate(TemplateName Name, SourceLocation NameLoc) const; @@ -1007,6 +1022,8 @@ public: const IdentifierInfo *Name) const; TemplateName getDependentTemplateName(NestedNameSpecifier *NNS, OverloadedOperatorKind Operator) const; + TemplateName getSubstTemplateTemplateParm(TemplateTemplateParmDecl *param, + TemplateName replacement) const; TemplateName getSubstTemplateTemplateParmPack(TemplateTemplateParmDecl *Param, const TemplateArgument &ArgPack) const; @@ -1044,7 +1061,9 @@ public: /// isObjCNSObjectType - Return true if this is an NSObject object with /// its NSObject attribute set. - bool isObjCNSObjectType(QualType Ty) const; + static bool isObjCNSObjectType(QualType Ty) { + return Ty->isObjCNSObjectType(); + } //===--------------------------------------------------------------------===// // Type Sizing and Analysis @@ -1315,6 +1334,18 @@ public: /// getConstantArrayElementCount - Returns number of constant array elements. uint64_t getConstantArrayElementCount(const ConstantArrayType *CA) const; + /// \brief Perform adjustment on the parameter type of a function. + /// + /// This routine adjusts the given parameter type @p T to the actual + /// parameter type used by semantic analysis (C99 6.7.5.3p[7,8], + /// C++ [dcl.fct]p3). The adjusted parameter type is returned. + QualType getAdjustedParameterType(QualType T); + + /// \brief Retrieve the parameter type as adjusted for use in the signature + /// of a function, decaying array and function types and removing top-level + /// cv-qualifiers. + QualType getSignatureParameterType(QualType T); + /// getArrayDecayedType - Return the properly qualified result of decaying the /// specified array type to a pointer. This operation is non-trivial when /// handling typedefs etc. The canonical type of "T" must be an array type, @@ -1328,6 +1359,10 @@ public: /// integer type. QualType getPromotedIntegerType(QualType PromotableType) const; + /// \brief Recurses in pointer/array types until it finds an objc retainable + /// type and returns its ownership. + Qualifiers::ObjCLifetime getInnerObjCOwnership(QualType T) const; + /// \brief Whether this is a promotable bitfield reference according /// to C99 6.3.1.1p2, bullet 2 (and GCC extensions). /// @@ -1382,6 +1417,7 @@ public: bool typesAreCompatible(QualType T1, QualType T2, bool CompareUnqualified = false); // C99 6.2.7p1 + bool propertyTypesAreCompatible(QualType, QualType); bool typesAreBlockPointerCompatible(QualType, QualType); bool isObjCIdType(QualType T) const { diff --git a/include/clang/AST/ASTDiagnostic.h b/include/clang/AST/ASTDiagnostic.h index 1cb803a3396a..70a548d4e965 100644 --- a/include/clang/AST/ASTDiagnostic.h +++ b/include/clang/AST/ASTDiagnostic.h @@ -33,16 +33,18 @@ namespace clang { /// diagnostics. It is meant to be used as the argument to /// \c Diagnostic::SetArgToStringFn(), where the cookie is an \c ASTContext /// pointer. - void FormatASTNodeDiagnosticArgument(Diagnostic::ArgumentKind Kind, - intptr_t Val, - const char *Modifier, - unsigned ModLen, - const char *Argument, - unsigned ArgLen, - const Diagnostic::ArgumentValue *PrevArgs, - unsigned NumPrevArgs, - llvm::SmallVectorImpl<char> &Output, - void *Cookie); + void FormatASTNodeDiagnosticArgument( + Diagnostic::ArgumentKind Kind, + intptr_t Val, + const char *Modifier, + unsigned ModLen, + const char *Argument, + unsigned ArgLen, + const Diagnostic::ArgumentValue *PrevArgs, + unsigned NumPrevArgs, + llvm::SmallVectorImpl<char> &Output, + void *Cookie, + llvm::SmallVectorImpl<intptr_t> &QualTypeVals); } // end namespace clang #endif diff --git a/include/clang/AST/CanonicalType.h b/include/clang/AST/CanonicalType.h index 251881490499..38e6b41977f8 100644 --- a/include/clang/AST/CanonicalType.h +++ b/include/clang/AST/CanonicalType.h @@ -250,7 +250,6 @@ public: LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjectType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIncompleteType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIncompleteOrObjectType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isPODType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVariablyModifiedType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIntegerType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isEnumeralType) @@ -295,6 +294,7 @@ public: LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isUnsignedIntegerOrEnumerationType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isConstantSizeType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSpecifierType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(CXXRecordDecl*, getAsCXXRecordDecl) /// \brief Retrieve the proxy-adaptor type. /// diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index d993d345ef96..5691e99e7297 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -702,8 +702,12 @@ private: /// \brief Whether this variable is the for-range-declaration in a C++0x /// for-range statement. unsigned CXXForRangeDecl : 1; + + /// \brief Whether this variable is an ARC pseudo-__strong + /// variable; see isARCPseudoStrong() for details. + unsigned ARCPseudoStrong : 1; }; - enum { NumVarDeclBits = 13 }; // two reserved bits for now + enum { NumVarDeclBits = 13 }; // one reserved bit friend class ASTDeclReader; friend class StmtIteratorBase; @@ -975,6 +979,20 @@ public: void setInit(Expr *I); + /// \brief Determine whether this variable is a reference that + /// extends the lifetime of its temporary initializer. + /// + /// A reference extends the lifetime of its temporary initializer if + /// it's initializer is an rvalue that would normally go out of scope + /// at the end of the initializer (a full expression). In such cases, + /// the reference itself takes ownership of the temporary, which will + /// be destroyed when the reference goes out of scope. For example: + /// + /// \code + /// const int &r = 1.0; // creates a temporary of type 'int' + /// \endcode + bool extendsLifetimeOfTemporary() const; + EvaluatedStmt *EnsureEvaluatedStmt() const { EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>(); if (!Eval) { @@ -1102,6 +1120,13 @@ public: /// a C++0x for-range statement. bool isCXXForRangeDecl() const { return VarDeclBits.CXXForRangeDecl; } void setCXXForRangeDecl(bool FRD) { VarDeclBits.CXXForRangeDecl = FRD; } + + /// \brief Determine whether this variable is an ARC pseudo-__strong + /// variable. A pseudo-__strong variable has a __strong-qualified + /// type but does not actually retain the object written into it. + /// Generally such variables are also 'const' for safety. + bool isARCPseudoStrong() const { return VarDeclBits.ARCPseudoStrong; } + void setARCPseudoStrong(bool ps) { VarDeclBits.ARCPseudoStrong = ps; } /// \brief If this variable is an instantiated static data member of a /// class template specialization, returns the templated static data member @@ -2014,6 +2039,11 @@ public: InitializerOrBitWidth.setPointer(BW); InitializerOrBitWidth.setInt(1); } + /// removeBitWidth - Remove the bitfield width from this member. + void removeBitWidth() { + assert(isBitField() && "no bit width to remove"); + InitializerOrBitWidth.setPointer(0); + } /// hasInClassInitializer - Determine whether this member has a C++0x in-class /// initializer. @@ -2956,6 +2986,8 @@ public: bool capturesCXXThis() const { return CapturesCXXThis; } + bool capturesVariable(const VarDecl *var) const; + void setCaptures(ASTContext &Context, const Capture *begin, const Capture *end, diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index b5047b91c0e8..8b2ef2a81acb 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -381,7 +381,24 @@ public: attr_iterator attr_end() const { return hasAttrs() ? getAttrs().end() : 0; } - + + template <typename T> + void dropAttr() { + if (!HasAttrs) return; + + AttrVec &Attrs = getAttrs(); + for (unsigned i = 0, e = Attrs.size(); i != e; /* in loop */) { + if (isa<T>(Attrs[i])) { + Attrs.erase(Attrs.begin() + i); + --e; + } + else + ++i; + } + if (Attrs.empty()) + HasAttrs = false; + } + template <typename T> specific_attr_iterator<T> specific_attr_begin() const { return specific_attr_iterator<T>(attr_begin()); diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 42a12eb5a34c..dd490f48c52c 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -19,7 +19,6 @@ #include "clang/AST/Decl.h" #include "clang/AST/TypeLoc.h" #include "clang/AST/UnresolvedSet.h" -#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallPtrSet.h" namespace clang { diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index 74ceb43c713c..d318fc27a8ba 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -641,6 +641,18 @@ public: return false; } + /// isArcWeakrefUnavailable - Checks for a class or one of its super classes + /// to be incompatible with __weak references. Returns true if it is. + bool isArcWeakrefUnavailable() const { + const ObjCInterfaceDecl *Class = this; + while (Class) { + if (Class->hasAttr<ArcWeakrefUnavailableAttr>()) + return true; + Class = Class->getSuperClass(); + } + return false; + } + ObjCIvarDecl *lookupInstanceVariable(IdentifierInfo *IVarName, ObjCInterfaceDecl *&ClassDeclared); ObjCIvarDecl *lookupInstanceVariable(IdentifierInfo *IVarName) { @@ -1240,6 +1252,9 @@ class ObjCImplementationDecl : public ObjCImplDecl { /// IvarInitializers - The arguments used to initialize the ivars CXXCtorInitializer **IvarInitializers; unsigned NumIvarInitializers; + + /// true if class has a .cxx_[construct,destruct] method. + bool HasCXXStructors : 1; /// true of class extension has at least one bitfield ivar. bool HasSynthBitfield : 1; @@ -1249,7 +1264,7 @@ class ObjCImplementationDecl : public ObjCImplDecl { ObjCInterfaceDecl *superDecl) : ObjCImplDecl(ObjCImplementation, DC, L, classInterface), SuperClass(superDecl), IvarInitializers(0), NumIvarInitializers(0), - HasSynthBitfield(false) {} + HasCXXStructors(false), HasSynthBitfield(false) {} public: static ObjCImplementationDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, @@ -1287,6 +1302,9 @@ public: void setIvarInitializers(ASTContext &C, CXXCtorInitializer ** initializers, unsigned numInitializers); + + bool hasCXXStructors() const { return HasCXXStructors; } + void setHasCXXStructors(bool val) { HasCXXStructors = val; } bool hasSynthBitfield() const { return HasSynthBitfield; } void setHasSynthBitfield (bool val) { HasSynthBitfield = val; } @@ -1393,7 +1411,16 @@ public: OBJC_PR_copy = 0x20, OBJC_PR_nonatomic = 0x40, OBJC_PR_setter = 0x80, - OBJC_PR_atomic = 0x100 + OBJC_PR_atomic = 0x100, + OBJC_PR_weak = 0x200, + OBJC_PR_strong = 0x400, + OBJC_PR_unsafe_unretained = 0x800 + // Adding a property should change NumPropertyAttrsBits + }; + + enum { + /// \brief Number of bits fitting all the property attributes. + NumPropertyAttrsBits = 12 }; enum SetterKind { Assign, Retain, Copy }; @@ -1401,8 +1428,8 @@ public: private: SourceLocation AtLoc; // location of @property TypeSourceInfo *DeclType; - unsigned PropertyAttributes : 9; - unsigned PropertyAttributesAsWritten : 9; + unsigned PropertyAttributes : NumPropertyAttrsBits; + unsigned PropertyAttributesAsWritten : NumPropertyAttrsBits; // @required/@optional unsigned PropertyImplementation : 2; @@ -1445,6 +1472,12 @@ public: PropertyAttributeKind getPropertyAttributesAsWritten() const { return PropertyAttributeKind(PropertyAttributesAsWritten); } + + bool hasWrittenStorageAttribute() const { + return PropertyAttributesAsWritten & (OBJC_PR_assign | OBJC_PR_copy | + OBJC_PR_unsafe_unretained | OBJC_PR_retain | OBJC_PR_strong | + OBJC_PR_weak); + } void setPropertyAttributesAsWritten(PropertyAttributeKind PRVal) { PropertyAttributesAsWritten = PRVal; @@ -1466,7 +1499,7 @@ public: /// the property setter. This is only valid if the property has been /// defined to have a setter. SetterKind getSetterKind() const { - if (PropertyAttributes & OBJC_PR_retain) + if (PropertyAttributes & (OBJC_PR_retain|OBJC_PR_strong)) return Retain; if (PropertyAttributes & OBJC_PR_copy) return Copy; diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index dc50d614bf7c..d2b1d3990c66 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -314,6 +314,10 @@ public: return (TemplateSpecializationKind)(Template.getInt() + 1); } + bool isExplicitSpecialization() const { + return getTemplateSpecializationKind() == TSK_ExplicitSpecialization; + } + /// \brief Set the template specialization kind. void setTemplateSpecializationKind(TemplateSpecializationKind TSK) { assert(TSK != TSK_Undeclared && @@ -1398,6 +1402,10 @@ public: return static_cast<TemplateSpecializationKind>(SpecializationKind); } + bool isExplicitSpecialization() const { + return getSpecializationKind() == TSK_ExplicitSpecialization; + } + void setSpecializationKind(TemplateSpecializationKind TSK) { SpecializationKind = TSK; } diff --git a/include/clang/AST/DeclarationName.h b/include/clang/AST/DeclarationName.h index e54719b33d30..bb098313ea3a 100644 --- a/include/clang/AST/DeclarationName.h +++ b/include/clang/AST/DeclarationName.h @@ -492,6 +492,9 @@ public: LocInfo.CXXLiteralOperatorName.OpNameLoc = Loc.getRawEncoding(); } + /// \brief Determine whether this name involves a template parameter. + bool isInstantiationDependent() const; + /// \brief Determine whether this name contains an unexpanded /// parameter pack. bool containsUnexpandedParameterPack() const; diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index ce86458ed4f4..c7f870725c42 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -57,9 +57,12 @@ class Expr : public Stmt { protected: Expr(StmtClass SC, QualType T, ExprValueKind VK, ExprObjectKind OK, - bool TD, bool VD, bool ContainsUnexpandedParameterPack) : Stmt(SC) { + bool TD, bool VD, bool ID, bool ContainsUnexpandedParameterPack) + : Stmt(SC) + { ExprBits.TypeDependent = TD; ExprBits.ValueDependent = VD; + ExprBits.InstantiationDependent = ID; ExprBits.ValueKind = VK; ExprBits.ObjectKind = OK; ExprBits.ContainsUnexpandedParameterPack = ContainsUnexpandedParameterPack; @@ -95,7 +98,11 @@ public: bool isValueDependent() const { return ExprBits.ValueDependent; } /// \brief Set whether this expression is value-dependent or not. - void setValueDependent(bool VD) { ExprBits.ValueDependent = VD; } + void setValueDependent(bool VD) { + ExprBits.ValueDependent = VD; + if (VD) + ExprBits.InstantiationDependent = true; + } /// isTypeDependent - Determines whether this expression is /// type-dependent (C++ [temp.dep.expr]), which means that its type @@ -111,7 +118,37 @@ public: bool isTypeDependent() const { return ExprBits.TypeDependent; } /// \brief Set whether this expression is type-dependent or not. - void setTypeDependent(bool TD) { ExprBits.TypeDependent = TD; } + void setTypeDependent(bool TD) { + ExprBits.TypeDependent = TD; + if (TD) + ExprBits.InstantiationDependent = true; + } + + /// \brief Whether this expression is instantiation-dependent, meaning that + /// it depends in some way on a template parameter, even if neither its type + /// nor (constant) value can change due to the template instantiation. + /// + /// In the following example, the expression \c sizeof(sizeof(T() + T())) is + /// instantiation-dependent (since it involves a template parameter \c T), but + /// is neither type- nor value-dependent, since the type of the inner + /// \c sizeof is known (\c std::size_t) and therefore the size of the outer + /// \c sizeof is known. + /// + /// \code + /// template<typename T> + /// void f(T x, T y) { + /// sizeof(sizeof(T() + T()); + /// } + /// \endcode + /// + bool isInstantiationDependent() const { + return ExprBits.InstantiationDependent; + } + + /// \brief Set whether this expression is instantiation-dependent or not. + void setInstantiationDependent(bool ID) { + ExprBits.InstantiationDependent = ID; + } /// \brief Whether this expression contains an unexpanded parameter /// pack (for C++0x variadic templates). @@ -501,6 +538,14 @@ public: /// the rules of C++ [expr.unary.noexcept]. CanThrowResult CanThrow(ASTContext &C) const; + /// IgnoreImpCasts - Skip past any implicit casts which might + /// surround this expression. Only skips ImplicitCastExprs. + Expr *IgnoreImpCasts(); + + /// IgnoreImplicit - Skip past any implicit AST nodes which might + /// surround this expression. + Expr *IgnoreImplicit() { return cast<Expr>(Stmt::IgnoreImplicit()); } + /// IgnoreParens - Ignore parentheses. If this Expr is a ParenExpr, return /// its subexpression. If that subexpression is also a ParenExpr, /// then this method recursively returns its subexpression, and so forth. @@ -555,7 +600,10 @@ public: /// \brief Whether this expression is an implicit reference to 'this' in C++. bool isImplicitCXXThis() const; - + + const Expr *IgnoreImpCasts() const { + return const_cast<Expr*>(this)->IgnoreImpCasts(); + } const Expr *IgnoreParens() const { return const_cast<Expr*>(this)->IgnoreParens(); } @@ -595,7 +643,9 @@ public: OpaqueValueExpr(SourceLocation Loc, QualType T, ExprValueKind VK, ExprObjectKind OK = OK_Ordinary) : Expr(OpaqueValueExprClass, T, VK, OK, - T->isDependentType(), T->isDependentType(), false), + T->isDependentType(), T->isDependentType(), + T->isInstantiationDependentType(), + false), SourceExpr(0), Loc(Loc) { } @@ -664,7 +714,8 @@ struct ExplicitTemplateArgumentList { void initializeFrom(const TemplateArgumentListInfo &List); void initializeFrom(const TemplateArgumentListInfo &List, - bool &Dependent, bool &ContainsUnexpandedParameterPack); + bool &Dependent, bool &InstantiationDependent, + bool &ContainsUnexpandedParameterPack); void copyInto(TemplateArgumentListInfo &List) const; static std::size_t sizeFor(unsigned NumTemplateArgs); static std::size_t sizeFor(const TemplateArgumentListInfo &List); @@ -746,9 +797,10 @@ class DeclRefExpr : public Expr { void computeDependence(); public: - DeclRefExpr(ValueDecl *D, QualType T, ExprValueKind VK, SourceLocation L) - : Expr(DeclRefExprClass, T, VK, OK_Ordinary, false, false, false), - D(D), Loc(L) { + DeclRefExpr(ValueDecl *D, QualType T, ExprValueKind VK, SourceLocation L, + const DeclarationNameLoc &LocInfo = DeclarationNameLoc()) + : Expr(DeclRefExprClass, T, VK, OK_Ordinary, false, false, false, false), + D(D), Loc(L), DNLoc(LocInfo) { DeclRefExprBits.HasQualifier = 0; DeclRefExprBits.HasExplicitTemplateArgs = 0; DeclRefExprBits.HasFoundDecl = 0; @@ -936,6 +988,7 @@ public: PredefinedExpr(SourceLocation l, QualType type, IdentType IT) : Expr(PredefinedExprClass, type, VK_LValue, OK_Ordinary, type->isDependentType(), type->isDependentType(), + type->isInstantiationDependentType(), /*ContainsUnexpandedParameterPack=*/false), Loc(l), Type(IT) {} @@ -1023,7 +1076,7 @@ public: IntegerLiteral(ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l) : Expr(IntegerLiteralClass, type, VK_RValue, OK_Ordinary, false, false, - false), + false, false), Loc(l) { assert(type->isIntegerType() && "Illegal type in IntegerLiteral"); assert(V.getBitWidth() == C.getIntWidth(type) && @@ -1066,7 +1119,7 @@ public: // type should be IntTy CharacterLiteral(unsigned value, bool iswide, QualType type, SourceLocation l) : Expr(CharacterLiteralClass, type, VK_RValue, OK_Ordinary, false, false, - false), + false, false), Value(value), Loc(l), IsWide(iswide) { } @@ -1101,7 +1154,7 @@ class FloatingLiteral : public Expr { FloatingLiteral(ASTContext &C, const llvm::APFloat &V, bool isexact, QualType Type, SourceLocation L) : Expr(FloatingLiteralClass, Type, VK_RValue, OK_Ordinary, false, false, - false), + false, false), IsExact(isexact), Loc(L) { setValue(C, V); } @@ -1152,7 +1205,7 @@ class ImaginaryLiteral : public Expr { public: ImaginaryLiteral(Expr *val, QualType Ty) : Expr(ImaginaryLiteralClass, Ty, VK_RValue, OK_Ordinary, false, false, - false), + false, false), Val(val) {} /// \brief Build an empty imaginary literal. @@ -1200,21 +1253,20 @@ class StringLiteral : public Expr { SourceLocation TokLocs[1]; StringLiteral(QualType Ty) : - Expr(StringLiteralClass, Ty, VK_LValue, OK_Ordinary, false, false, false) {} + Expr(StringLiteralClass, Ty, VK_LValue, OK_Ordinary, false, false, false, + false) {} public: /// This is the "fully general" constructor that allows representation of /// strings formed from multiple concatenated tokens. - static StringLiteral *Create(ASTContext &C, const char *StrData, - unsigned ByteLength, bool Wide, bool Pascal, - QualType Ty, + static StringLiteral *Create(ASTContext &C, llvm::StringRef Str, bool Wide, + bool Pascal, QualType Ty, const SourceLocation *Loc, unsigned NumStrs); /// Simple constructor for string literals made from one token. - static StringLiteral *Create(ASTContext &C, const char *StrData, - unsigned ByteLength, bool Wide, + static StringLiteral *Create(ASTContext &C, llvm::StringRef Str, bool Wide, bool Pascal, QualType Ty, SourceLocation Loc) { - return Create(C, StrData, ByteLength, Wide, Pascal, Ty, &Loc, 1); + return Create(C, Str, Wide, Pascal, Ty, &Loc, 1); } /// \brief Construct an empty string literal. @@ -1289,6 +1341,7 @@ public: : Expr(ParenExprClass, val->getType(), val->getValueKind(), val->getObjectKind(), val->isTypeDependent(), val->isValueDependent(), + val->isInstantiationDependent(), val->containsUnexpandedParameterPack()), L(l), R(r), Val(val) {} @@ -1345,6 +1398,8 @@ public: : Expr(UnaryOperatorClass, type, VK, OK, input->isTypeDependent() || type->isDependentType(), input->isValueDependent(), + (input->isInstantiationDependent() || + type->isInstantiationDependentType()), input->containsUnexpandedParameterPack()), Opc(opc), Loc(l), Val(input) {} @@ -1640,6 +1695,7 @@ public: false, // Never type-dependent (C++ [temp.dep.expr]p3). // Value-dependent if the argument is type-dependent. TInfo->getType()->isDependentType(), + TInfo->getType()->isInstantiationDependentType(), TInfo->getType()->containsUnexpandedParameterPack()), Kind(ExprKind), isType(true), OpLoc(op), RParenLoc(rp) { Argument.Ty = TInfo; @@ -1652,6 +1708,7 @@ public: false, // Never type-dependent (C++ [temp.dep.expr]p3). // Value-dependent if the argument is type-dependent. E->isTypeDependent(), + E->isInstantiationDependent(), E->containsUnexpandedParameterPack()), Kind(ExprKind), isType(false), OpLoc(op), RParenLoc(rp) { Argument.Ex = E; @@ -1729,6 +1786,8 @@ public: : Expr(ArraySubscriptExprClass, t, VK, OK, lhs->isTypeDependent() || rhs->isTypeDependent(), lhs->isValueDependent() || rhs->isValueDependent(), + (lhs->isInstantiationDependent() || + rhs->isInstantiationDependent()), (lhs->containsUnexpandedParameterPack() || rhs->containsUnexpandedParameterPack())), RBracketLoc(rbracketloc) { @@ -1986,7 +2045,9 @@ public: const DeclarationNameInfo &NameInfo, QualType ty, ExprValueKind VK, ExprObjectKind OK) : Expr(MemberExprClass, ty, VK, OK, - base->isTypeDependent(), base->isValueDependent(), + base->isTypeDependent(), + base->isValueDependent(), + base->isInstantiationDependent(), base->containsUnexpandedParameterPack()), Base(base), MemberDecl(memberdecl), MemberLoc(NameInfo.getLoc()), MemberDNLoc(NameInfo.getInfo()), IsArrow(isarrow), @@ -2003,6 +2064,7 @@ public: ExprValueKind VK, ExprObjectKind OK) : Expr(MemberExprClass, ty, VK, OK, base->isTypeDependent(), base->isValueDependent(), + base->isInstantiationDependent(), base->containsUnexpandedParameterPack()), Base(base), MemberDecl(memberdecl), MemberLoc(l), MemberDNLoc(), IsArrow(isarrow), @@ -2188,6 +2250,8 @@ public: : Expr(CompoundLiteralExprClass, T, VK, OK_Ordinary, tinfo->getType()->isDependentType(), init->isValueDependent(), + (init->isInstantiationDependent() || + tinfo->getType()->isInstantiationDependentType()), init->containsUnexpandedParameterPack()), LParenLoc(lparenloc), TInfo(tinfo), Init(init), FileScope(fileScope) {} @@ -2276,6 +2340,9 @@ private: case CK_IntegralComplexToReal: case CK_IntegralComplexCast: case CK_IntegralComplexToFloatingComplex: + case CK_ObjCProduceObject: + case CK_ObjCConsumeObject: + case CK_ObjCReclaimReturnedObject: assert(!getType()->isBooleanType() && "unheralded conversion to bool"); // fallthrough to check for null base path @@ -2318,6 +2385,8 @@ protected: // Cast expressions are value-dependent if the type is // dependent or if the subexpression is value-dependent. ty->isDependentType() || (op && op->isValueDependent()), + (ty->isInstantiationDependentType() || + (op && op->isInstantiationDependent())), (ty->containsUnexpandedParameterPack() || op->containsUnexpandedParameterPack())), Op(op) { @@ -2426,6 +2495,13 @@ public: static bool classof(const ImplicitCastExpr *) { return true; } }; +inline Expr *Expr::IgnoreImpCasts() { + Expr *e = this; + while (ImplicitCastExpr *ice = dyn_cast<ImplicitCastExpr>(e)) + e = ice->getSubExpr(); + return e; +} + /// ExplicitCastExpr - An explicit cast written in the source /// code. /// @@ -2551,6 +2627,8 @@ public: : Expr(BinaryOperatorClass, ResTy, VK, OK, lhs->isTypeDependent() || rhs->isTypeDependent(), lhs->isValueDependent() || rhs->isValueDependent(), + (lhs->isInstantiationDependent() || + rhs->isInstantiationDependent()), (lhs->containsUnexpandedParameterPack() || rhs->containsUnexpandedParameterPack())), Opc(opc), OpLoc(opLoc) { @@ -2653,6 +2731,8 @@ protected: : Expr(CompoundAssignOperatorClass, ResTy, VK, OK, lhs->isTypeDependent() || rhs->isTypeDependent(), lhs->isValueDependent() || rhs->isValueDependent(), + (lhs->isInstantiationDependent() || + rhs->isInstantiationDependent()), (lhs->containsUnexpandedParameterPack() || rhs->containsUnexpandedParameterPack())), Opc(opc), OpLoc(opLoc) { @@ -2713,11 +2793,11 @@ class AbstractConditionalOperator : public Expr { protected: AbstractConditionalOperator(StmtClass SC, QualType T, ExprValueKind VK, ExprObjectKind OK, - bool TD, bool VD, + bool TD, bool VD, bool ID, bool ContainsUnexpandedParameterPack, SourceLocation qloc, SourceLocation cloc) - : Expr(SC, T, VK, OK, TD, VD, ContainsUnexpandedParameterPack), + : Expr(SC, T, VK, OK, TD, VD, ID, ContainsUnexpandedParameterPack), QuestionLoc(qloc), ColonLoc(cloc) {} AbstractConditionalOperator(StmtClass SC, EmptyShell Empty) @@ -2765,6 +2845,9 @@ public: (lhs->isTypeDependent() || rhs->isTypeDependent()), (cond->isValueDependent() || lhs->isValueDependent() || rhs->isValueDependent()), + (cond->isInstantiationDependent() || + lhs->isInstantiationDependent() || + rhs->isInstantiationDependent()), (cond->containsUnexpandedParameterPack() || lhs->containsUnexpandedParameterPack() || rhs->containsUnexpandedParameterPack()), @@ -2833,6 +2916,8 @@ public: : AbstractConditionalOperator(BinaryConditionalOperatorClass, t, VK, OK, (common->isTypeDependent() || rhs->isTypeDependent()), (common->isValueDependent() || rhs->isValueDependent()), + (common->isInstantiationDependent() || + rhs->isInstantiationDependent()), (common->containsUnexpandedParameterPack() || rhs->containsUnexpandedParameterPack()), qloc, cloc), @@ -2914,7 +2999,8 @@ class AddrLabelExpr : public Expr { public: AddrLabelExpr(SourceLocation AALoc, SourceLocation LLoc, LabelDecl *L, QualType t) - : Expr(AddrLabelExprClass, t, VK_RValue, OK_Ordinary, false, false, false), + : Expr(AddrLabelExprClass, t, VK_RValue, OK_Ordinary, false, false, false, + false), AmpAmpLoc(AALoc), LabelLoc(LLoc), Label(L) {} /// \brief Build an empty address of a label expression. @@ -2953,10 +3039,12 @@ class StmtExpr : public Expr { SourceLocation LParenLoc, RParenLoc; public: // FIXME: Does type-dependence need to be computed differently? + // FIXME: Do we need to compute instantiation instantiation-dependence for + // statements? (ugh!) StmtExpr(CompoundStmt *substmt, QualType T, SourceLocation lp, SourceLocation rp) : Expr(StmtExprClass, T, VK_RValue, OK_Ordinary, - T->isDependentType(), false, false), + T->isDependentType(), false, false, false), SubStmt(substmt), LParenLoc(lp), RParenLoc(rp) { } /// \brief Build an empty statement expression. @@ -3073,6 +3161,9 @@ public: QualType t, ExprValueKind VK, ExprObjectKind OK, SourceLocation RP, bool TypeDependent, bool ValueDependent) : Expr(ChooseExprClass, t, VK, OK, TypeDependent, ValueDependent, + (cond->isInstantiationDependent() || + lhs->isInstantiationDependent() || + rhs->isInstantiationDependent()), (cond->containsUnexpandedParameterPack() || lhs->containsUnexpandedParameterPack() || rhs->containsUnexpandedParameterPack())), @@ -3134,7 +3225,8 @@ class GNUNullExpr : public Expr { public: GNUNullExpr(QualType Ty, SourceLocation Loc) - : Expr(GNUNullExprClass, Ty, VK_RValue, OK_Ordinary, false, false, false), + : Expr(GNUNullExprClass, Ty, VK_RValue, OK_Ordinary, false, false, false, + false), TokenLoc(Loc) { } /// \brief Build an empty GNU __null expression. @@ -3166,6 +3258,8 @@ public: SourceLocation RPLoc, QualType t) : Expr(VAArgExprClass, t, VK_RValue, OK_Ordinary, t->isDependentType(), false, + (TInfo->getType()->isInstantiationDependentType() || + e->isInstantiationDependent()), (TInfo->getType()->containsUnexpandedParameterPack() || e->containsUnexpandedParameterPack())), Val(e), TInfo(TInfo), @@ -3537,9 +3631,9 @@ public: bool isArrayDesignator() const { return Kind == ArrayDesignator; } bool isArrayRangeDesignator() const { return Kind == ArrayRangeDesignator; } - IdentifierInfo * getFieldName(); + IdentifierInfo *getFieldName() const; - FieldDecl *getField() { + FieldDecl *getField() const { assert(Kind == FieldDesignator && "Only valid on a field designator"); if (Field.NameOrField & 0x01) return 0; @@ -3612,12 +3706,18 @@ public: unsigned size() const { return NumDesignators; } // Iterator access to the designators. - typedef Designator* designators_iterator; + typedef Designator *designators_iterator; designators_iterator designators_begin() { return Designators; } designators_iterator designators_end() { return Designators + NumDesignators; } + typedef const Designator *const_designators_iterator; + const_designators_iterator designators_begin() const { return Designators; } + const_designators_iterator designators_end() const { + return Designators + NumDesignators; + } + typedef std::reverse_iterator<designators_iterator> reverse_designators_iterator; reverse_designators_iterator designators_rbegin() { @@ -3627,6 +3727,15 @@ public: return reverse_designators_iterator(designators_begin()); } + typedef std::reverse_iterator<const_designators_iterator> + const_reverse_designators_iterator; + const_reverse_designators_iterator designators_rbegin() const { + return const_reverse_designators_iterator(designators_end()); + } + const_reverse_designators_iterator designators_rend() const { + return const_reverse_designators_iterator(designators_begin()); + } + Designator *getDesignator(unsigned Idx) { return &designators_begin()[Idx]; } void setDesignators(ASTContext &C, const Designator *Desigs, @@ -3708,7 +3817,7 @@ class ImplicitValueInitExpr : public Expr { public: explicit ImplicitValueInitExpr(QualType ty) : Expr(ImplicitValueInitExprClass, ty, VK_RValue, OK_Ordinary, - false, false, false) { } + false, false, ty->isInstantiationDependentType(), false) { } /// \brief Construct an empty implicit value initialization. explicit ImplicitValueInitExpr(EmptyShell Empty) @@ -3735,7 +3844,7 @@ class ParenListExpr : public Expr { public: ParenListExpr(ASTContext& C, SourceLocation lparenloc, Expr **exprs, - unsigned numexprs, SourceLocation rparenloc); + unsigned numexprs, SourceLocation rparenloc, QualType T); /// \brief Build an empty paren list. explicit ParenListExpr(EmptyShell Empty) : Expr(ParenListExprClass, Empty) { } @@ -3909,6 +4018,7 @@ public: : Expr(ExtVectorElementExprClass, ty, VK, (VK == VK_RValue ? OK_Ordinary : OK_VectorComponent), base->isTypeDependent(), base->isValueDependent(), + base->isInstantiationDependent(), base->containsUnexpandedParameterPack()), Base(base), Accessor(&accessor), AccessorLoc(loc) {} @@ -3963,7 +4073,10 @@ protected: public: BlockExpr(BlockDecl *BD, QualType ty) : Expr(BlockExprClass, ty, VK_RValue, OK_Ordinary, - ty->isDependentType(), false, false), + ty->isDependentType(), false, + // FIXME: Check for instantiate-dependence in the statement? + ty->isInstantiationDependentType(), + false), TheBlock(BD) {} /// \brief Build an empty block expression. @@ -4037,26 +4150,36 @@ public: /// AsTypeExpr - Clang builtin function __builtin_astype [OpenCL 6.2.4.2] /// This AST node provides support for reinterpreting a type to another /// type of the same size. -class AsTypeExpr : public Expr { +class AsTypeExpr : public Expr { // Should this be an ExplicitCastExpr? private: - Expr* SrcExpr; - QualType DstType; + Stmt *SrcExpr; SourceLocation BuiltinLoc, RParenLoc; + + friend class ASTReader; + friend class ASTStmtReader; + explicit AsTypeExpr(EmptyShell Empty) : Expr(AsTypeExprClass, Empty) {} public: AsTypeExpr(Expr* SrcExpr, QualType DstType, ExprValueKind VK, ExprObjectKind OK, SourceLocation BuiltinLoc, SourceLocation RParenLoc) - : Expr(AsTypeExprClass, DstType, VK, OK, false, false, false), - SrcExpr(SrcExpr), DstType(DstType), - BuiltinLoc(BuiltinLoc), RParenLoc(RParenLoc) {} - - /// \brief Build an empty __builtin_astype - explicit AsTypeExpr(EmptyShell Empty) : Expr(AsTypeExprClass, Empty) {} + : Expr(AsTypeExprClass, DstType, VK, OK, + DstType->isDependentType(), + DstType->isDependentType() || SrcExpr->isValueDependent(), + (DstType->isInstantiationDependentType() || + SrcExpr->isInstantiationDependent()), + (DstType->containsUnexpandedParameterPack() || + SrcExpr->containsUnexpandedParameterPack())), + SrcExpr(SrcExpr), BuiltinLoc(BuiltinLoc), RParenLoc(RParenLoc) {} /// getSrcExpr - Return the Expr to be converted. - Expr *getSrcExpr() const { return SrcExpr; } - QualType getDstType() const { return DstType; } + Expr *getSrcExpr() const { return cast<Expr>(SrcExpr); } + + /// getBuiltinLoc - Return the location of the __builtin_astype token. + SourceLocation getBuiltinLoc() const { return BuiltinLoc; } + + /// getRParenLoc - Return the location of final right parenthesis. + SourceLocation getRParenLoc() const { return RParenLoc; } SourceRange getSourceRange() const { return SourceRange(BuiltinLoc, RParenLoc); @@ -4068,7 +4191,7 @@ public: static bool classof(const AsTypeExpr *) { return true; } // Iterators - child_range children() { return child_range(); } + child_range children() { return child_range(&SrcExpr, &SrcExpr+1); } }; } // end namespace clang diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index a97057973745..19117040ef96 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -330,7 +330,7 @@ class CXXBoolLiteralExpr : public Expr { public: CXXBoolLiteralExpr(bool val, QualType Ty, SourceLocation l) : Expr(CXXBoolLiteralExprClass, Ty, VK_RValue, OK_Ordinary, false, false, - false), + false, false), Value(val), Loc(l) {} explicit CXXBoolLiteralExpr(EmptyShell Empty) @@ -359,7 +359,7 @@ class CXXNullPtrLiteralExpr : public Expr { public: CXXNullPtrLiteralExpr(QualType Ty, SourceLocation l) : Expr(CXXNullPtrLiteralExprClass, Ty, VK_RValue, OK_Ordinary, false, false, - false), + false, false), Loc(l) {} explicit CXXNullPtrLiteralExpr(EmptyShell Empty) @@ -395,6 +395,7 @@ public: false, // typeid is value-dependent if the type or expression are dependent Operand->getType()->isDependentType(), + Operand->getType()->isInstantiationDependentType(), Operand->getType()->containsUnexpandedParameterPack()), Operand(Operand), Range(R) { } @@ -404,6 +405,7 @@ public: false, // typeid is value-dependent if the type or expression are dependent Operand->isTypeDependent() || Operand->isValueDependent(), + Operand->isInstantiationDependent(), Operand->containsUnexpandedParameterPack()), Operand(Operand), Range(R) { } @@ -471,12 +473,14 @@ public: CXXUuidofExpr(QualType Ty, TypeSourceInfo *Operand, SourceRange R) : Expr(CXXUuidofExprClass, Ty, VK_LValue, OK_Ordinary, false, Operand->getType()->isDependentType(), + Operand->getType()->isInstantiationDependentType(), Operand->getType()->containsUnexpandedParameterPack()), Operand(Operand), Range(R) { } CXXUuidofExpr(QualType Ty, Expr *Operand, SourceRange R) : Expr(CXXUuidofExprClass, Ty, VK_LValue, OK_Ordinary, false, Operand->isTypeDependent(), + Operand->isInstantiationDependent(), Operand->containsUnexpandedParameterPack()), Operand(Operand), Range(R) { } @@ -552,6 +556,7 @@ public: // 'this' is type-dependent if the class type of the enclosing // member function is dependent (C++ [temp.dep.expr]p2) Type->isDependentType(), Type->isDependentType(), + Type->isInstantiationDependentType(), /*ContainsUnexpandedParameterPack=*/false), Loc(L), Implicit(isImplicit) { } @@ -581,23 +586,35 @@ public: class CXXThrowExpr : public Expr { Stmt *Op; SourceLocation ThrowLoc; + /// \brief Whether the thrown variable (if any) is in scope. + unsigned IsThrownVariableInScope : 1; + + friend class ASTStmtReader; + public: // Ty is the void type which is used as the result type of the // exepression. The l is the location of the throw keyword. expr // can by null, if the optional expression to throw isn't present. - CXXThrowExpr(Expr *expr, QualType Ty, SourceLocation l) : + CXXThrowExpr(Expr *expr, QualType Ty, SourceLocation l, + bool IsThrownVariableInScope) : Expr(CXXThrowExprClass, Ty, VK_RValue, OK_Ordinary, false, false, + expr && expr->isInstantiationDependent(), expr && expr->containsUnexpandedParameterPack()), - Op(expr), ThrowLoc(l) {} + Op(expr), ThrowLoc(l), IsThrownVariableInScope(IsThrownVariableInScope) {} CXXThrowExpr(EmptyShell Empty) : Expr(CXXThrowExprClass, Empty) {} const Expr *getSubExpr() const { return cast_or_null<Expr>(Op); } Expr *getSubExpr() { return cast_or_null<Expr>(Op); } - void setSubExpr(Expr *E) { Op = E; } SourceLocation getThrowLoc() const { return ThrowLoc; } - void setThrowLoc(SourceLocation L) { ThrowLoc = L; } + /// \brief Determines whether the variable thrown by this expression (if any!) + /// is within the innermost try block. + /// + /// This information is required to determine whether the NRVO can apply to + /// this variable. + bool isThrownVariableInScope() const { return IsThrownVariableInScope; } + SourceRange getSourceRange() const { if (getSubExpr() == 0) return SourceRange(ThrowLoc, ThrowLoc); @@ -636,14 +653,14 @@ class CXXDefaultArgExpr : public Expr { ? param->getType().getNonReferenceType() : param->getDefaultArg()->getType(), param->getDefaultArg()->getValueKind(), - param->getDefaultArg()->getObjectKind(), false, false, false), + param->getDefaultArg()->getObjectKind(), false, false, false, false), Param(param, false), Loc(Loc) { } CXXDefaultArgExpr(StmtClass SC, SourceLocation Loc, ParmVarDecl *param, Expr *SubExpr) : Expr(SC, SubExpr->getType(), SubExpr->getValueKind(), SubExpr->getObjectKind(), - false, false, false), + false, false, false, false), Param(param, true), Loc(Loc) { *reinterpret_cast<Expr **>(this + 1) = SubExpr; } @@ -742,6 +759,7 @@ class CXXBindTemporaryExpr : public Expr { : Expr(CXXBindTemporaryExprClass, SubExpr->getType(), VK_RValue, OK_Ordinary, SubExpr->isTypeDependent(), SubExpr->isValueDependent(), + SubExpr->isInstantiationDependent(), SubExpr->containsUnexpandedParameterPack()), Temp(temp), SubExpr(SubExpr) { } @@ -995,7 +1013,7 @@ public: TypeSourceInfo *TypeInfo, SourceLocation rParenLoc ) : Expr(CXXScalarValueInitExprClass, Type, VK_RValue, OK_Ordinary, - false, false, false), + false, false, Type->isInstantiationDependentType(), false), RParenLoc(rParenLoc), TypeInfo(TypeInfo) {} explicit CXXScalarValueInitExpr(EmptyShell Shell) @@ -1241,6 +1259,7 @@ public: bool arrayFormAsWritten, bool usualArrayDeleteWantsSize, FunctionDecl *operatorDelete, Expr *arg, SourceLocation loc) : Expr(CXXDeleteExprClass, ty, VK_RValue, OK_Ordinary, false, false, + arg->isInstantiationDependent(), arg->containsUnexpandedParameterPack()), GlobalDelete(globalDelete), ArrayForm(arrayForm), ArrayFormAsWritten(arrayFormAsWritten), @@ -1500,6 +1519,7 @@ public: SourceLocation rparen, QualType ty) : Expr(UnaryTypeTraitExprClass, ty, VK_RValue, OK_Ordinary, false, queried->getType()->isDependentType(), + queried->getType()->isInstantiationDependentType(), queried->getType()->containsUnexpandedParameterPack()), UTT(utt), Value(value), Loc(loc), RParen(rparen), QueriedType(queried) { } @@ -1558,6 +1578,8 @@ public: : Expr(BinaryTypeTraitExprClass, ty, VK_RValue, OK_Ordinary, false, lhsType->getType()->isDependentType() || rhsType->getType()->isDependentType(), + (lhsType->getType()->isInstantiationDependentType() || + rhsType->getType()->isInstantiationDependentType()), (lhsType->getType()->containsUnexpandedParameterPack() || rhsType->getType()->containsUnexpandedParameterPack())), BTT(btt), Value(value), Loc(loc), RParen(rparen), @@ -1625,6 +1647,8 @@ public: Expr *dimension, SourceLocation rparen, QualType ty) : Expr(ArrayTypeTraitExprClass, ty, VK_RValue, OK_Ordinary, false, queried->getType()->isDependentType(), + (queried->getType()->isInstantiationDependentType() || + (dimension && dimension->isInstantiationDependent())), queried->getType()->containsUnexpandedParameterPack()), ATT(att), Value(value), Dimension(dimension), Loc(loc), RParen(rparen), QueriedType(queried) { } @@ -1684,6 +1708,7 @@ public: false, // Not type-dependent // Value-dependent if the argument is type-dependent. queried->isTypeDependent(), + queried->isInstantiationDependent(), queried->containsUnexpandedParameterPack()), ET(et), Value(value), Loc(loc), RParen(rparen), QueriedExpression(queried) { } @@ -1736,8 +1761,9 @@ protected: const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin, UnresolvedSetIterator End, - bool KnownDependent = false, - bool KnownContainsUnexpandedParameterPack = false); + bool KnownDependent, + bool KnownInstantiationDependent, + bool KnownContainsUnexpandedParameterPack); OverloadExpr(StmtClass K, EmptyShell Empty) : Expr(K, Empty), Results(0), NumResults(0), @@ -1880,7 +1906,7 @@ class UnresolvedLookupExpr : public OverloadExpr { UnresolvedSetIterator Begin, UnresolvedSetIterator End, bool StdIsAssociatedNamespace) : OverloadExpr(UnresolvedLookupExprClass, C, QualifierLoc, NameInfo, - TemplateArgs, Begin, End), + TemplateArgs, Begin, End, false, false, false), RequiresADL(RequiresADL), StdIsAssociatedNamespace(StdIsAssociatedNamespace), Overloaded(Overloaded), NamingClass(NamingClass) @@ -2727,6 +2753,7 @@ public: : Expr(CXXNoexceptExprClass, Ty, VK_RValue, OK_Ordinary, /*TypeDependent*/false, /*ValueDependent*/Val == CT_Dependent, + Val == CT_Dependent || Operand->isInstantiationDependent(), Operand->containsUnexpandedParameterPack()), Value(Val == CT_Cannot), Operand(Operand), Range(Keyword, RParen) { } @@ -2787,7 +2814,8 @@ public: llvm::Optional<unsigned> NumExpansions) : Expr(PackExpansionExprClass, T, Pattern->getValueKind(), Pattern->getObjectKind(), /*TypeDependent=*/true, - /*ValueDependent=*/true, /*ContainsUnexpandedParameterPack=*/false), + /*ValueDependent=*/true, /*InstantiationDependent=*/true, + /*ContainsUnexpandedParameterPack=*/false), EllipsisLoc(EllipsisLoc), NumExpansions(NumExpansions? *NumExpansions + 1 : 0), Pattern(Pattern) { } @@ -2874,6 +2902,7 @@ public: SourceLocation PackLoc, SourceLocation RParenLoc) : Expr(SizeOfPackExprClass, SizeType, VK_RValue, OK_Ordinary, /*TypeDependent=*/false, /*ValueDependent=*/true, + /*InstantiationDependent=*/true, /*ContainsUnexpandedParameterPack=*/false), OperatorLoc(OperatorLoc), PackLoc(PackLoc), RParenLoc(RParenLoc), Length(0), Pack(Pack) { } @@ -2885,6 +2914,7 @@ public: unsigned Length) : Expr(SizeOfPackExprClass, SizeType, VK_RValue, OK_Ordinary, /*TypeDependent=*/false, /*ValueDependent=*/false, + /*InstantiationDependent=*/false, /*ContainsUnexpandedParameterPack=*/false), OperatorLoc(OperatorLoc), PackLoc(PackLoc), RParenLoc(RParenLoc), Length(Length), Pack(Pack) { } @@ -2927,6 +2957,53 @@ public: child_range children() { return child_range(); } }; +/// \brief Represents a reference to a non-type template parameter +/// that has been substituted with a template argument. +class SubstNonTypeTemplateParmExpr : public Expr { + /// \brief The replaced parameter. + NonTypeTemplateParmDecl *Param; + + /// \brief The replacement expression. + Stmt *Replacement; + + /// \brief The location of the non-type template parameter reference. + SourceLocation NameLoc; + + friend class ASTReader; + friend class ASTStmtReader; + explicit SubstNonTypeTemplateParmExpr(EmptyShell Empty) + : Expr(SubstNonTypeTemplateParmExprClass, Empty) { } + +public: + SubstNonTypeTemplateParmExpr(QualType type, + ExprValueKind valueKind, + SourceLocation loc, + NonTypeTemplateParmDecl *param, + Expr *replacement) + : Expr(SubstNonTypeTemplateParmExprClass, type, valueKind, OK_Ordinary, + replacement->isTypeDependent(), replacement->isValueDependent(), + replacement->isInstantiationDependent(), + replacement->containsUnexpandedParameterPack()), + Param(param), Replacement(replacement), NameLoc(loc) {} + + SourceLocation getNameLoc() const { return NameLoc; } + SourceRange getSourceRange() const { return NameLoc; } + + Expr *getReplacement() const { return cast<Expr>(Replacement); } + + NonTypeTemplateParmDecl *getParameter() const { return Param; } + + static bool classof(const Stmt *s) { + return s->getStmtClass() == SubstNonTypeTemplateParmExprClass; + } + static bool classof(const SubstNonTypeTemplateParmExpr *) { + return true; + } + + // Iterators + child_range children() { return child_range(&Replacement, &Replacement+1); } +}; + /// \brief Represents a reference to a non-type template parameter pack that /// has been substituted with a non-template argument pack. /// @@ -2953,8 +3030,10 @@ class SubstNonTypeTemplateParmPackExpr : public Expr { /// \brief The location of the non-type template parameter pack reference. SourceLocation NameLoc; + friend class ASTReader; friend class ASTStmtReader; - friend class ASTStmtWriter; + explicit SubstNonTypeTemplateParmPackExpr(EmptyShell Empty) + : Expr(SubstNonTypeTemplateParmPackExprClass, Empty) { } public: SubstNonTypeTemplateParmPackExpr(QualType T, @@ -2962,9 +3041,6 @@ public: SourceLocation NameLoc, const TemplateArgument &ArgPack); - SubstNonTypeTemplateParmPackExpr(EmptyShell Empty) - : Expr(SubstNonTypeTemplateParmPackExprClass, Empty) { } - /// \brief Retrieve the non-type template parameter pack being substituted. NonTypeTemplateParmDecl *getParameterPack() const { return Param; } @@ -2987,6 +3063,66 @@ public: // Iterators child_range children() { return child_range(); } }; + +/// \brief Represents a prvalue temporary that written into memory so that +/// a reference can bind to it. +/// +/// Prvalue expressions are materialized when they need to have an address +/// in memory for a reference to bind to. This happens when binding a +/// reference to the result of a conversion, e.g., +/// +/// \code +/// const int &r = 1.0; +/// \endcode +/// +/// Here, 1.0 is implicitly converted to an \c int. That resulting \c int is +/// then materialized via a \c MaterializeTemporaryExpr, and the reference +/// binds to the temporary. \c MaterializeTemporaryExprs are always glvalues +/// (either an lvalue or an xvalue, depending on the kind of reference binding +/// to it), maintaining the invariant that references always bind to glvalues. +class MaterializeTemporaryExpr : public Expr { + /// \brief The temporary-generating expression whose value will be + /// materialized. + Stmt *Temporary; + + friend class ASTStmtReader; + friend class ASTStmtWriter; + +public: + MaterializeTemporaryExpr(QualType T, Expr *Temporary, + bool BoundToLvalueReference) + : Expr(MaterializeTemporaryExprClass, T, + BoundToLvalueReference? VK_LValue : VK_XValue, OK_Ordinary, + Temporary->isTypeDependent(), Temporary->isValueDependent(), + Temporary->isInstantiationDependent(), + Temporary->containsUnexpandedParameterPack()), + Temporary(Temporary) { } + + MaterializeTemporaryExpr(EmptyShell Empty) + : Expr(MaterializeTemporaryExprClass, Empty) { } + + /// \brief Retrieve the temporary-generating subexpression whose value will + /// be materialized into a glvalue. + Expr *GetTemporaryExpr() const { return reinterpret_cast<Expr *>(Temporary); } + + /// \brief Determine whether this materialized temporary is bound to an + /// lvalue reference; otherwise, it's bound to an rvalue reference. + bool isBoundToLvalueReference() const { + return getValueKind() == VK_LValue; + } + + SourceRange getSourceRange() const { return Temporary->getSourceRange(); } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == MaterializeTemporaryExprClass; + } + static bool classof(const MaterializeTemporaryExpr *) { + return true; + } + + // Iterators + child_range children() { return child_range(&Temporary, &Temporary + 1); } +}; } // end namespace clang diff --git a/include/clang/AST/ExprObjC.h b/include/clang/AST/ExprObjC.h index 8163923d62d1..49d4cfe67626 100644 --- a/include/clang/AST/ExprObjC.h +++ b/include/clang/AST/ExprObjC.h @@ -30,7 +30,7 @@ class ObjCStringLiteral : public Expr { public: ObjCStringLiteral(StringLiteral *SL, QualType T, SourceLocation L) : Expr(ObjCStringLiteralClass, T, VK_RValue, OK_Ordinary, false, false, - false), + false, false), String(SL), AtLoc(L) {} explicit ObjCStringLiteral(EmptyShell Empty) : Expr(ObjCStringLiteralClass, Empty) {} @@ -67,6 +67,7 @@ public: : Expr(ObjCEncodeExprClass, T, VK_LValue, OK_Ordinary, EncodedType->getType()->isDependentType(), EncodedType->getType()->isDependentType(), + EncodedType->getType()->isInstantiationDependentType(), EncodedType->getType()->containsUnexpandedParameterPack()), EncodedType(EncodedType), AtLoc(at), RParenLoc(rp) {} @@ -106,7 +107,7 @@ public: ObjCSelectorExpr(QualType T, Selector selInfo, SourceLocation at, SourceLocation rp) : Expr(ObjCSelectorExprClass, T, VK_RValue, OK_Ordinary, false, false, - false), + false, false), SelName(selInfo), AtLoc(at), RParenLoc(rp){} explicit ObjCSelectorExpr(EmptyShell Empty) : Expr(ObjCSelectorExprClass, Empty) {} @@ -146,7 +147,7 @@ public: ObjCProtocolExpr(QualType T, ObjCProtocolDecl *protocol, SourceLocation at, SourceLocation rp) : Expr(ObjCProtocolExprClass, T, VK_RValue, OK_Ordinary, false, false, - false), + false, false), TheProtocol(protocol), AtLoc(at), RParenLoc(rp) {} explicit ObjCProtocolExpr(EmptyShell Empty) : Expr(ObjCProtocolExprClass, Empty) {} @@ -186,6 +187,7 @@ public: bool arrow = false, bool freeIvar = false) : Expr(ObjCIvarRefExprClass, t, VK_LValue, OK_Ordinary, /*TypeDependent=*/false, base->isValueDependent(), + base->isInstantiationDependent(), base->containsUnexpandedParameterPack()), D(d), Loc(l), Base(base), IsArrow(arrow), IsFreeIvar(freeIvar) {} @@ -248,6 +250,7 @@ public: SourceLocation l, Expr *base) : Expr(ObjCPropertyRefExprClass, t, VK, OK, /*TypeDependent=*/false, base->isValueDependent(), + base->isInstantiationDependent(), base->containsUnexpandedParameterPack()), PropertyOrGetter(PD, false), Setter(0), IdLoc(l), ReceiverLoc(), Receiver(base) { @@ -257,7 +260,7 @@ public: ExprValueKind VK, ExprObjectKind OK, SourceLocation l, SourceLocation sl, QualType st) : Expr(ObjCPropertyRefExprClass, t, VK, OK, - /*TypeDependent=*/false, false, + /*TypeDependent=*/false, false, st->isInstantiationDependentType(), st->containsUnexpandedParameterPack()), PropertyOrGetter(PD, false), Setter(0), IdLoc(l), ReceiverLoc(sl), Receiver(st.getTypePtr()) { @@ -267,7 +270,7 @@ public: QualType T, ExprValueKind VK, ExprObjectKind OK, SourceLocation IdLoc, Expr *Base) : Expr(ObjCPropertyRefExprClass, T, VK, OK, false, - Base->isValueDependent(), + Base->isValueDependent(), Base->isInstantiationDependent(), Base->containsUnexpandedParameterPack()), PropertyOrGetter(Getter, true), Setter(Setter), IdLoc(IdLoc), ReceiverLoc(), Receiver(Base) { @@ -277,7 +280,7 @@ public: QualType T, ExprValueKind VK, ExprObjectKind OK, SourceLocation IdLoc, SourceLocation SuperLoc, QualType SuperTy) - : Expr(ObjCPropertyRefExprClass, T, VK, OK, false, false, false), + : Expr(ObjCPropertyRefExprClass, T, VK, OK, false, false, false, false), PropertyOrGetter(Getter, true), Setter(Setter), IdLoc(IdLoc), ReceiverLoc(SuperLoc), Receiver(SuperTy.getTypePtr()) { } @@ -286,7 +289,7 @@ public: QualType T, ExprValueKind VK, ExprObjectKind OK, SourceLocation IdLoc, SourceLocation ReceiverLoc, ObjCInterfaceDecl *Receiver) - : Expr(ObjCPropertyRefExprClass, T, VK, OK, false, false, false), + : Expr(ObjCPropertyRefExprClass, T, VK, OK, false, false, false, false), PropertyOrGetter(Getter, true), Setter(Setter), IdLoc(IdLoc), ReceiverLoc(ReceiverLoc), Receiver(Receiver) { } @@ -456,7 +459,11 @@ class ObjCMessageExpr : public Expr { /// /// When non-zero, we have a method declaration; otherwise, we just /// have a selector. - unsigned HasMethod : 8; + unsigned HasMethod : 1; + + /// \brief Whether this message send is a "delegate init call", + /// i.e. a call of an init method on self from within an init method. + unsigned IsDelegateInitCall : 1; /// \brief When the message expression is a send to 'super', this is /// the location of the 'super' keyword. @@ -476,7 +483,7 @@ class ObjCMessageExpr : public Expr { ObjCMessageExpr(EmptyShell Empty, unsigned NumArgs) : Expr(ObjCMessageExprClass, Empty), NumArgs(NumArgs), Kind(0), - HasMethod(0), SelectorOrMethod(0) { } + HasMethod(0), IsDelegateInitCall(0), SelectorOrMethod(0) { } ObjCMessageExpr(QualType T, ExprValueKind VK, SourceLocation LBracLoc, @@ -807,6 +814,12 @@ public: getArgs()[Arg] = ArgExpr; } + /// isDelegateInitCall - Answers whether this message send has been + /// tagged as a "delegate init call", i.e. a call to a method in the + /// -init family on self from within an -init method implementation. + bool isDelegateInitCall() const { return IsDelegateInitCall; } + void setDelegateInitCall(bool isDelegate) { IsDelegateInitCall = isDelegate; } + SourceLocation getLeftLoc() const { return LBracLoc; } SourceLocation getRightLoc() const { return RBracLoc; } SourceLocation getSelectorLoc() const { return SelectorLoc; } @@ -860,6 +873,7 @@ public: ObjCIsaExpr(Expr *base, bool isarrow, SourceLocation l, QualType ty) : Expr(ObjCIsaExprClass, ty, VK_LValue, OK_Ordinary, /*TypeDependent=*/false, base->isValueDependent(), + base->isInstantiationDependent(), /*ContainsUnexpandedParameterPack=*/false), Base(base), IsaMemberLoc(l), IsArrow(isarrow) {} @@ -892,6 +906,123 @@ public: child_range children() { return child_range(&Base, &Base+1); } }; + +/// ObjCIndirectCopyRestoreExpr - Represents the passing of a function +/// argument by indirect copy-restore in ARC. This is used to support +/// passing indirect arguments with the wrong lifetime, e.g. when +/// passing the address of a __strong local variable to an 'out' +/// parameter. This expression kind is only valid in an "argument" +/// position to some sort of call expression. +/// +/// The parameter must have type 'pointer to T', and the argument must +/// have type 'pointer to U', where T and U agree except possibly in +/// qualification. If the argument value is null, then a null pointer +/// is passed; otherwise it points to an object A, and: +/// 1. A temporary object B of type T is initialized, either by +/// zero-initialization (used when initializing an 'out' parameter) +/// or copy-initialization (used when initializing an 'inout' +/// parameter). +/// 2. The address of the temporary is passed to the function. +/// 3. If the call completes normally, A is move-assigned from B. +/// 4. Finally, A is destroyed immediately. +/// +/// Currently 'T' must be a retainable object lifetime and must be +/// __autoreleasing; this qualifier is ignored when initializing +/// the value. +class ObjCIndirectCopyRestoreExpr : public Expr { + Stmt *Operand; + + // unsigned ObjCIndirectCopyRestoreBits.ShouldCopy : 1; + + friend class ASTReader; + friend class ASTStmtReader; + + void setShouldCopy(bool shouldCopy) { + ObjCIndirectCopyRestoreExprBits.ShouldCopy = shouldCopy; + } + + explicit ObjCIndirectCopyRestoreExpr(EmptyShell Empty) + : Expr(ObjCIndirectCopyRestoreExprClass, Empty) { } + +public: + ObjCIndirectCopyRestoreExpr(Expr *operand, QualType type, bool shouldCopy) + : Expr(ObjCIndirectCopyRestoreExprClass, type, VK_LValue, OK_Ordinary, + operand->isTypeDependent(), operand->isValueDependent(), + operand->isInstantiationDependent(), + operand->containsUnexpandedParameterPack()), + Operand(operand) { + setShouldCopy(shouldCopy); + } + + Expr *getSubExpr() { return cast<Expr>(Operand); } + const Expr *getSubExpr() const { return cast<Expr>(Operand); } + + /// shouldCopy - True if we should do the 'copy' part of the + /// copy-restore. If false, the temporary will be zero-initialized. + bool shouldCopy() const { return ObjCIndirectCopyRestoreExprBits.ShouldCopy; } + + child_range children() { return child_range(&Operand, &Operand+1); } + + // Source locations are determined by the subexpression. + SourceRange getSourceRange() const { return Operand->getSourceRange(); } + SourceLocation getExprLoc() const { return getSubExpr()->getExprLoc(); } + + static bool classof(const Stmt *s) { + return s->getStmtClass() == ObjCIndirectCopyRestoreExprClass; + } + static bool classof(const ObjCIndirectCopyRestoreExpr *) { return true; } +}; + +/// \brief An Objective-C "bridged" cast expression, which casts between +/// Objective-C pointers and C pointers, transferring ownership in the process. +/// +/// \code +/// NSString *str = (__bridge_transfer NSString *)CFCreateString(); +/// \endcode +class ObjCBridgedCastExpr : public ExplicitCastExpr { + SourceLocation LParenLoc; + SourceLocation BridgeKeywordLoc; + unsigned Kind : 2; + + friend class ASTStmtReader; + friend class ASTStmtWriter; + +public: + ObjCBridgedCastExpr(SourceLocation LParenLoc, ObjCBridgeCastKind Kind, + SourceLocation BridgeKeywordLoc, TypeSourceInfo *TSInfo, + Expr *Operand) + : ExplicitCastExpr(ObjCBridgedCastExprClass, TSInfo->getType(), VK_RValue, + CK_BitCast, Operand, 0, TSInfo), + LParenLoc(LParenLoc), BridgeKeywordLoc(BridgeKeywordLoc), Kind(Kind) { } + + /// \brief Construct an empty Objective-C bridged cast. + explicit ObjCBridgedCastExpr(EmptyShell Shell) + : ExplicitCastExpr(ObjCBridgedCastExprClass, Shell, 0) { } + + SourceLocation getLParenLoc() const { return LParenLoc; } + + /// \brief Determine which kind of bridge is being performed via this cast. + ObjCBridgeCastKind getBridgeKind() const { + return static_cast<ObjCBridgeCastKind>(Kind); + } + + /// \brief Retrieve the kind of bridge being performed as a string. + llvm::StringRef getBridgeKindName() const; + + /// \brief The location of the bridge keyword. + SourceLocation getBridgeKeywordLoc() const { return BridgeKeywordLoc; } + + SourceRange getSourceRange() const { + return SourceRange(LParenLoc, getSubExpr()->getLocEnd()); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCBridgedCastExprClass; + } + static bool classof(const ObjCBridgedCastExpr *) { return true; } + +}; + } // end namespace clang #endif diff --git a/include/clang/AST/ExternalASTSource.h b/include/clang/AST/ExternalASTSource.h index 846813adf7c3..ef1f1618ba1d 100644 --- a/include/clang/AST/ExternalASTSource.h +++ b/include/clang/AST/ExternalASTSource.h @@ -32,6 +32,20 @@ class Selector; class Stmt; class TagDecl; +/// \brief Enumeration describing the result of loading information from +/// an external source. +enum ExternalLoadResult { + /// \brief Loading the external information has succeeded. + ELR_Success, + + /// \brief Loading the external information has failed. + ELR_Failure, + + /// \brief The external information has already been loaded, and therefore + /// no additional processing is required. + ELR_AlreadyLoaded +}; + /// \brief Abstract interface for external sources of AST nodes. /// /// External AST sources provide AST nodes constructed from some @@ -132,10 +146,10 @@ public: /// declaration kind is one we are looking for. If NULL, all declarations /// are returned. /// - /// \return true if an error occurred + /// \return an indication of whether the load succeeded or failed. /// /// The default implementation of this method is a no-op. - virtual bool FindExternalLexicalDecls(const DeclContext *DC, + virtual ExternalLoadResult FindExternalLexicalDecls(const DeclContext *DC, bool (*isKindWeWant)(Decl::Kind), llvm::SmallVectorImpl<Decl*> &Result); @@ -143,14 +157,14 @@ public: /// DeclContext. /// /// \return true if an error occurred - bool FindExternalLexicalDecls(const DeclContext *DC, + ExternalLoadResult FindExternalLexicalDecls(const DeclContext *DC, llvm::SmallVectorImpl<Decl*> &Result) { return FindExternalLexicalDecls(DC, 0, Result); } template <typename DeclTy> - bool FindExternalLexicalDeclsBy(const DeclContext *DC, - llvm::SmallVectorImpl<Decl*> &Result) { + ExternalLoadResult FindExternalLexicalDeclsBy(const DeclContext *DC, + llvm::SmallVectorImpl<Decl*> &Result) { return FindExternalLexicalDecls(DC, DeclTy::classofKind, Result); } diff --git a/lib/CodeGen/GlobalDecl.h b/include/clang/AST/GlobalDecl.h index c2f36d210bfc..c43e44c26f31 100644 --- a/lib/CodeGen/GlobalDecl.h +++ b/include/clang/AST/GlobalDecl.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CLANG_CODEGEN_GLOBALDECL_H -#define CLANG_CODEGEN_GLOBALDECL_H +#ifndef LLVM_CLANG_AST_GLOBALDECL_H +#define LLVM_CLANG_AST_GLOBALDECL_H #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" @@ -21,8 +21,6 @@ namespace clang { -namespace CodeGen { - /// GlobalDecl - represents a global declaration. This can either be a /// CXXConstructorDecl and the constructor type (Base, Complete). /// a CXXDestructorDecl and the destructor type (Base, Complete) or @@ -89,28 +87,27 @@ public: } }; -} // end namespace CodeGen } // end namespace clang namespace llvm { template<class> struct DenseMapInfo; - template<> struct DenseMapInfo<clang::CodeGen::GlobalDecl> { - static inline clang::CodeGen::GlobalDecl getEmptyKey() { - return clang::CodeGen::GlobalDecl(); + template<> struct DenseMapInfo<clang::GlobalDecl> { + static inline clang::GlobalDecl getEmptyKey() { + return clang::GlobalDecl(); } - static inline clang::CodeGen::GlobalDecl getTombstoneKey() { - return clang::CodeGen::GlobalDecl:: + static inline clang::GlobalDecl getTombstoneKey() { + return clang::GlobalDecl:: getFromOpaquePtr(reinterpret_cast<void*>(-1)); } - static unsigned getHashValue(clang::CodeGen::GlobalDecl GD) { + static unsigned getHashValue(clang::GlobalDecl GD) { return DenseMapInfo<void*>::getHashValue(GD.getAsOpaquePtr()); } - static bool isEqual(clang::CodeGen::GlobalDecl LHS, - clang::CodeGen::GlobalDecl RHS) { + static bool isEqual(clang::GlobalDecl LHS, + clang::GlobalDecl RHS) { return LHS == RHS; } @@ -119,7 +116,7 @@ namespace llvm { // GlobalDecl isn't *technically* a POD type. However, its copy constructor, // copy assignment operator, and destructor are all trivial. template <> - struct isPodLike<clang::CodeGen::GlobalDecl> { + struct isPodLike<clang::GlobalDecl> { static const bool value = true; }; } // end namespace llvm diff --git a/include/clang/AST/NestedNameSpecifier.h b/include/clang/AST/NestedNameSpecifier.h index c21c76b006ff..018041f8ba20 100644 --- a/include/clang/AST/NestedNameSpecifier.h +++ b/include/clang/AST/NestedNameSpecifier.h @@ -186,6 +186,10 @@ public: /// type or not. bool isDependent() const; + /// \brief Whether this nested name specifier involves a template + /// parameter. + bool isInstantiationDependent() const; + /// \brief Whether this nested-name-specifier contains an unexpanded /// parameter pack (for C++0x variadic templates). bool containsUnexpandedParameterPack() const; @@ -435,6 +439,14 @@ public: /// copied. NestedNameSpecifierLoc getWithLocInContext(ASTContext &Context) const; + /// \brief Retrieve a nested-name-specifier with location + /// information based on the information in this builder. This loc + /// will contain references to the builder's internal data and may + /// be invalidated by any change to the builder. + NestedNameSpecifierLoc getTemporary() const { + return NestedNameSpecifierLoc(Representation, Buffer); + } + /// \brief Clear out this builder, and prepare it to build another /// nested-name-specifier with source-location information. void Clear() { diff --git a/include/clang/AST/OperationKinds.h b/include/clang/AST/OperationKinds.h index 35c72c45ce7c..92ff6041371c 100644 --- a/include/clang/AST/OperationKinds.h +++ b/include/clang/AST/OperationKinds.h @@ -245,7 +245,22 @@ enum CastKind { /// \brief Converts from an integral complex to a floating complex. /// _Complex unsigned -> _Complex float - CK_IntegralComplexToFloatingComplex + CK_IntegralComplexToFloatingComplex, + + /// \brief Produces a retainable object pointer so that it may be + /// consumed, e.g. by being passed to a consuming parameter. Calls + /// objc_retain. + CK_ObjCProduceObject, + + /// \brief Consumes a retainable object pointer that has just been + /// produced, e.g. as the return value of a retaining call. Enters + /// a cleanup to call objc_release at some indefinite time. + CK_ObjCConsumeObject, + + /// \brief Reclaim a retainable object pointer object that may have + /// been produced and autoreleased as part of a function return + /// sequence. + CK_ObjCReclaimReturnedObject }; #define CK_Invalid ((CastKind) -1) @@ -284,6 +299,19 @@ enum UnaryOperatorKind { UO_Extension // __extension__ marker. }; +/// \brief The kind of bridging performed by the Objective-C bridge cast. +enum ObjCBridgeCastKind { + /// \brief Bridging via __bridge, which does nothing but reinterpret + /// the bits. + OBC_Bridge, + /// \brief Bridging via __bridge_transfer, which transfers ownership of an + /// Objective-C pointer into ARC. + OBC_BridgeTransfer, + /// \brief Bridging via __bridge_retain, which makes an ARC object available + /// as a +1 C pointer. + OBC_BridgeRetained +}; + } #endif diff --git a/include/clang/AST/ParentMap.h b/include/clang/AST/ParentMap.h index 9ea5a0930d32..22c1e7269fac 100644 --- a/include/clang/AST/ParentMap.h +++ b/include/clang/AST/ParentMap.h @@ -32,6 +32,7 @@ public: Stmt *getParent(Stmt*) const; Stmt *getParentIgnoreParens(Stmt *) const; Stmt *getParentIgnoreParenCasts(Stmt *) const; + Stmt *getOuterParenParent(Stmt *) const; const Stmt *getParent(const Stmt* S) const { return getParent(const_cast<Stmt*>(S)); diff --git a/include/clang/AST/PrettyPrinter.h b/include/clang/AST/PrettyPrinter.h index cf5fadbd1850..fc8ac36b3b97 100644 --- a/include/clang/AST/PrettyPrinter.h +++ b/include/clang/AST/PrettyPrinter.h @@ -41,7 +41,7 @@ struct PrintingPolicy { SuppressTagKeyword(false), SuppressTag(false), SuppressScope(false), SuppressInitializers(false), Dump(false), ConstantArraySizeAsWritten(false), - AnonymousTagLocations(true) { } + AnonymousTagLocations(true), SuppressStrongLifetime(false) { } /// \brief The number of spaces to use to indent each line. unsigned Indentation : 8; @@ -129,6 +129,10 @@ struct PrintingPolicy { /// that entity (e.g., "enum <anonymous at t.h:10:5>"). Otherwise, just /// prints "<anonymous>" for the name. bool AnonymousTagLocations : 1; + + /// \brief When true, suppress printing of the __strong lifetime qualifier in + /// ARC. + unsigned SuppressStrongLifetime : 1; }; } // end namespace clang diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index a8f182a5bc92..85c5c08853d1 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -1721,6 +1721,7 @@ DEF_TRAVERSE_STMT(ObjCAtSynchronizedStmt, { }) DEF_TRAVERSE_STMT(ObjCAtThrowStmt, { }) DEF_TRAVERSE_STMT(ObjCAtTryStmt, { }) DEF_TRAVERSE_STMT(ObjCForCollectionStmt, { }) +DEF_TRAVERSE_STMT(ObjCAutoreleasePoolStmt, { }) DEF_TRAVERSE_STMT(CXXForRangeStmt, { }) DEF_TRAVERSE_STMT(ReturnStmt, { }) DEF_TRAVERSE_STMT(SwitchStmt, { }) @@ -1933,6 +1934,10 @@ DEF_TRAVERSE_STMT(ObjCMessageExpr, { }) DEF_TRAVERSE_STMT(ObjCPropertyRefExpr, { }) DEF_TRAVERSE_STMT(ObjCProtocolExpr, { }) DEF_TRAVERSE_STMT(ObjCSelectorExpr, { }) +DEF_TRAVERSE_STMT(ObjCIndirectCopyRestoreExpr, { }) +DEF_TRAVERSE_STMT(ObjCBridgedCastExpr, { + TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc())); +}) DEF_TRAVERSE_STMT(ParenExpr, { }) DEF_TRAVERSE_STMT(ParenListExpr, { }) DEF_TRAVERSE_STMT(PredefinedExpr, { }) @@ -1973,6 +1978,8 @@ DEF_TRAVERSE_STMT(CXXNoexceptExpr, { }) DEF_TRAVERSE_STMT(PackExpansionExpr, { }) DEF_TRAVERSE_STMT(SizeOfPackExpr, { }) DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmPackExpr, { }) +DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmExpr, { }) +DEF_TRAVERSE_STMT(MaterializeTemporaryExpr, { }) // These literals (all of them) do not need any action. DEF_TRAVERSE_STMT(IntegerLiteral, { }) diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h index 695fb0403ead..bf5f383be5e0 100644 --- a/include/clang/AST/Stmt.h +++ b/include/clang/AST/Stmt.h @@ -154,9 +154,10 @@ protected: unsigned ObjectKind : 2; unsigned TypeDependent : 1; unsigned ValueDependent : 1; + unsigned InstantiationDependent : 1; unsigned ContainsUnexpandedParameterPack : 1; }; - enum { NumExprBits = 15 }; + enum { NumExprBits = 16 }; class DeclRefExprBitfields { friend class DeclRefExpr; @@ -183,6 +184,13 @@ protected: unsigned NumPreArgs : 1; }; + class ObjCIndirectCopyRestoreExprBitfields { + friend class ObjCIndirectCopyRestoreExpr; + unsigned : NumExprBits; + + unsigned ShouldCopy : 1; + }; + union { // FIXME: this is wasteful on 64-bit platforms. void *Aligner; @@ -193,6 +201,7 @@ protected: DeclRefExprBitfields DeclRefExprBits; CastExprBitfields CastExprBits; CallExprBitfields CallExprBits; + ObjCIndirectCopyRestoreExprBitfields ObjCIndirectCopyRestoreExprBits; }; friend class ASTStmtReader; @@ -284,6 +293,10 @@ public: /// works on systems with GraphViz (Mac OS X) or dot+gv installed. void viewAST() const; + /// Skip past any implicit AST nodes which might surround this + /// statement, such as ExprWithCleanups or ImplicitCastExpr nodes. + Stmt *IgnoreImplicit(); + // Implement isa<T> support. static bool classof(const Stmt *) { return true; } @@ -327,7 +340,7 @@ public: /// declaration pointers) or the exact representation of the statement as /// written in the source. void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, - bool Canonical); + bool Canonical) const; }; /// DeclStmt - Adaptor class for mixing declarations with statements and @@ -1458,6 +1471,10 @@ class SEHExceptStmt : public Stmt { Expr *FilterExpr, Stmt *Block); + friend class ASTReader; + friend class ASTStmtReader; + explicit SEHExceptStmt(EmptyShell E) : Stmt(SEHExceptStmtClass, E) { } + public: static SEHExceptStmt* Create(ASTContext &C, SourceLocation ExceptLoc, @@ -1492,6 +1509,10 @@ class SEHFinallyStmt : public Stmt { SEHFinallyStmt(SourceLocation Loc, Stmt *Block); + friend class ASTReader; + friend class ASTStmtReader; + explicit SEHFinallyStmt(EmptyShell E) : Stmt(SEHFinallyStmtClass, E) { } + public: static SEHFinallyStmt* Create(ASTContext &C, SourceLocation FinallyLoc, @@ -1530,6 +1551,10 @@ class SEHTryStmt : public Stmt { Stmt *TryBlock, Stmt *Handler); + friend class ASTReader; + friend class ASTStmtReader; + explicit SEHTryStmt(EmptyShell E) : Stmt(SEHTryStmtClass, E) { } + public: static SEHTryStmt* Create(ASTContext &C, bool isCXXTry, diff --git a/include/clang/AST/StmtObjC.h b/include/clang/AST/StmtObjC.h index 1800a71f9154..d996fc5cada3 100644 --- a/include/clang/AST/StmtObjC.h +++ b/include/clang/AST/StmtObjC.h @@ -342,6 +342,39 @@ public: child_range children() { return child_range(&Throw, &Throw+1); } }; +/// ObjCAutoreleasePoolStmt - This represent objective-c's +/// @autoreleasepool Statement +class ObjCAutoreleasePoolStmt : public Stmt { + Stmt *SubStmt; + SourceLocation AtLoc; +public: + ObjCAutoreleasePoolStmt(SourceLocation atLoc, + Stmt *subStmt) + : Stmt(ObjCAutoreleasePoolStmtClass), + SubStmt(subStmt), AtLoc(atLoc) {} + + explicit ObjCAutoreleasePoolStmt(EmptyShell Empty) : + Stmt(ObjCAutoreleasePoolStmtClass, Empty) { } + + const Stmt *getSubStmt() const { return SubStmt; } + Stmt *getSubStmt() { return SubStmt; } + void setSubStmt(Stmt *S) { SubStmt = S; } + + SourceRange getSourceRange() const { + return SourceRange(AtLoc, SubStmt->getLocEnd()); + } + + SourceLocation getAtLoc() const { return AtLoc; } + void setAtLoc(SourceLocation Loc) { AtLoc = Loc; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCAutoreleasePoolStmtClass; + } + static bool classof(const ObjCAutoreleasePoolStmt *) { return true; } + + child_range children() { return child_range(&SubStmt, &SubStmt + 1); } +}; + } // end namespace clang #endif diff --git a/include/clang/AST/TemplateBase.h b/include/clang/AST/TemplateBase.h index 821b4fcbb168..1c693e00c8cc 100644 --- a/include/clang/AST/TemplateBase.h +++ b/include/clang/AST/TemplateBase.h @@ -235,9 +235,14 @@ public: bool isNull() const { return Kind == Null; } /// \brief Whether this template argument is dependent on a template - /// parameter. + /// parameter such that its result can change from one instantiation to + /// another. bool isDependent() const; + /// \brief Whether this template argument is dependent on a template + /// parameter. + bool isInstantiationDependent() const; + /// \brief Whether this template argument contains an unexpanded /// parameter pack. bool containsUnexpandedParameterPack() const; diff --git a/include/clang/AST/TemplateName.h b/include/clang/AST/TemplateName.h index 1721973e8229..a180f587eddd 100644 --- a/include/clang/AST/TemplateName.h +++ b/include/clang/AST/TemplateName.h @@ -33,6 +33,7 @@ class OverloadedTemplateStorage; struct PrintingPolicy; class QualifiedTemplateName; class NamedDecl; +class SubstTemplateTemplateParmStorage; class SubstTemplateTemplateParmPackStorage; class TemplateArgument; class TemplateDecl; @@ -42,38 +43,49 @@ class TemplateTemplateParmDecl; /// template names or an already-substituted template template parameter pack. class UncommonTemplateNameStorage { protected: + enum Kind { + Overloaded, + SubstTemplateTemplateParm, + SubstTemplateTemplateParmPack + }; + union { struct { - /// \brief If true, this is an OverloadedTemplateStorage instance; - /// otherwise, it's a SubstTemplateTemplateParmPackStorage instance. - unsigned IsOverloadedStorage : 1; + /// \brief A Kind. + unsigned Kind : 2; /// \brief The number of stored templates or template arguments, /// depending on which subclass we have. - unsigned Size : 31; + unsigned Size : 30; } Bits; void *PointerAlignment; }; - UncommonTemplateNameStorage(unsigned Size, bool OverloadedStorage) { - Bits.IsOverloadedStorage = OverloadedStorage; - Bits.Size = Size; + UncommonTemplateNameStorage(Kind kind, unsigned size) { + Bits.Kind = kind; + Bits.Size = size; } public: unsigned size() const { return Bits.Size; } OverloadedTemplateStorage *getAsOverloadedStorage() { - return Bits.IsOverloadedStorage + return Bits.Kind == Overloaded ? reinterpret_cast<OverloadedTemplateStorage *>(this) : 0; } + SubstTemplateTemplateParmStorage *getAsSubstTemplateTemplateParm() { + return Bits.Kind == SubstTemplateTemplateParm + ? reinterpret_cast<SubstTemplateTemplateParmStorage *>(this) + : 0; + } + SubstTemplateTemplateParmPackStorage *getAsSubstTemplateTemplateParmPack() { - return Bits.IsOverloadedStorage - ? 0 - : reinterpret_cast<SubstTemplateTemplateParmPackStorage *>(this) ; + return Bits.Kind == SubstTemplateTemplateParmPack + ? reinterpret_cast<SubstTemplateTemplateParmPackStorage *>(this) + : 0; } }; @@ -82,8 +94,8 @@ public: class OverloadedTemplateStorage : public UncommonTemplateNameStorage { friend class ASTContext; - OverloadedTemplateStorage(unsigned Size) - : UncommonTemplateNameStorage(Size, true) { } + OverloadedTemplateStorage(unsigned size) + : UncommonTemplateNameStorage(Overloaded, size) { } NamedDecl **getStorage() { return reinterpret_cast<NamedDecl **>(this + 1); @@ -98,8 +110,7 @@ public: iterator begin() const { return getStorage(); } iterator end() const { return getStorage() + size(); } }; - - + /// \brief A structure for storing an already-substituted template template /// parameter pack. /// @@ -109,16 +120,14 @@ public: class SubstTemplateTemplateParmPackStorage : public UncommonTemplateNameStorage, public llvm::FoldingSetNode { - ASTContext &Context; TemplateTemplateParmDecl *Parameter; const TemplateArgument *Arguments; public: - SubstTemplateTemplateParmPackStorage(ASTContext &Context, - TemplateTemplateParmDecl *Parameter, + SubstTemplateTemplateParmPackStorage(TemplateTemplateParmDecl *Parameter, unsigned Size, const TemplateArgument *Arguments) - : UncommonTemplateNameStorage(Size, false), Context(Context), + : UncommonTemplateNameStorage(SubstTemplateTemplateParmPack, Size), Parameter(Parameter), Arguments(Arguments) { } /// \brief Retrieve the template template parameter pack being substituted. @@ -130,9 +139,10 @@ public: /// parameter was substituted. TemplateArgument getArgumentPack() const; - void Profile(llvm::FoldingSetNodeID &ID); + void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context); - static void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context, + static void Profile(llvm::FoldingSetNodeID &ID, + ASTContext &Context, TemplateTemplateParmDecl *Parameter, const TemplateArgument &ArgPack); }; @@ -189,6 +199,9 @@ public: /// \brief A dependent template name that has not been resolved to a /// template (or set of templates). DependentTemplate, + /// \brief A template template parameter that has been substituted + /// for some other template name. + SubstTemplateTemplateParm, /// \brief A template template parameter pack that has been substituted for /// a template template argument pack, but has not yet been expanded into /// individual arguments. @@ -199,6 +212,7 @@ public: explicit TemplateName(TemplateDecl *Template) : Storage(Template) { } explicit TemplateName(OverloadedTemplateStorage *Storage) : Storage(Storage) { } + explicit TemplateName(SubstTemplateTemplateParmStorage *Storage); explicit TemplateName(SubstTemplateTemplateParmPackStorage *Storage) : Storage(Storage) { } explicit TemplateName(QualifiedTemplateName *Qual) : Storage(Qual) { } @@ -234,6 +248,19 @@ public: return 0; } + /// \brief Retrieve the substituted template template parameter, if + /// known. + /// + /// \returns The storage for the substituted template template parameter, + /// if known. Otherwise, returns NULL. + SubstTemplateTemplateParmStorage *getAsSubstTemplateTemplateParm() const { + if (UncommonTemplateNameStorage *uncommon = + Storage.dyn_cast<UncommonTemplateNameStorage *>()) + return uncommon->getAsSubstTemplateTemplateParm(); + + return 0; + } + /// \brief Retrieve the substituted template template parameter pack, if /// known. /// @@ -260,9 +287,15 @@ public: return Storage.dyn_cast<DependentTemplateName *>(); } + TemplateName getUnderlying() const; + /// \brief Determines whether this is a dependent template name. bool isDependent() const; + /// \brief Determines whether this is a template name that somehow + /// depends on a template parameter. + bool isInstantiationDependent() const; + /// \brief Determines whether this template name contains an /// unexpanded parameter pack (for C++0x variadic templates). bool containsUnexpandedParameterPack() const; @@ -300,6 +333,41 @@ public: const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, TemplateName N); +/// \brief A structure for storing the information associated with a +/// substituted template template parameter. +class SubstTemplateTemplateParmStorage + : public UncommonTemplateNameStorage, public llvm::FoldingSetNode { + friend class ASTContext; + + TemplateTemplateParmDecl *Parameter; + TemplateName Replacement; + + SubstTemplateTemplateParmStorage(TemplateTemplateParmDecl *parameter, + TemplateName replacement) + : UncommonTemplateNameStorage(SubstTemplateTemplateParm, 0), + Parameter(parameter), Replacement(replacement) {} + +public: + TemplateTemplateParmDecl *getParameter() const { return Parameter; } + TemplateName getReplacement() const { return Replacement; } + + void Profile(llvm::FoldingSetNodeID &ID); + + static void Profile(llvm::FoldingSetNodeID &ID, + TemplateTemplateParmDecl *parameter, + TemplateName replacement); +}; + +inline TemplateName::TemplateName(SubstTemplateTemplateParmStorage *Storage) + : Storage(Storage) { } + +inline TemplateName TemplateName::getUnderlying() const { + if (SubstTemplateTemplateParmStorage *subst + = getAsSubstTemplateTemplateParm()) + return subst->getReplacement().getUnderlying(); + return *this; +} + /// \brief Represents a template name that was expressed as a /// qualified name. /// diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 77633831ff27..ef0dbdae037c 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -126,6 +126,28 @@ public: Strong }; + enum ObjCLifetime { + /// There is no lifetime qualification on this type. + OCL_None, + + /// This object can be modified without requiring retains or + /// releases. + OCL_ExplicitNone, + + /// Assigning into this object requires the old value to be + /// released and the new value to be retained. The timing of the + /// release of the old value is inexact: it may be moved to + /// immediately after the last known point where the value is + /// live. + OCL_Strong, + + /// Reading or writing from this object requires a barrier call. + OCL_Weak, + + /// Assigning into this object requires a lifetime extension. + OCL_Autoreleasing + }; + enum { /// The maximum supported address space number. /// 24 bits should be enough for anyone. @@ -218,7 +240,37 @@ public: qs.removeObjCGCAttr(); return qs; } + Qualifiers withoutObjCGLifetime() const { + Qualifiers qs = *this; + qs.removeObjCLifetime(); + return qs; + } + + bool hasObjCLifetime() const { return Mask & LifetimeMask; } + ObjCLifetime getObjCLifetime() const { + return ObjCLifetime((Mask & LifetimeMask) >> LifetimeShift); + } + void setObjCLifetime(ObjCLifetime type) { + Mask = (Mask & ~LifetimeMask) | (type << LifetimeShift); + } + void removeObjCLifetime() { setObjCLifetime(OCL_None); } + void addObjCLifetime(ObjCLifetime type) { + assert(type); + setObjCLifetime(type); + } + + /// True if the lifetime is neither None or ExplicitNone. + bool hasNonTrivialObjCLifetime() const { + ObjCLifetime lifetime = getObjCLifetime(); + return (lifetime > OCL_ExplicitNone); + } + /// True if the lifetime is either strong or weak. + bool hasStrongOrWeakObjCLifetime() const { + ObjCLifetime lifetime = getObjCLifetime(); + return (lifetime == OCL_Strong || lifetime == OCL_Weak); + } + bool hasAddressSpace() const { return Mask & AddressSpaceMask; } unsigned getAddressSpace() const { return Mask >> AddressSpaceShift; } void setAddressSpace(unsigned space) { @@ -277,6 +329,8 @@ public: addAddressSpace(Q.getAddressSpace()); if (Q.hasObjCGCAttr()) addObjCGCAttr(Q.getObjCGCAttr()); + if (Q.hasObjCLifetime()) + addObjCLifetime(Q.getObjCLifetime()); } } @@ -287,6 +341,8 @@ public: !hasAddressSpace() || !qs.hasAddressSpace()); assert(getObjCGCAttr() == qs.getObjCGCAttr() || !hasObjCGCAttr() || !qs.hasObjCGCAttr()); + assert(getObjCLifetime() == qs.getObjCLifetime() || + !hasObjCLifetime() || !qs.hasObjCLifetime()); Mask |= qs.Mask; } @@ -301,10 +357,30 @@ public: // changed. (getObjCGCAttr() == other.getObjCGCAttr() || !hasObjCGCAttr() || !other.hasObjCGCAttr()) && + // ObjC lifetime qualifiers must match exactly. + getObjCLifetime() == other.getObjCLifetime() && // CVR qualifiers may subset. (((Mask & CVRMask) | (other.Mask & CVRMask)) == (Mask & CVRMask)); } + /// \brief Determines if these qualifiers compatibly include another set of + /// qualifiers from the narrow perspective of Objective-C ARC lifetime. + /// + /// One set of Objective-C lifetime qualifiers compatibly includes the other + /// if the lifetime qualifiers match, or if both are non-__weak and the + /// including set also contains the 'const' qualifier. + bool compatiblyIncludesObjCLifetime(Qualifiers other) const { + if (getObjCLifetime() == other.getObjCLifetime()) + return true; + + if (getObjCLifetime() == OCL_Weak || other.getObjCLifetime() == OCL_Weak) + return false; + + return hasConst(); + } + + bool isSupersetOf(Qualifiers Other) const; + /// \brief Determine whether this set of qualifiers is a strict superset of /// another set of qualifiers, not considering qualifier compatibility. bool isStrictSupersetOf(Qualifiers Other) const; @@ -351,14 +427,16 @@ public: private: - // bits: |0 1 2|3 .. 4|5 .. 31| - // |C R V|GCAttr|AddrSpace| + // bits: |0 1 2|3 .. 4|5 .. 7|8 ... 31| + // |C R V|GCAttr|Lifetime|AddressSpace| uint32_t Mask; static const uint32_t GCAttrMask = 0x18; static const uint32_t GCAttrShift = 3; - static const uint32_t AddressSpaceMask = ~(CVRMask | GCAttrMask); - static const uint32_t AddressSpaceShift = 5; + static const uint32_t LifetimeMask = 0xE0; + static const uint32_t LifetimeShift = 5; + static const uint32_t AddressSpaceMask = ~(CVRMask|GCAttrMask|LifetimeMask); + static const uint32_t AddressSpaceShift = 8; }; /// CallingConv - Specifies the calling convention that a function uses. @@ -527,6 +605,23 @@ public: return QualType::isConstant(*this, Ctx); } + /// \brief Determine whether this is a Plain Old Data (POD) type (C++ 3.9p10). + bool isPODType(ASTContext &Context) const; + + /// isCXX11PODType() - Return true if this is a POD type according to the + /// more relaxed rules of the C++11 standard, regardless of the current + /// compilation's language. + /// (C++0x [basic.types]p9) + bool isCXX11PODType(ASTContext &Context) const; + + /// isTrivialType - Return true if this is a trivial type + /// (C++0x [basic.types]p9) + bool isTrivialType(ASTContext &Context) const; + + /// isTriviallyCopyableType - Return true if this is a trivially + /// copyable type (C++0x [basic.types]p9) + bool isTriviallyCopyableType(ASTContext &Context) const; + // Don't promise in the API that anything besides 'const' can be // easily added. @@ -546,6 +641,10 @@ public: return withFastQualifiers(Qualifiers::Volatile); } + QualType withCVRQualifiers(unsigned CVR) const { + return withFastQualifiers(CVR); + } + void addFastQualifiers(unsigned TQs) { assert(!(TQs & ~Qualifiers::FastMask) && "non-fast qualifier bits set in mask!"); @@ -658,6 +757,13 @@ public: return getSplitDesugaredType(*this); } + /// \brief Return the specified type with one level of "sugar" removed from + /// the type. + /// + /// This routine takes off the first typedef, typeof, etc. If the outer level + /// of the type is already concrete, it returns it unmodified. + QualType getSingleStepDesugaredType(const ASTContext &Context) const; + /// IgnoreParens - Returns the specified type after dropping any /// outer-level parentheses. QualType IgnoreParens() const { @@ -709,7 +815,7 @@ public: /// getAddressSpace - Return the address space of this type. inline unsigned getAddressSpace() const; - /// GCAttrTypesAttr - Returns gc attribute of this type. + /// getObjCGCAttr - Returns gc attribute of this type. inline Qualifiers::GC getObjCGCAttr() const; /// isObjCGCWeak true when Type is objc's weak. @@ -722,9 +828,24 @@ public: return getObjCGCAttr() == Qualifiers::Strong; } + /// getObjCLifetime - Returns lifetime attribute of this type. + Qualifiers::ObjCLifetime getObjCLifetime() const { + return getQualifiers().getObjCLifetime(); + } + + bool hasNonTrivialObjCLifetime() const { + return getQualifiers().hasNonTrivialObjCLifetime(); + } + + bool hasStrongOrWeakObjCLifetime() const { + return getQualifiers().hasStrongOrWeakObjCLifetime(); + } + enum DestructionKind { DK_none, - DK_cxx_destructor + DK_cxx_destructor, + DK_objc_strong_lifetime, + DK_objc_weak_lifetime }; /// isDestructedType - nonzero if objects of this type require @@ -735,6 +856,21 @@ public: return isDestructedTypeImpl(*this); } + /// \brief Determine whether expressions of the given type are forbidden + /// from being lvalues in C. + /// + /// The expression types that are forbidden to be lvalues are: + /// - 'void', but not qualified void + /// - function types + /// + /// The exact rule here is C99 6.3.2.1: + /// An lvalue is an expression with an object type or an incomplete + /// type other than void. + bool isCForbiddenLValueType() const; + + /// \brief Determine whether this type has trivial copy-assignment semantics. + bool hasTrivialCopyAssignment(ASTContext &Context) const; + private: // These methods are implemented in a separate translation unit; // "static"-ize them to avoid creating temporary QualTypes in the @@ -849,6 +985,11 @@ public: bool hasObjCGCAttr() const { return Quals.hasObjCGCAttr(); } Qualifiers::GC getObjCGCAttr() const { return Quals.getObjCGCAttr(); } + bool hasObjCLifetime() const { return Quals.hasObjCLifetime(); } + Qualifiers::ObjCLifetime getObjCLifetime() const { + return Quals.getObjCLifetime(); + } + bool hasAddressSpace() const { return Quals.hasAddressSpace(); } unsigned getAddressSpace() const { return Quals.getAddressSpace(); } @@ -931,6 +1072,10 @@ private: /// subclasses can pack their bitfields into the same word. unsigned Dependent : 1; + /// \brief Whether this type somehow involves a template parameter, even + /// if the resolution of the type does not depend on a template parameter. + unsigned InstantiationDependent : 1; + /// \brief Whether this type is a variably-modified type (C99 6.7.5). unsigned VariablyModified : 1; @@ -968,7 +1113,7 @@ private: return CachedLocalOrUnnamed; } }; - enum { NumTypeBits = 17 }; + enum { NumTypeBits = 18 }; protected: // These classes allow subclasses to somewhat cleanly pack bitfields @@ -1111,12 +1256,14 @@ private: protected: // silence VC++ warning C4355: 'this' : used in base member initializer list Type *this_() { return this; } - Type(TypeClass tc, QualType canon, bool Dependent, bool VariablyModified, + Type(TypeClass tc, QualType canon, bool Dependent, + bool InstantiationDependent, bool VariablyModified, bool ContainsUnexpandedParameterPack) : ExtQualsTypeCommonBase(this, canon.isNull() ? QualType(this_(), 0) : canon) { TypeBits.TC = tc; TypeBits.Dependent = Dependent; + TypeBits.InstantiationDependent = Dependent || InstantiationDependent; TypeBits.VariablyModified = VariablyModified; TypeBits.ContainsUnexpandedParameterPack = ContainsUnexpandedParameterPack; TypeBits.CacheValidAndVisibility = 0; @@ -1126,8 +1273,15 @@ protected: } friend class ASTContext; - void setDependent(bool D = true) { TypeBits.Dependent = D; } - void setVariablyModified(bool VM = true) { TypeBits.VariablyModified = VM; } + void setDependent(bool D = true) { + TypeBits.Dependent = D; + if (D) + TypeBits.InstantiationDependent = true; + } + void setInstantiationDependent(bool D = true) { + TypeBits.InstantiationDependent = D; } + void setVariablyModified(bool VM = true) { TypeBits.VariablyModified = VM; + } void setContainsUnexpandedParameterPack(bool PP = true) { TypeBits.ContainsUnexpandedParameterPack = PP; } @@ -1186,31 +1340,14 @@ public: return !isReferenceType() && !isFunctionType() && !isVoidType(); } - /// isPODType - Return true if this is a plain-old-data type (C++ 3.9p10). - bool isPODType() const; - /// isLiteralType - Return true if this is a literal type /// (C++0x [basic.types]p10) bool isLiteralType() const; - /// isTrivialType - Return true if this is a trivial type - /// (C++0x [basic.types]p9) - bool isTrivialType() const; - - /// isTriviallyCopyableType - Return true if this is a trivially copyable type - /// (C++0x [basic.types]p9 - bool isTriviallyCopyableType() const; - /// \brief Test if this type is a standard-layout type. /// (C++0x [basic.type]p9) bool isStandardLayoutType() const; - /// isCXX11PODType() - Return true if this is a POD type according to the - /// more relaxed rules of the C++11 standard, regardless of the current - /// compilation's language. - /// (C++0x [basic.types]p9) - bool isCXX11PODType() const; - /// Helper methods to distinguish type categories. All type predicates /// operate on the canonical type, ignoring typedefs and qualifiers. @@ -1290,7 +1427,11 @@ public: bool isComplexIntegerType() const; // GCC _Complex integer type. bool isVectorType() const; // GCC vector type. bool isExtVectorType() const; // Extended vector type. - bool isObjCObjectPointerType() const; // Pointer to *any* ObjC object. + bool isObjCObjectPointerType() const; // pointer to ObjC object + bool isObjCRetainableType() const; // ObjC object or block pointer + bool isObjCLifetimeType() const; // (array of)* retainable type + bool isObjCIndirectLifetimeType() const; // (pointer to)* lifetime type + bool isObjCNSObjectType() const; // __attribute__((NSObject)) // FIXME: change this to 'raw' interface type, so we can used 'interface' type // for the common case. bool isObjCObjectType() const; // NSString or typeof(*(id)0) @@ -1302,9 +1443,19 @@ public: bool isObjCClassType() const; // Class bool isObjCSelType() const; // Class bool isObjCBuiltinType() const; // 'id' or 'Class' + bool isObjCARCBridgableType() const; + bool isCARCBridgableType() const; bool isTemplateTypeParmType() const; // C++ template type parameter bool isNullPtrType() const; // C++0x nullptr_t + /// Determines if this type, which must satisfy + /// isObjCLifetimeType(), is implicitly __unsafe_unretained rather + /// than implicitly __strong. + bool isObjCARCImplicitlyUnretainedType() const; + + /// Return the implicit lifetime for this type, which must not be dependent. + Qualifiers::ObjCLifetime getObjCARCImplicitLifetime() const; + enum ScalarTypeKind { STK_Pointer, STK_MemberPointer, @@ -1322,6 +1473,14 @@ public: /// (C++ [temp.dep.type]). bool isDependentType() const { return TypeBits.Dependent; } + /// \brief Determine whether this type is an instantiation-dependent type, + /// meaning that the type involves a template parameter (even if the + /// definition does not actually depend on the type substituted for that + /// template parameter). + bool isInstantiationDependentType() const { + return TypeBits.InstantiationDependent; + } + /// \brief Whether this type is a variably-modified type (C99 6.7.5). bool isVariablyModifiedType() const { return TypeBits.VariablyModified; } @@ -1336,6 +1495,8 @@ public: /// \brief Determine wither this type is a C++ elaborated-type-specifier. bool isElaboratedTypeSpecifier() const; + + bool canDecayToPointerType() const; /// hasPointerRepresentation - Whether this type is represented /// natively as a pointer; this includes pointers, references, block @@ -1480,6 +1641,7 @@ public: } CanQualType getCanonicalTypeUnqualified() const; // in CanonicalType.h void dump() const; + static bool classof(const Type *) { return true; } friend class ASTReader; @@ -1586,6 +1748,7 @@ public: public: BuiltinType(Kind K) : Type(Builtin, QualType(), /*Dependent=*/(K == Dependent), + /*InstantiationDependent=*/(K == Dependent), /*VariablyModified=*/false, /*Unexpanded paramter pack=*/false) { BuiltinTypeBits.Kind = K; @@ -1631,6 +1794,7 @@ class ComplexType : public Type, public llvm::FoldingSetNode { QualType ElementType; ComplexType(QualType Element, QualType CanonicalPtr) : Type(Complex, CanonicalPtr, Element->isDependentType(), + Element->isInstantiationDependentType(), Element->isVariablyModifiedType(), Element->containsUnexpandedParameterPack()), ElementType(Element) { @@ -1661,6 +1825,7 @@ class ParenType : public Type, public llvm::FoldingSetNode { ParenType(QualType InnerType, QualType CanonType) : Type(Paren, CanonType, InnerType->isDependentType(), + InnerType->isInstantiationDependentType(), InnerType->isVariablyModifiedType(), InnerType->containsUnexpandedParameterPack()), Inner(InnerType) { @@ -1692,6 +1857,7 @@ class PointerType : public Type, public llvm::FoldingSetNode { PointerType(QualType Pointee, QualType CanonicalPtr) : Type(Pointer, CanonicalPtr, Pointee->isDependentType(), + Pointee->isInstantiationDependentType(), Pointee->isVariablyModifiedType(), Pointee->containsUnexpandedParameterPack()), PointeeType(Pointee) { @@ -1724,6 +1890,7 @@ class BlockPointerType : public Type, public llvm::FoldingSetNode { QualType PointeeType; // Block is some kind of pointer type BlockPointerType(QualType Pointee, QualType CanonicalCls) : Type(BlockPointer, CanonicalCls, Pointee->isDependentType(), + Pointee->isInstantiationDependentType(), Pointee->isVariablyModifiedType(), Pointee->containsUnexpandedParameterPack()), PointeeType(Pointee) { @@ -1760,6 +1927,7 @@ protected: ReferenceType(TypeClass tc, QualType Referencee, QualType CanonicalRef, bool SpelledAsLValue) : Type(tc, CanonicalRef, Referencee->isDependentType(), + Referencee->isInstantiationDependentType(), Referencee->isVariablyModifiedType(), Referencee->containsUnexpandedParameterPack()), PointeeType(Referencee) @@ -1844,6 +2012,8 @@ class MemberPointerType : public Type, public llvm::FoldingSetNode { MemberPointerType(QualType Pointee, const Type *Cls, QualType CanonicalPtr) : Type(MemberPointer, CanonicalPtr, Cls->isDependentType() || Pointee->isDependentType(), + (Cls->isInstantiationDependentType() || + Pointee->isInstantiationDependentType()), Pointee->isVariablyModifiedType(), (Cls->containsUnexpandedParameterPack() || Pointee->containsUnexpandedParameterPack())), @@ -1911,6 +2081,7 @@ protected: ArraySizeModifier sm, unsigned tq, bool ContainsUnexpandedParameterPack) : Type(tc, can, et->isDependentType() || tc == DependentSizedArray, + et->isInstantiationDependentType() || tc == DependentSizedArray, (tc == VariableArray || et->isVariablyModifiedType()), ContainsUnexpandedParameterPack), ElementType(et) { @@ -2344,28 +2515,32 @@ class FunctionType : public Type { // you'll need to adjust both the Bits field below and // Type::FunctionTypeBitfields. - // | CC |noreturn|hasregparm|regparm - // |0 .. 2| 3 | 4 |5 .. 7 + // | CC |noreturn|produces|regparm| + // |0 .. 2| 3 | 4 | 5 .. 7| + // + // regparm is either 0 (no regparm attribute) or the regparm value+1. enum { CallConvMask = 0x7 }; enum { NoReturnMask = 0x8 }; - enum { HasRegParmMask = 0x10 }; - enum { RegParmMask = ~(CallConvMask | NoReturnMask), - RegParmOffset = 5 }; + enum { ProducesResultMask = 0x10 }; + enum { RegParmMask = ~(CallConvMask | NoReturnMask | ProducesResultMask), + RegParmOffset = 5 }; // Assumed to be the last field - unsigned char Bits; + uint16_t Bits; - ExtInfo(unsigned Bits) : Bits(static_cast<unsigned char>(Bits)) {} + ExtInfo(unsigned Bits) : Bits(static_cast<uint16_t>(Bits)) {} friend class FunctionType; public: // Constructor with no defaults. Use this when you know that you // have all the elements (when reading an AST file for example). - ExtInfo(bool noReturn, bool hasRegParm, unsigned regParm, CallingConv cc) { + ExtInfo(bool noReturn, bool hasRegParm, unsigned regParm, CallingConv cc, + bool producesResult) { + assert((!hasRegParm || regParm < 7) && "Invalid regparm value"); Bits = ((unsigned) cc) | (noReturn ? NoReturnMask : 0) | - (hasRegParm ? HasRegParmMask : 0) | - (regParm << RegParmOffset); + (producesResult ? ProducesResultMask : 0) | + (hasRegParm ? ((regParm + 1) << RegParmOffset) : 0); } // Constructor with all defaults. Use when for example creating a @@ -2373,8 +2548,14 @@ class FunctionType : public Type { ExtInfo() : Bits(0) {} bool getNoReturn() const { return Bits & NoReturnMask; } - bool getHasRegParm() const { return Bits & HasRegParmMask; } - unsigned getRegParm() const { return Bits >> RegParmOffset; } + bool getProducesResult() const { return Bits & ProducesResultMask; } + bool getHasRegParm() const { return (Bits >> RegParmOffset) != 0; } + unsigned getRegParm() const { + unsigned RegParm = Bits >> RegParmOffset; + if (RegParm > 0) + --RegParm; + return RegParm; + } CallingConv getCC() const { return CallingConv(Bits & CallConvMask); } bool operator==(ExtInfo Other) const { @@ -2394,8 +2575,17 @@ class FunctionType : public Type { return ExtInfo(Bits & ~NoReturnMask); } + ExtInfo withProducesResult(bool producesResult) const { + if (producesResult) + return ExtInfo(Bits | ProducesResultMask); + else + return ExtInfo(Bits & ~ProducesResultMask); + } + ExtInfo withRegParm(unsigned RegParm) const { - return ExtInfo(HasRegParmMask | (Bits & ~RegParmMask) | (RegParm << RegParmOffset)); + assert(RegParm < 7 && "Invalid regparm value"); + return ExtInfo((Bits & ~RegParmMask) | + ((RegParm + 1) << RegParmOffset)); } ExtInfo withCallingConv(CallingConv cc) const { @@ -2411,9 +2601,10 @@ protected: FunctionType(TypeClass tc, QualType res, bool variadic, unsigned typeQuals, RefQualifierKind RefQualifier, QualType Canonical, bool Dependent, + bool InstantiationDependent, bool VariablyModified, bool ContainsUnexpandedParameterPack, ExtInfo Info) - : Type(tc, Canonical, Dependent, VariablyModified, + : Type(tc, Canonical, Dependent, InstantiationDependent, VariablyModified, ContainsUnexpandedParameterPack), ResultType(res) { FunctionTypeBits.ExtInfo = Info.Bits; @@ -2458,7 +2649,8 @@ public: class FunctionNoProtoType : public FunctionType, public llvm::FoldingSetNode { FunctionNoProtoType(QualType Result, QualType Canonical, ExtInfo Info) : FunctionType(FunctionNoProto, Result, false, 0, RQ_None, Canonical, - /*Dependent=*/false, Result->isVariablyModifiedType(), + /*Dependent=*/false, /*InstantiationDependent=*/false, + Result->isVariablyModifiedType(), /*ContainsUnexpandedParameterPack=*/false, Info) {} friend class ASTContext; // ASTContext creates these. @@ -2495,7 +2687,8 @@ public: struct ExtProtoInfo { ExtProtoInfo() : Variadic(false), ExceptionSpecType(EST_None), TypeQuals(0), - RefQualifier(RQ_None), NumExceptions(0), Exceptions(0), NoexceptExpr(0) {} + RefQualifier(RQ_None), NumExceptions(0), Exceptions(0), NoexceptExpr(0), + ConsumedArguments(0) {} FunctionType::ExtInfo ExtInfo; bool Variadic; @@ -2505,6 +2698,7 @@ public: unsigned NumExceptions; const QualType *Exceptions; Expr *NoexceptExpr; + const bool *ConsumedArguments; }; private: @@ -2523,7 +2717,7 @@ private: QualType canonical, const ExtProtoInfo &epi); /// NumArgs - The number of arguments this function has, not counting '...'. - unsigned NumArgs : 20; + unsigned NumArgs : 19; /// NumExceptions - The number of types in the exception spec, if any. unsigned NumExceptions : 9; @@ -2531,6 +2725,9 @@ private: /// ExceptionSpecType - The type of exception specification this function has. unsigned ExceptionSpecType : 3; + /// HasAnyConsumedArgs - Whether this function has any consumed arguments. + unsigned HasAnyConsumedArgs : 1; + /// ArgInfo - There is an variable size array after the class in memory that /// holds the argument types. @@ -2540,8 +2737,25 @@ private: /// NoexceptExpr - Instead of Exceptions, there may be a single Expr* pointing /// to the expression in the noexcept() specifier. + /// ConsumedArgs - A variable size array, following Exceptions + /// and of length NumArgs, holding flags indicating which arguments + /// are consumed. This only appears if HasAnyConsumedArgs is true. + friend class ASTContext; // ASTContext creates these. + const bool *getConsumedArgsBuffer() const { + assert(hasAnyConsumedArgs()); + + // Find the end of the exceptions. + Expr * const *eh_end = reinterpret_cast<Expr * const *>(arg_type_end()); + if (getExceptionSpecType() != EST_ComputedNoexcept) + eh_end += NumExceptions; + else + eh_end += 1; // NoexceptExpr + + return reinterpret_cast<const bool*>(eh_end); + } + public: unsigned getNumArgs() const { return NumArgs; } QualType getArgType(unsigned i) const { @@ -2562,6 +2776,8 @@ public: } else if (EPI.ExceptionSpecType == EST_ComputedNoexcept) { EPI.NoexceptExpr = getNoexceptExpr(); } + if (hasAnyConsumedArgs()) + EPI.ConsumedArguments = getConsumedArgsBuffer(); return EPI; } @@ -2647,6 +2863,16 @@ public: return exception_begin() + NumExceptions; } + bool hasAnyConsumedArgs() const { + return HasAnyConsumedArgs; + } + bool isArgConsumed(unsigned I) const { + assert(I < getNumArgs() && "argument index out of range!"); + if (hasAnyConsumedArgs()) + return getConsumedArgsBuffer()[I]; + return false; + } + bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -2670,7 +2896,7 @@ class UnresolvedUsingType : public Type { UnresolvedUsingTypenameDecl *Decl; UnresolvedUsingType(const UnresolvedUsingTypenameDecl *D) - : Type(UnresolvedUsing, QualType(), true, false, + : Type(UnresolvedUsing, QualType(), true, true, false, /*ContainsUnexpandedParameterPack=*/false), Decl(const_cast<UnresolvedUsingTypenameDecl*>(D)) {} friend class ASTContext; // ASTContext creates these. @@ -2700,7 +2926,9 @@ class TypedefType : public Type { TypedefNameDecl *Decl; protected: TypedefType(TypeClass tc, const TypedefNameDecl *D, QualType can) - : Type(tc, can, can->isDependentType(), can->isVariablyModifiedType(), + : Type(tc, can, can->isDependentType(), + can->isInstantiationDependentType(), + can->isVariablyModifiedType(), /*ContainsUnexpandedParameterPack=*/false), Decl(const_cast<TypedefNameDecl*>(D)) { assert(!isa<TypedefType>(can) && "Invalid canonical type"); @@ -2731,7 +2959,7 @@ public: QualType desugar() const; /// \brief Returns whether this type directly provides sugar. - bool isSugared() const { return true; } + bool isSugared() const; static bool classof(const Type *T) { return T->getTypeClass() == TypeOfExpr; } static bool classof(const TypeOfExprType *) { return true; } @@ -2751,9 +2979,6 @@ public: DependentTypeOfExprType(const ASTContext &Context, Expr *E) : TypeOfExprType(E), Context(Context) { } - bool isSugared() const { return false; } - QualType desugar() const { return QualType(this, 0); } - void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, Context, getUnderlyingExpr()); } @@ -2766,7 +2991,9 @@ public: class TypeOfType : public Type { QualType TOType; TypeOfType(QualType T, QualType can) - : Type(TypeOf, can, T->isDependentType(), T->isVariablyModifiedType(), + : Type(TypeOf, can, T->isDependentType(), + T->isInstantiationDependentType(), + T->isVariablyModifiedType(), T->containsUnexpandedParameterPack()), TOType(T) { assert(!isa<TypedefType>(can) && "Invalid canonical type"); @@ -2802,10 +3029,10 @@ public: QualType getUnderlyingType() const { return UnderlyingType; } /// \brief Remove a single level of sugar. - QualType desugar() const { return getUnderlyingType(); } + QualType desugar() const; /// \brief Returns whether this type directly provides sugar. - bool isSugared() const { return !isDependentType(); } + bool isSugared() const; static bool classof(const Type *T) { return T->getTypeClass() == Decltype; } static bool classof(const DecltypeType *) { return true; } @@ -2823,9 +3050,6 @@ class DependentDecltypeType : public DecltypeType, public llvm::FoldingSetNode { public: DependentDecltypeType(const ASTContext &Context, Expr *E); - bool isSugared() const { return false; } - QualType desugar() const { return QualType(this, 0); } - void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, Context, getUnderlyingExpr()); } @@ -2971,6 +3195,7 @@ public: // Enumerated operand (string or keyword). attr_objc_gc, + attr_objc_ownership, attr_pcs, FirstEnumOperandKind = attr_objc_gc, @@ -2994,6 +3219,7 @@ private: AttributedType(QualType canon, Kind attrKind, QualType modified, QualType equivalent) : Type(Attributed, canon, canon->isDependentType(), + canon->isInstantiationDependentType(), canon->isVariablyModifiedType(), canon->containsUnexpandedParameterPack()), ModifiedType(modified), EquivalentType(equivalent) { @@ -3046,13 +3272,16 @@ class TemplateTypeParmType : public Type, public llvm::FoldingSetNode { /// Build a non-canonical type. TemplateTypeParmType(TemplateTypeParmDecl *TTPDecl, QualType Canon) : Type(TemplateTypeParm, Canon, /*Dependent=*/true, + /*InstantiationDependent=*/true, /*VariablyModified=*/false, Canon->containsUnexpandedParameterPack()), TTPDecl(TTPDecl) { } /// Build the canonical type. TemplateTypeParmType(unsigned D, unsigned I, bool PP) - : Type(TemplateTypeParm, QualType(this, 0), /*Dependent=*/true, + : Type(TemplateTypeParm, QualType(this, 0), + /*Dependent=*/true, + /*InstantiationDependent=*/true, /*VariablyModified=*/false, PP) { CanTTPTInfo.Depth = D; CanTTPTInfo.Index = I; @@ -3112,6 +3341,7 @@ class SubstTemplateTypeParmType : public Type, public llvm::FoldingSetNode { SubstTemplateTypeParmType(const TemplateTypeParmType *Param, QualType Canon) : Type(SubstTemplateTypeParm, Canon, Canon->isDependentType(), + Canon->isInstantiationDependentType(), Canon->isVariablyModifiedType(), Canon->containsUnexpandedParameterPack()), Replaced(Param) { } @@ -3211,6 +3441,7 @@ class AutoType : public Type, public llvm::FoldingSetNode { AutoType(QualType DeducedType) : Type(Auto, DeducedType.isNull() ? QualType(this, 0) : DeducedType, /*Dependent=*/DeducedType.isNull(), + /*InstantiationDependent=*/DeducedType.isNull(), /*VariablyModified=*/false, /*ContainsParameterPack=*/false) { assert((DeducedType.isNull() || !DeducedType->isDependentType()) && "deduced a dependent type for auto"); @@ -3244,28 +3475,35 @@ public: static bool classof(const AutoType *T) { return true; } }; -/// \brief Represents the type of a template specialization as written -/// in the source code. +/// \brief Represents a type template specialization; the template +/// must be a class template, a type alias template, or a template +/// template parameter. A template which cannot be resolved to one of +/// these, e.g. because it is written with a dependent scope +/// specifier, is instead represented as a +/// @c DependentTemplateSpecializationType. /// -/// Template specialization types represent the syntactic form of a -/// template-id that refers to a type, e.g., @c vector<int>. Some -/// template specialization types are syntactic sugar, whose canonical -/// type will point to some other type node that represents the -/// instantiation or class template specialization. For example, a -/// class template specialization type of @c vector<int> will refer to -/// a tag type for the instantiation -/// @c std::vector<int, std::allocator<int>>. +/// A non-dependent template specialization type is always "sugar", +/// typically for a @c RecordType. For example, a class template +/// specialization type of @c vector<int> will refer to a tag type for +/// the instantiation @c std::vector<int, std::allocator<int>> /// -/// Other template specialization types, for which the template name -/// is dependent, may be canonical types. These types are always -/// dependent. +/// Template specializations are dependent if either the template or +/// any of the template arguments are dependent, in which case the +/// type may also be canonical. /// -/// An instance of this type is followed by an array of TemplateArgument*s, -/// then, if the template specialization type is for a type alias template, -/// a QualType representing the non-canonical aliased type. +/// Instances of this type are allocated with a trailing array of +/// TemplateArguments, followed by a QualType representing the +/// non-canonical aliased type when the template is a type alias +/// template. class TemplateSpecializationType : public Type, public llvm::FoldingSetNode { - /// \brief The name of the template being specialized. + /// \brief The name of the template being specialized. This is + /// either a TemplateName::Template (in which case it is a + /// ClassTemplateDecl*, a TemplateTemplateParmDecl*, or a + /// TypeAliasTemplateDecl*), a + /// TemplateName::SubstTemplateTemplateParmPack, or a + /// TemplateName::SubstTemplateTemplateParm (in which case the + /// replacement must, recursively, be one of these). TemplateName Template; /// \brief - The number of template arguments named in this class @@ -3283,12 +3521,15 @@ public: /// \brief Determine whether any of the given template arguments are /// dependent. static bool anyDependentTemplateArguments(const TemplateArgument *Args, - unsigned NumArgs); + unsigned NumArgs, + bool &InstantiationDependent); static bool anyDependentTemplateArguments(const TemplateArgumentLoc *Args, - unsigned NumArgs); + unsigned NumArgs, + bool &InstantiationDependent); - static bool anyDependentTemplateArguments(const TemplateArgumentListInfo &); + static bool anyDependentTemplateArguments(const TemplateArgumentListInfo &, + bool &InstantiationDependent); /// \brief Print a template argument list, including the '<' and '>' /// enclosing the template arguments. @@ -3399,6 +3640,7 @@ class InjectedClassNameType : public Type { // interdependencies. InjectedClassNameType(CXXRecordDecl *D, QualType TST) : Type(InjectedClassName, QualType(), /*Dependent=*/true, + /*InstantiationDependent=*/true, /*VariablyModified=*/false, /*ContainsUnexpandedParameterPack=*/false), Decl(D), InjectedType(TST) { @@ -3461,9 +3703,10 @@ enum ElaboratedTypeKeyword { class TypeWithKeyword : public Type { protected: TypeWithKeyword(ElaboratedTypeKeyword Keyword, TypeClass tc, - QualType Canonical, bool Dependent, bool VariablyModified, + QualType Canonical, bool Dependent, + bool InstantiationDependent, bool VariablyModified, bool ContainsUnexpandedParameterPack) - : Type(tc, Canonical, Dependent, VariablyModified, + : Type(tc, Canonical, Dependent, InstantiationDependent, VariablyModified, ContainsUnexpandedParameterPack) { TypeWithKeywordBits.Keyword = Keyword; } @@ -3523,6 +3766,7 @@ class ElaboratedType : public TypeWithKeyword, public llvm::FoldingSetNode { QualType NamedType, QualType CanonType) : TypeWithKeyword(Keyword, Elaborated, CanonType, NamedType->isDependentType(), + NamedType->isInstantiationDependentType(), NamedType->isVariablyModifiedType(), NamedType->containsUnexpandedParameterPack()), NNS(NNS), NamedType(NamedType) { @@ -3585,6 +3829,7 @@ class DependentNameType : public TypeWithKeyword, public llvm::FoldingSetNode { DependentNameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, const IdentifierInfo *Name, QualType CanonType) : TypeWithKeyword(Keyword, DependentName, CanonType, /*Dependent=*/true, + /*InstantiationDependent=*/true, /*VariablyModified=*/false, NNS->containsUnexpandedParameterPack()), NNS(NNS), Name(Name) { @@ -3738,6 +3983,7 @@ class PackExpansionType : public Type, public llvm::FoldingSetNode { PackExpansionType(QualType Pattern, QualType Canon, llvm::Optional<unsigned> NumExpansions) : Type(PackExpansion, Canon, /*Dependent=*/true, + /*InstantiationDependent=*/true, /*VariableModified=*/Pattern->isVariablyModifiedType(), /*ContainsUnexpandedParameterPack=*/false), Pattern(Pattern), @@ -3829,7 +4075,7 @@ protected: enum Nonce_ObjCInterface { Nonce_ObjCInterface }; ObjCObjectType(enum Nonce_ObjCInterface) - : Type(ObjCInterface, QualType(), false, false, false), + : Type(ObjCInterface, QualType(), false, false, false, false), BaseType(QualType(this_(), 0)) { ObjCObjectTypeBits.NumProtocols = 0; } @@ -3986,7 +4232,7 @@ class ObjCObjectPointerType : public Type, public llvm::FoldingSetNode { QualType PointeeType; ObjCObjectPointerType(QualType Canonical, QualType Pointee) - : Type(ObjCObjectPointer, Canonical, false, false, false), + : Type(ObjCObjectPointer, Canonical, false, false, false, false), PointeeType(Pointee) {} friend class ASTContext; // ASTContext creates these. @@ -4303,6 +4549,11 @@ inline QualType QualType::getNonReferenceType() const { return *this; } +inline bool QualType::isCForbiddenLValueType() const { + return ((getTypePtr()->isVoidType() && !hasQualifiers()) || + getTypePtr()->isFunctionType()); +} + /// \brief Tests whether the type is categorized as a fundamental type. /// /// \returns True for types specified in C++0x [basic.fundamental]. @@ -4480,6 +4731,11 @@ inline bool Type::isOverloadableType() const { return isDependentType() || isRecordType() || isEnumeralType(); } +/// \brief Determines whether this type can decay to a pointer type. +inline bool Type::canDecayToPointerType() const { + return isFunctionType() || isArrayType(); +} + inline bool Type::hasPointerRepresentation() const { return (isPointerType() || isReferenceType() || isBlockPointerType() || isObjCObjectPointerType() || isNullPtrType()); diff --git a/include/clang/Analysis/Analyses/UninitializedValues.h b/include/clang/Analysis/Analyses/UninitializedValues.h index b966f3a90fff..badb493a9df4 100644 --- a/include/clang/Analysis/Analyses/UninitializedValues.h +++ b/include/clang/Analysis/Analyses/UninitializedValues.h @@ -32,10 +32,16 @@ public: const VarDecl *vd, bool isAlwaysUninit) {} }; - + +struct UninitVariablesAnalysisStats { + unsigned NumVariablesAnalyzed; + unsigned NumBlockVisits; +}; + void runUninitializedVariablesAnalysis(const DeclContext &dc, const CFG &cfg, AnalysisContext &ac, - UninitVariablesHandler &handler); + UninitVariablesHandler &handler, + UninitVariablesAnalysisStats &stats); } #endif diff --git a/include/clang/Analysis/AnalysisContext.h b/include/clang/Analysis/AnalysisContext.h index 66c12a5384d4..6a1876e65900 100644 --- a/include/clang/Analysis/AnalysisContext.h +++ b/include/clang/Analysis/AnalysisContext.h @@ -107,6 +107,11 @@ public: void dumpCFG(); + /// \brief Returns true if we have built a CFG for this analysis context. + /// Note that this doesn't correspond to whether or not a valid CFG exists, it + /// corresponds to whether we *attempted* to build one. + bool isCFGBuilt() const { return builtCFG; } + ParentMap &getParentMap(); PseudoConstantAnalysis *getPseudoConstantAnalysis(); LiveVariables *getLiveVariables(); diff --git a/include/clang/Analysis/DomainSpecific/CocoaConventions.h b/include/clang/Analysis/DomainSpecific/CocoaConventions.h index 18e81fed79f8..5a4e06ff53e5 100644 --- a/include/clang/Analysis/DomainSpecific/CocoaConventions.h +++ b/include/clang/Analysis/DomainSpecific/CocoaConventions.h @@ -7,34 +7,45 @@ // //===----------------------------------------------------------------------===// // -// This file defines +// This file implements cocoa naming convention analysis. // //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_ANALYSIS_DS_COCOA #define LLVM_CLANG_ANALYSIS_DS_COCOA +#include "llvm/ADT/StringRef.h" #include "clang/AST/Type.h" namespace clang { + +class ObjCMethodDecl; + namespace ento { namespace cocoa { enum NamingConvention { NoConvention, CreateRule, InitRule }; - NamingConvention deriveNamingConvention(Selector S); + NamingConvention deriveNamingConvention(Selector S, const ObjCMethodDecl *MD); - static inline bool followsFundamentalRule(Selector S) { - return deriveNamingConvention(S) == CreateRule; + static inline bool followsFundamentalRule(Selector S, + const ObjCMethodDecl *MD) { + return deriveNamingConvention(S, MD) == CreateRule; } bool isRefType(QualType RetTy, llvm::StringRef Prefix, llvm::StringRef Name = llvm::StringRef()); - + + bool isCocoaObjectRef(QualType T); + +} + +namespace coreFoundation { bool isCFObjectRef(QualType T); - bool isCocoaObjectRef(QualType T); + bool followsCreateRule(llvm::StringRef functionName); +} -}}} +}} // end: "clang:ento" #endif diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index e4c6722e8378..e64dc6a2ade0 100644 --- a/include/clang/Basic/Attr.td +++ b/include/clang/Basic/Attr.td @@ -400,6 +400,11 @@ def ObjCNSObject : InheritableAttr { let Spellings = ["NSObject"]; } +def ObjCPreciseLifetime : Attr { + let Spellings = ["objc_precise_lifetime"]; + let Subjects = [Var]; +} + def Overloadable : Attr { let Spellings = ["overloadable"]; } @@ -479,6 +484,10 @@ def Unavailable : InheritableAttr { let Args = [StringArgument<"Message">]; } +def ArcWeakrefUnavailable : InheritableAttr { + let Spellings = ["objc_arc_weak_reference_unavailable"]; +} + def Unused : InheritableAttr { let Spellings = ["unused"]; } diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def index 9a4c768dc649..a3cc6156238e 100644 --- a/include/clang/Basic/Builtins.def +++ b/include/clang/Basic/Builtins.def @@ -604,6 +604,8 @@ BUILTIN(__builtin_rindex, "c*cC*i", "Fn") // Microsoft builtins. BUILTIN(__assume, "vb", "n") BUILTIN(__noop, "v.", "n") +BUILTIN(__debugbreak, "v", "n") + // C99 library functions // C99 stdlib.h @@ -727,6 +729,10 @@ LIBBUILTIN(cos, "dd", "fe", "math.h", ALL_LANGUAGES) LIBBUILTIN(cosl, "LdLd", "fe", "math.h", ALL_LANGUAGES) LIBBUILTIN(cosf, "ff", "fe", "math.h", ALL_LANGUAGES) +LIBBUILTIN(fma, "dddd", "fc", "math.h", ALL_LANGUAGES) +LIBBUILTIN(fmal, "LdLdLdLd", "fc", "math.h", ALL_LANGUAGES) +LIBBUILTIN(fmaf, "ffff", "fc", "math.h", ALL_LANGUAGES) + // Blocks runtime Builtin math library functions LIBBUILTIN(_Block_object_assign, "vv*vC*iC", "f", "Blocks.h", ALL_LANGUAGES) LIBBUILTIN(_Block_object_dispose, "vvC*iC", "f", "Blocks.h", ALL_LANGUAGES) diff --git a/include/clang/Basic/Builtins.h b/include/clang/Basic/Builtins.h index 0d17e03d8a52..7469e144c150 100644 --- a/include/clang/Basic/Builtins.h +++ b/include/clang/Basic/Builtins.h @@ -50,7 +50,6 @@ enum ID { struct Info { const char *Name, *Type, *Attributes, *HeaderName; LanguageID builtin_lang; - bool Suppressed; bool operator==(const Info &RHS) const { return !strcmp(Name, RHS.Name) && diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def index 6ef667db7beb..6bd901469cee 100644 --- a/include/clang/Basic/BuiltinsX86.def +++ b/include/clang/Basic/BuiltinsX86.def @@ -26,6 +26,7 @@ // 3DNow! // +BUILTIN(__builtin_ia32_femms, "v", "") BUILTIN(__builtin_ia32_pavgusb, "V8cV8cV8c", "nc") BUILTIN(__builtin_ia32_pf2id, "V2iV2f", "nc") BUILTIN(__builtin_ia32_pfacc, "V2fV2fV2f", "nc") @@ -47,7 +48,7 @@ BUILTIN(__builtin_ia32_pfsub, "V2fV2fV2f", "nc") BUILTIN(__builtin_ia32_pfsubr, "V2fV2fV2f", "nc") BUILTIN(__builtin_ia32_pi2fd, "V2fV2i", "nc") BUILTIN(__builtin_ia32_pmulhrw, "V4sV4sV4s", "nc") -// 3DNow! Extensions. +// 3DNow! Extensions (3dnowa). BUILTIN(__builtin_ia32_pf2iw, "V2iV2f", "nc") BUILTIN(__builtin_ia32_pfnacc, "V2fV2fV2f", "nc") BUILTIN(__builtin_ia32_pfpnacc, "V2fV2fV2f", "nc") @@ -57,15 +58,13 @@ BUILTIN(__builtin_ia32_pswapdsi, "V2iV2i", "nc") // MMX // -// FIXME: All MMX instructions will be generated via builtins. Any MMX vector +// All MMX instructions will be generated via builtins. Any MMX vector // types (<1 x i64>, <2 x i32>, etc.) that aren't used by these builtins will be // expanded by the back-end. BUILTIN(__builtin_ia32_emms, "v", "") -BUILTIN(__builtin_ia32_femms, "v", "") BUILTIN(__builtin_ia32_paddb, "V8cV8cV8c", "") BUILTIN(__builtin_ia32_paddw, "V4sV4sV4s", "") BUILTIN(__builtin_ia32_paddd, "V2iV2iV2i", "") -BUILTIN(__builtin_ia32_paddq, "V1LLiV1LLiV1LLi", "") BUILTIN(__builtin_ia32_paddsb, "V8cV8cV8c", "") BUILTIN(__builtin_ia32_paddsw, "V4sV4sV4s", "") BUILTIN(__builtin_ia32_paddusb, "V8cV8cV8c", "") @@ -73,27 +72,17 @@ BUILTIN(__builtin_ia32_paddusw, "V4sV4sV4s", "") BUILTIN(__builtin_ia32_psubb, "V8cV8cV8c", "") BUILTIN(__builtin_ia32_psubw, "V4sV4sV4s", "") BUILTIN(__builtin_ia32_psubd, "V2iV2iV2i", "") -BUILTIN(__builtin_ia32_psubq, "V1LLiV1LLiV1LLi", "") BUILTIN(__builtin_ia32_psubsb, "V8cV8cV8c", "") BUILTIN(__builtin_ia32_psubsw, "V4sV4sV4s", "") BUILTIN(__builtin_ia32_psubusb, "V8cV8cV8c", "") BUILTIN(__builtin_ia32_psubusw, "V4sV4sV4s", "") BUILTIN(__builtin_ia32_pmulhw, "V4sV4sV4s", "") BUILTIN(__builtin_ia32_pmullw, "V4sV4sV4s", "") -BUILTIN(__builtin_ia32_pmulhuw, "V4sV4sV4s", "") -BUILTIN(__builtin_ia32_pmuludq, "V1LLiV2iV2i", "") BUILTIN(__builtin_ia32_pmaddwd, "V2iV4sV4s", "") BUILTIN(__builtin_ia32_pand, "V1LLiV1LLiV1LLi", "") BUILTIN(__builtin_ia32_pandn, "V1LLiV1LLiV1LLi", "") BUILTIN(__builtin_ia32_por, "V1LLiV1LLiV1LLi", "") BUILTIN(__builtin_ia32_pxor, "V1LLiV1LLiV1LLi", "") -BUILTIN(__builtin_ia32_pavgb, "V8cV8cV8c", "") -BUILTIN(__builtin_ia32_pavgw, "V4sV4sV4s", "") -BUILTIN(__builtin_ia32_pmaxub, "V8cV8cV8c", "") -BUILTIN(__builtin_ia32_pmaxsw, "V4sV4sV4s", "") -BUILTIN(__builtin_ia32_pminub, "V8cV8cV8c", "") -BUILTIN(__builtin_ia32_pminsw, "V4sV4sV4s", "") -BUILTIN(__builtin_ia32_psadbw, "V4sV8cV8c", "") BUILTIN(__builtin_ia32_psllw, "V4sV4sV1LLi", "") BUILTIN(__builtin_ia32_pslld, "V2iV2iV1LLi", "") BUILTIN(__builtin_ia32_psllq, "V1LLiV1LLiV1LLi", "") @@ -113,7 +102,6 @@ BUILTIN(__builtin_ia32_psradi, "V2iV2ii", "") BUILTIN(__builtin_ia32_packsswb, "V8cV4sV4s", "") BUILTIN(__builtin_ia32_packssdw, "V4sV2iV2i", "") BUILTIN(__builtin_ia32_packuswb, "V8cV4sV4s", "") -BUILTIN(__builtin_ia32_pshufw, "V4sV4sIc", "") BUILTIN(__builtin_ia32_punpckhbw, "V8cV8cV8c", "") BUILTIN(__builtin_ia32_punpckhwd, "V4sV4sV4s", "") BUILTIN(__builtin_ia32_punpckhdq, "V2iV2iV2i", "") @@ -127,14 +115,53 @@ BUILTIN(__builtin_ia32_pcmpgtb, "V8cV8cV8c", "") BUILTIN(__builtin_ia32_pcmpgtw, "V4sV4sV4s", "") BUILTIN(__builtin_ia32_pcmpgtd, "V2iV2iV2i", "") BUILTIN(__builtin_ia32_maskmovq, "vV8cV8cc*", "") -BUILTIN(__builtin_ia32_pmovmskb, "iV8c", "") BUILTIN(__builtin_ia32_movntq, "vV1LLi*V1LLi", "") -BUILTIN(__builtin_ia32_palignr, "V8cV8cV8cIc", "") BUILTIN(__builtin_ia32_vec_init_v2si, "V2iii", "") BUILTIN(__builtin_ia32_vec_init_v4hi, "V4sssss", "") BUILTIN(__builtin_ia32_vec_init_v8qi, "V8ccccccccc", "") BUILTIN(__builtin_ia32_vec_ext_v2si, "iV2ii", "") +// MMX2 (MMX+SSE) intrinsics +BUILTIN(__builtin_ia32_cvtpi2ps, "V4fV4fV2i", "") +BUILTIN(__builtin_ia32_cvtps2pi, "V2iV4f", "") +BUILTIN(__builtin_ia32_cvttps2pi, "V2iV4f", "") +BUILTIN(__builtin_ia32_pavgb, "V8cV8cV8c", "") +BUILTIN(__builtin_ia32_pavgw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_pmaxsw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_pmaxub, "V8cV8cV8c", "") +BUILTIN(__builtin_ia32_pminsw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_pminub, "V8cV8cV8c", "") +BUILTIN(__builtin_ia32_pmovmskb, "iV8c", "") +BUILTIN(__builtin_ia32_pmulhuw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_psadbw, "V4sV8cV8c", "") +BUILTIN(__builtin_ia32_pshufw, "V4sV4sIc", "") + +// MMX+SSE2 +BUILTIN(__builtin_ia32_cvtpd2pi, "V2iV2d", "") +BUILTIN(__builtin_ia32_cvtpi2pd, "V2dV2i", "") +BUILTIN(__builtin_ia32_cvttpd2pi, "V2iV2d", "") +BUILTIN(__builtin_ia32_paddq, "V1LLiV1LLiV1LLi", "") +BUILTIN(__builtin_ia32_pmuludq, "V1LLiV2iV2i", "") +BUILTIN(__builtin_ia32_psubq, "V1LLiV1LLiV1LLi", "") + +// MMX+SSSE3 +BUILTIN(__builtin_ia32_pabsb, "V8cV8c", "") +BUILTIN(__builtin_ia32_pabsd, "V2iV2i", "") +BUILTIN(__builtin_ia32_pabsw, "V4sV4s", "") +BUILTIN(__builtin_ia32_palignr, "V8cV8cV8cIc", "") +BUILTIN(__builtin_ia32_phaddd, "V2iV2iV2i", "") +BUILTIN(__builtin_ia32_phaddsw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_phaddw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_phsubd, "V2iV2iV2i", "") +BUILTIN(__builtin_ia32_phsubsw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_phsubw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_pmaddubsw, "V8cV8cV8c", "") +BUILTIN(__builtin_ia32_pmulhrsw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_pshufb, "V8cV8cV8c", "") +BUILTIN(__builtin_ia32_psignw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_psignb, "V8cV8cV8c", "") +BUILTIN(__builtin_ia32_psignd, "V2iV2iV2i", "") + // SSE intrinsics. BUILTIN(__builtin_ia32_comieq, "iV4fV4f", "") BUILTIN(__builtin_ia32_comilt, "iV4fV4f", "") @@ -204,42 +231,24 @@ BUILTIN(__builtin_ia32_haddpd, "V2dV2dV2d", "") BUILTIN(__builtin_ia32_hsubps, "V4fV4fV4f", "") BUILTIN(__builtin_ia32_hsubpd, "V2dV2dV2d", "") BUILTIN(__builtin_ia32_phaddw128, "V8sV8sV8s", "") -BUILTIN(__builtin_ia32_phaddw, "V4sV4sV4s", "") BUILTIN(__builtin_ia32_phaddd128, "V4iV4iV4i", "") -BUILTIN(__builtin_ia32_phaddd, "V2iV2iV2i", "") BUILTIN(__builtin_ia32_phaddsw128, "V8sV8sV8s", "") -BUILTIN(__builtin_ia32_phaddsw, "V4sV4sV4s", "") BUILTIN(__builtin_ia32_phsubw128, "V8sV8sV8s", "") -BUILTIN(__builtin_ia32_phsubw, "V4sV4sV4s", "") BUILTIN(__builtin_ia32_phsubd128, "V4iV4iV4i", "") -BUILTIN(__builtin_ia32_phsubd, "V2iV2iV2i", "") BUILTIN(__builtin_ia32_phsubsw128, "V8sV8sV8s", "") -BUILTIN(__builtin_ia32_phsubsw, "V4sV4sV4s", "") BUILTIN(__builtin_ia32_pmaddubsw128, "V16cV16cV16c", "") -BUILTIN(__builtin_ia32_pmaddubsw, "V8cV8cV8c", "") BUILTIN(__builtin_ia32_pmulhrsw128, "V8sV8sV8s", "") -BUILTIN(__builtin_ia32_pmulhrsw, "V4sV4sV4s", "") BUILTIN(__builtin_ia32_pshufb128, "V16cV16cV16c", "") -BUILTIN(__builtin_ia32_pshufb, "V8cV8cV8c", "") BUILTIN(__builtin_ia32_psignb128, "V16cV16cV16c", "") -BUILTIN(__builtin_ia32_psignb, "V8cV8cV8c", "") BUILTIN(__builtin_ia32_psignw128, "V8sV8sV8s", "") -BUILTIN(__builtin_ia32_psignw, "V4sV4sV4s", "") BUILTIN(__builtin_ia32_psignd128, "V4iV4iV4i", "") -BUILTIN(__builtin_ia32_psignd, "V2iV2iV2i", "") BUILTIN(__builtin_ia32_pabsb128, "V16cV16c", "") -BUILTIN(__builtin_ia32_pabsb, "V8cV8c", "") BUILTIN(__builtin_ia32_pabsw128, "V8sV8s", "") -BUILTIN(__builtin_ia32_pabsw, "V4sV4s", "") BUILTIN(__builtin_ia32_pabsd128, "V4iV4i", "") -BUILTIN(__builtin_ia32_pabsd, "V2iV2i", "") BUILTIN(__builtin_ia32_ldmxcsr, "vUi", "") BUILTIN(__builtin_ia32_stmxcsr, "Ui", "") -BUILTIN(__builtin_ia32_cvtpi2ps, "V4fV4fV2i", "") -BUILTIN(__builtin_ia32_cvtps2pi, "V2iV4f", "") BUILTIN(__builtin_ia32_cvtss2si, "iV4f", "") BUILTIN(__builtin_ia32_cvtss2si64, "LLiV4f", "") -BUILTIN(__builtin_ia32_cvttps2pi, "V2iV4f", "") BUILTIN(__builtin_ia32_storeups, "vf*V4f", "") BUILTIN(__builtin_ia32_storehps, "vV2i*V4f", "") BUILTIN(__builtin_ia32_storelps, "vV2i*V4f", "") @@ -265,11 +274,8 @@ BUILTIN(__builtin_ia32_sqrtsd, "V2dV2d", "") BUILTIN(__builtin_ia32_cvtdq2pd, "V2dV4i", "") BUILTIN(__builtin_ia32_cvtdq2ps, "V4fV4i", "") BUILTIN(__builtin_ia32_cvtpd2dq, "V2LLiV2d", "") -BUILTIN(__builtin_ia32_cvtpd2pi, "V2iV2d", "") BUILTIN(__builtin_ia32_cvtpd2ps, "V4fV2d", "") BUILTIN(__builtin_ia32_cvttpd2dq, "V4iV2d", "") -BUILTIN(__builtin_ia32_cvttpd2pi, "V2iV2d", "") -BUILTIN(__builtin_ia32_cvtpi2pd, "V2dV2i", "") BUILTIN(__builtin_ia32_cvtsd2si, "iV2d", "") BUILTIN(__builtin_ia32_cvtsd2si64, "LLiV2d", "") BUILTIN(__builtin_ia32_cvtps2dq, "V4iV4f", "") diff --git a/include/clang/Basic/DelayedCleanupPool.h b/include/clang/Basic/DelayedCleanupPool.h new file mode 100644 index 000000000000..843205f7b011 --- /dev/null +++ b/include/clang/Basic/DelayedCleanupPool.h @@ -0,0 +1,109 @@ +//=== DelayedCleanupPool.h - Delayed Clean-up Pool Implementation *- 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 facility to delay calling cleanup methods until specific +// points. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_BASIC_DELAYEDCLEANUPPOOL_H +#define LLVM_CLANG_BASIC_DELAYEDCLEANUPPOOL_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" + +namespace clang { + +/// \brief Gathers pairs of pointer-to-object/pointer-to-cleanup-function +/// allowing the cleanup functions to get called (with the pointer as parameter) +/// at specific points. +/// +/// The use case is to simplify clean-up of certain resources that, while their +/// lifetime is well-known and restricted, cleaning them up manually is easy to +/// miss and cause a leak. +/// +/// The same pointer can be added multiple times; its clean-up function will +/// only be called once. +class DelayedCleanupPool { +public: + typedef void (*CleanupFn)(void *ptr); + + /// \brief Adds a pointer and its associated cleanup function to be called + /// at a later point. + /// + /// \returns false if the pointer is already added, true otherwise. + bool delayCleanup(void *ptr, CleanupFn fn) { + assert(ptr && "Expected valid pointer to object"); + assert(fn && "Expected valid pointer to function"); + + CleanupFn &mapFn = Ptrs[ptr]; + assert((!mapFn || mapFn == fn) && + "Adding a pointer with different cleanup function!"); + + if (!mapFn) { + mapFn = fn; + Cleanups.push_back(std::make_pair(ptr, fn)); + return true; + } + + return false; + } + + template <typename T> + bool delayDelete(T *ptr) { + return delayCleanup(ptr, cleanupWithDelete<T>); + } + + template <typename T, void (T::*Fn)()> + bool delayMemberFunc(T *ptr) { + return delayCleanup(ptr, cleanupWithMemberFunc<T, Fn>); + } + + void doCleanup() { + for (llvm::SmallVector<std::pair<void *, CleanupFn>, 8>::reverse_iterator + I = Cleanups.rbegin(), E = Cleanups.rend(); I != E; ++I) + I->second(I->first); + Cleanups.clear(); + Ptrs.clear(); + } + + ~DelayedCleanupPool() { + doCleanup(); + } + +private: + llvm::DenseMap<void *, CleanupFn> Ptrs; + llvm::SmallVector<std::pair<void *, CleanupFn>, 8> Cleanups; + + template <typename T> + static void cleanupWithDelete(void *ptr) { + delete static_cast<T *>(ptr); + } + + template <typename T, void (T::*Fn)()> + static void cleanupWithMemberFunc(void *ptr) { + (static_cast<T *>(ptr)->*Fn)(); + } +}; + +/// \brief RAII object for triggering a cleanup of a DelayedCleanupPool. +class DelayedCleanupPoint { + DelayedCleanupPool &Pool; + +public: + DelayedCleanupPoint(DelayedCleanupPool &pool) : Pool(pool) { } + + ~DelayedCleanupPoint() { + Pool.doCleanup(); + } +}; + +} // end namespace clang + +#endif diff --git a/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h index fa763246d1b8..6f72976bfcf0 100644 --- a/include/clang/Basic/Diagnostic.h +++ b/include/clang/Basic/Diagnostic.h @@ -251,6 +251,14 @@ private: bool ErrorOccurred; bool FatalErrorOccurred; + /// \brief Indicates that an unrecoverable error has occurred. + bool UnrecoverableErrorOccurred; + + /// \brief Toggles for DiagnosticErrorTrap to check whether an error occurred + /// during a parsing section, e.g. during parsing a function. + bool TrapErrorOccurred; + bool TrapUnrecoverableErrorOccurred; + /// LastDiagLevel - This is the level of the last diagnostic emitted. This is /// used to emit continuation diagnostics with the same level as the /// diagnostic that they follow. @@ -269,13 +277,15 @@ private: /// can use this information to avoid redundancy across arguments. /// /// This is a hack to avoid a layering violation between libbasic and libsema. - typedef void (*ArgToStringFnTy)(ArgumentKind Kind, intptr_t Val, - const char *Modifier, unsigned ModifierLen, - const char *Argument, unsigned ArgumentLen, - const ArgumentValue *PrevArgs, - unsigned NumPrevArgs, - llvm::SmallVectorImpl<char> &Output, - void *Cookie); + typedef void (*ArgToStringFnTy)( + ArgumentKind Kind, intptr_t Val, + const char *Modifier, unsigned ModifierLen, + const char *Argument, unsigned ArgumentLen, + const ArgumentValue *PrevArgs, + unsigned NumPrevArgs, + llvm::SmallVectorImpl<char> &Output, + void *Cookie, + llvm::SmallVectorImpl<intptr_t> &QualTypeVals); void *ArgToStringCookie; ArgToStringFnTy ArgToStringFn; @@ -432,7 +442,12 @@ public: bool hasErrorOccurred() const { return ErrorOccurred; } bool hasFatalErrorOccurred() const { return FatalErrorOccurred; } - + + /// \brief Determine whether any kind of unrecoverable error has occurred. + bool hasUnrecoverableErrorOccurred() const { + return FatalErrorOccurred || UnrecoverableErrorOccurred; + } + unsigned getNumWarnings() const { return NumWarnings; } void setNumWarnings(unsigned NumWarnings) { @@ -452,9 +467,11 @@ public: const char *Modifier, unsigned ModLen, const char *Argument, unsigned ArgLen, const ArgumentValue *PrevArgs, unsigned NumPrevArgs, - llvm::SmallVectorImpl<char> &Output) const { + llvm::SmallVectorImpl<char> &Output, + llvm::SmallVectorImpl<intptr_t> &QualTypeVals) const { ArgToStringFn(Kind, Val, Modifier, ModLen, Argument, ArgLen, - PrevArgs, NumPrevArgs, Output, ArgToStringCookie); + PrevArgs, NumPrevArgs, Output, ArgToStringCookie, + QualTypeVals); } void SetArgToStringFn(ArgToStringFnTy Fn, void *Cookie) { @@ -621,20 +638,28 @@ private: /// queried. class DiagnosticErrorTrap { Diagnostic &Diag; - unsigned PrevErrors; public: explicit DiagnosticErrorTrap(Diagnostic &Diag) - : Diag(Diag), PrevErrors(Diag.NumErrors) {} + : Diag(Diag) { reset(); } /// \brief Determine whether any errors have occurred since this /// object instance was created. bool hasErrorOccurred() const { - return Diag.NumErrors > PrevErrors; + return Diag.TrapErrorOccurred; + } + + /// \brief Determine whether any unrecoverable errors have occurred since this + /// object instance was created. + bool hasUnrecoverableErrorOccurred() const { + return Diag.TrapUnrecoverableErrorOccurred; } // Set to initial state of "no errors occurred". - void reset() { PrevErrors = Diag.NumErrors; } + void reset() { + Diag.TrapErrorOccurred = false; + Diag.TrapUnrecoverableErrorOccurred = false; + } }; //===----------------------------------------------------------------------===// diff --git a/include/clang/Basic/DiagnosticCategories.h b/include/clang/Basic/DiagnosticCategories.h new file mode 100644 index 000000000000..4dd067ba1e98 --- /dev/null +++ b/include/clang/Basic/DiagnosticCategories.h @@ -0,0 +1,26 @@ +//===- DiagnosticCategories.h - Diagnostic Categories Enumerators-*- C++ -*===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_BASIC_DIAGNOSTICCATEGORIES_H +#define LLVM_CLANG_BASIC_DIAGNOSTICCATEGORIES_H + +namespace clang { + namespace diag { + enum { +#define GET_CATEGORY_TABLE +#define CATEGORY(X, ENUM) ENUM, +#include "clang/Basic/DiagnosticGroups.inc" +#undef CATEGORY +#undef GET_CATEGORY_TABLE + DiagCat_NUM_CATEGORIES + }; + } // end namespace diag +} // end namespace clang + +#endif diff --git a/include/clang/Basic/DiagnosticCommonKinds.td b/include/clang/Basic/DiagnosticCommonKinds.td index 50110fb53729..4b5de366cbc0 100644 --- a/include/clang/Basic/DiagnosticCommonKinds.td +++ b/include/clang/Basic/DiagnosticCommonKinds.td @@ -32,6 +32,7 @@ def note_type_being_defined : Note< def note_matching : Note<"to match this '%0'">; def note_using : Note<"using">; +def note_possibility : Note<"one possibility">; def note_also_found : Note<"also found">; // Parse && Lex diff --git a/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td index 908a69b162c4..e33b67ef7a07 100644 --- a/include/clang/Basic/DiagnosticDriverKinds.td +++ b/include/clang/Basic/DiagnosticDriverKinds.td @@ -82,6 +82,12 @@ def err_drv_conflicting_deployment_targets : Error< "conflicting deployment targets, both '%0' and '%1' are present in environment">; def err_drv_invalid_arch_for_deployment_target : Error< "invalid architecture '%0' for deployment target '%1'">; +def err_drv_objc_gc_arr : Error< + "cannot specify both '-fobjc-arc' and '%0'">; +def err_arc_nonfragile_abi : Error< + "-fobjc-arc is not supported with fragile abi">; +def err_drv_mg_requires_m_or_mm : Error< + "option '-MG' requires '-M' or '-MM'">; def warn_c_kext : Warning< "ignoring -fapple-kext which is valid for c++ and objective-c++ only">; diff --git a/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td index 4aa85134aae4..120ba67dc1f6 100644 --- a/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/include/clang/Basic/DiagnosticFrontendKinds.td @@ -137,6 +137,9 @@ def warn_pch_nonfragile_abi2 : Error< "PCH file was compiled with the %select{32-bit|enhanced non-fragile}0 " "Objective-C ABI but the %select{32-bit|enhanced non-fragile}1 " "Objective-C ABI is selected">; +def warn_pch_auto_ref_count : Error< + "PCH file was compiled %select{without|with} automated reference counting," + "which is currently %select{disabled|enabled}">; def warn_pch_apple_kext : Error< "PCH file was compiled %select{with|without}0 support for Apple's kernel " "extensions ABI but it is currently %select{disabled|enabled}1">; diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index 9abd6d3c5769..8a109149884f 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -62,6 +62,7 @@ def ExitTimeDestructors : DiagGroup<"exit-time-destructors">; def FourByteMultiChar : DiagGroup<"four-char-constants">; def GlobalConstructors : DiagGroup<"global-constructors">; def : DiagGroup<"idiomatic-parentheses">; +def BitwiseOpParentheses: DiagGroup<"bitwise-op-parentheses">; def LogicalOpParentheses: DiagGroup<"logical-op-parentheses">; def IgnoredQualifiers : DiagGroup<"ignored-qualifiers">; def : DiagGroup<"import">; @@ -115,6 +116,7 @@ def SignCompare : DiagGroup<"sign-compare">; def : DiagGroup<"stack-protector">; def : DiagGroup<"switch-default">; def : DiagGroup<"synth">; +def SizeofArrayArgument : DiagGroup<"sizeof-array-argument">; def TautologicalCompare : DiagGroup<"tautological-compare">; def HeaderHygiene : DiagGroup<"header-hygiene">; @@ -168,6 +170,15 @@ def ImplicitAtomic : DiagGroup<"implicit-atomic-properties">; def CustomAtomic : DiagGroup<"custom-atomic-properties">; def AtomicProperties : DiagGroup<"atomic-properties", [ImplicitAtomic, CustomAtomic]>; +def AutomaticReferenceCountingABI : DiagGroup<"arc-abi">; +def ARCUnsafeRetainedAssign : DiagGroup<"arc-unsafe-retained-assign">; +def ARCRetainCycles : DiagGroup<"arc-retain-cycles">; +def ARCNonPodMemAccess : DiagGroup<"arc-non-pod-memaccess">; +def AutomaticReferenceCounting : DiagGroup<"arc", + [AutomaticReferenceCountingABI, + ARCUnsafeRetainedAssign, + ARCRetainCycles, + ARCNonPodMemAccess]>; def Selector : DiagGroup<"selector">; def NonfragileAbi2 : DiagGroup<"nonfragile-abi2">; def Protocol : DiagGroup<"protocol">; @@ -192,7 +203,8 @@ def DuplicateArgDecl : DiagGroup<"duplicate-method-arg">; // in -Wparentheses because most users who use -Wparentheses explicitly // do not want these warnings. def Parentheses : DiagGroup<"parentheses", - [LogicalOpParentheses]>; + [LogicalOpParentheses, + BitwiseOpParentheses]>; // -Wconversion has its own warnings, but we split a few out for // legacy reasons: @@ -217,12 +229,12 @@ def Unused : DiagGroup<"unused", // Format settings. def FormatSecurity : DiagGroup<"format-security">; +def FormatY2K : DiagGroup<"format-y2k">; def Format : DiagGroup<"format", [FormatExtraArgs, FormatZeroLength, NonNull, - FormatSecurity]>, + FormatSecurity, FormatY2K]>, DiagCategory<"Format String Issue">; def FormatNonLiteral : DiagGroup<"format-nonliteral", [FormatSecurity]>; -def FormatY2K : DiagGroup<"format-y2k", [Format]>; def Format2 : DiagGroup<"format=2", [FormatNonLiteral, FormatSecurity, FormatY2K]>; @@ -248,6 +260,7 @@ def Most : DiagGroup<"most", [ ReturnType, SelfAssignment, Switch, + SizeofArrayArgument, Trigraphs, Uninitialized, UnknownPragmas, @@ -283,3 +296,6 @@ def GNU : DiagGroup<"gnu", [GNUDesignator, VLA]>; // A warning group for warnings about Microsoft extensions. def Microsoft : DiagGroup<"microsoft">; + +def ObjCNonUnifiedException : DiagGroup<"objc-nonunified-exceptions">; + diff --git a/include/clang/Basic/DiagnosticIDs.h b/include/clang/Basic/DiagnosticIDs.h index fa816de4fddb..ae4ed5bbb13c 100644 --- a/include/clang/Basic/DiagnosticIDs.h +++ b/include/clang/Basic/DiagnosticIDs.h @@ -227,6 +227,10 @@ private: /// suppressed. bool ProcessDiag(Diagnostic &Diag) const; + /// \brief Whether the diagnostic may leave the AST in a state where some + /// invariants can break. + bool isUnrecoverable(unsigned DiagID) const; + friend class Diagnostic; }; diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td index 3514ccace22a..38d6a8001655 100644 --- a/include/clang/Basic/DiagnosticLexKinds.td +++ b/include/clang/Basic/DiagnosticLexKinds.td @@ -178,7 +178,7 @@ def ext_empty_fnmacro_arg : Extension< def err_pp_invalid_directive : Error<"invalid preprocessing directive">; def err_pp_hash_error : Error<"#error%0">; -def err_pp_file_not_found : Error<"'%0' file not found">, DefaultFatal; +def warn_pp_file_not_found : Warning<"'%0' file not found">, DefaultFatal; def err_pp_error_opening_file : Error< "error opening file '%0': %1">, DefaultFatal; def err_pp_empty_filename : Error<"empty filename">; diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index fb1c90950822..3764a4091546 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -263,6 +263,11 @@ def warn_objc_protocol_qualifier_missing_id : Warning< def err_objc_unknown_at : Error<"expected an Objective-C directive after '@'">; def err_illegal_super_cast : Error< "cannot cast 'super' (it isn't an expression)">; + +let CategoryName = "Automatic Reference Counting Issue" in { +def err_arc_bridge_retain : Error< + "unknown cast annotation __bridge_retain; did you mean __bridge_retained?">; +} def err_objc_illegal_visibility_spec : Error< "illegal visibility specification">; diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 5cfa61b3972d..97414f23d796 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -48,6 +48,8 @@ def err_vla_decl_has_static_storage : Error< "variable length array declaration can not have 'static' storage duration">; def err_vla_decl_has_extern_linkage : Error< "variable length array declaration can not have 'extern' linkage">; +def ext_vla_folded_to_constant : Extension< + "variable length array folded to constant array as an extension">; // C99 variably modified types def err_variably_modified_template_arg : Error< @@ -267,6 +269,15 @@ def warn_dyn_class_memaccess : Warning< InGroup<DiagGroup<"dynamic-class-memaccess">>; def note_bad_memaccess_silence : Note< "explicitly cast the pointer to silence this warning">; +def warn_sizeof_pointer_expr_memaccess : Warning< + "argument to 'sizeof' in %0 call is the same expression as the " + "%select{destination|source}1; did you mean to " + "%select{dereference it|remove the addressof|provide an explicit length}2?">, + InGroup<DiagGroup<"sizeof-pointer-memaccess">>; +def warn_sizeof_pointer_type_memaccess : Warning< + "argument to 'sizeof' in %0 call is the same pointer type %1 as the " + "%select{destination|source}2; expected %3 or an explicit length">, + InGroup<DiagGroup<"sizeof-pointer-memaccess">>; /// main() // static/inline main() are not errors in C, just in C++. @@ -319,6 +330,8 @@ def err_duplicate_class_def : Error< "duplicate interface definition for class %0">; def err_undef_superclass : Error< "cannot find interface declaration for %0, superclass of %1">; +def err_forward_superclass : Error< + "attempting to use the forward class %0 as superclass of %1">; def err_no_nsconstant_string_class : Error< "cannot find interface declaration for %0">; def err_recursive_superclass : Error< @@ -344,6 +357,8 @@ def err_class_extension_after_impl : Error< "cannot declare class extension for %0 after class implementation">; def note_implementation_declared : Note< "class implementation is declared here">; +def note_class_declared : Note< + "class is declared here">; def warn_dup_category_def : Warning< "duplicate definition of category %1 on interface %0">; def err_conflicting_super_class : Error<"conflicting super class name %0">; @@ -425,6 +440,15 @@ def warn_objc_property_copy_missing_on_block : Warning< def warn_atomic_property_rule : Warning< "writable atomic property %0 cannot pair a synthesized setter/getter " "with a user defined setter/getter">; +def warn_ownin_getter_rule : Warning< + "property's synthesized getter follows Cocoa naming" + " convention for returning 'owned' objects">; +def warn_property_getter_owning_mismatch : Warning< + "property declared as returning non-retained objects" + "; getter returning retained objects">; +def err_ownin_getter_rule : Error< + "property's synthesized getter follows Cocoa naming" + " convention for returning 'owned' objects">; def warn_default_atomic_custom_getter_setter : Warning< "atomic by default property %0 has a user defined %select{getter|setter}1 " "(property should be marked 'atomic' if this is intended)">, @@ -460,6 +484,12 @@ def error_bad_property_context : Error< def error_missing_property_ivar_decl : Error< "synthesized property %0 must either be named the same as a compatible" " ivar or must explicitly name an ivar">; +def error_synthesize_weak_non_arc_or_gc : Error< + "@synthesize of 'weak' property is only allowed in ARC or GC mode">; +def err_arc_perform_selector_retains : Error< + "performSelector names a selector which retains the object">; +def warn_arc_perform_selector_leaks : Warning< + "performSelector may cause a leak because its selector is unknown">; def error_synthesized_ivar_yet_not_supported : Error< "instance variable synthesis not yet supported" @@ -472,7 +502,7 @@ def error_ivar_in_superclass_use : Error< def error_weak_property : Error< "existing ivar %1 for __weak property %0 must be __weak">; def error_strong_property : Error< - "property %0 must be declared __weak to match existing ivar %1 with __weak attribute">; + "existing ivar %1 for strong property %0 may not be __weak">; def error_dynamic_property_ivar_decl : Error< "dynamic property can not have ivar specification">; def error_duplicate_ivar_use : Error< @@ -729,8 +759,6 @@ def err_not_integral_type_bitfield : Error< "bit-field %0 has non-integral type %1">; def err_not_integral_type_anon_bitfield : Error< "anonymous bit-field has non-integral type %0">; -def err_member_initialization : Error< - "fields can only be initialized in constructors">; def err_member_function_initialization : Error< "initializer on function does not look like a pure-specifier">; def err_non_virtual_pure : Error< @@ -1135,6 +1163,8 @@ def err_format_attribute_implicit_this_format_string : Error< "format attribute cannot specify the implicit this argument as the format " "string">; def warn_unknown_method_family : Warning<"unrecognized method family">; +def err_init_method_bad_return_type : Error< + "init methods must return an object pointer type, not %0">; def err_attribute_invalid_size : Error< "vector size not an integral multiple of component size">; def err_attribute_zero_size : Error<"zero vector size">; @@ -1160,6 +1190,10 @@ def err_as_qualified_auto_decl : Error< "automatic variable qualified with an address space">; def err_arg_with_address_space : Error< "parameter may not be qualified with an address space">; +def err_attr_objc_ownership_bad_type : Error< + "the type %0 cannot be retained">; +def err_attr_objc_ownership_redundant : Error< + "the type %0 already has retainment attributes set on it">; def err_attribute_not_string : Error< "argument to %0 attribute was not a string literal">; def err_attribute_section_invalid_for_target : Error< @@ -1215,6 +1249,8 @@ def warn_function_attribute_wrong_type : Warning< "'%0' only applies to function types; type here is %1">; def warn_pointer_attribute_wrong_type : Warning< "'%0' only applies to pointer types; type here is %1">; +def warn_objc_object_attribute_wrong_type : Warning< + "'%0' only applies to objective-c object or block pointer types; type here is %1">; def warn_gnu_inline_attribute_requires_inline : Warning< "'gnu_inline' attribute requires function to be marked 'inline'," " attribute ignored">; @@ -1232,6 +1268,13 @@ def err_cconv_varargs : Error< def err_regparm_mismatch : Error<"function declared with with regparm(%0) " "attribute was previously declared " "%plural{0:without the regparm|:with the regparm(%1)}1 attribute">; +def err_objc_precise_lifetime_bad_type : Error< + "objc_precise_lifetime only applies to retainable types; type here is %0">; +def warn_objc_precise_lifetime_meaningless : Error< + "objc_precise_lifetime is not meaningful for " + "%select{__unsafe_unretained|__autoreleasing}0 objects">; +def warn_label_attribute_not_unused : Warning< + "The only valid attribute for labels is 'unused'">; def err_invalid_pcs : Error<"Invalid PCS type">; // Availability attribute @@ -1505,7 +1548,13 @@ def note_ovl_candidate_arity : Note<"candidate " def note_ovl_candidate_deleted : Note< "candidate %select{function|function|constructor|" - "function |function |constructor ||||constructor (inherited)}0%1 " + "function |function |constructor |" + "constructor (the implicit default constructor)|" + "constructor (the implicit copy constructor)|" + "constructor (the implicit move constructor)|" + "function (the implicit copy assignment operator)|" + "function (the implicit move assignment operator)|" + "constructor (inherited)}0%1 " "has been explicitly %select{made unavailable|deleted}2">; // Giving the index of the bad argument really clutters this message, and @@ -1565,7 +1614,18 @@ def note_ovl_candidate_bad_gc : Note<"candidate " "function (the implicit move assignment operator)|" "constructor (inherited)}0%1 not viable: " "%select{%ordinal6|'this'}5 argument (%2) has %select{no|__weak|__strong}3 " - "lifetime, but parameter has %select{no|__weak|__strong}4 lifetime">; + "ownership, but parameter has %select{no|__weak|__strong}4 ownership">; +def note_ovl_candidate_bad_ownership : Note<"candidate " + "%select{function|function|constructor|" + "function |function |constructor |" + "constructor (the implicit default constructor)|" + "constructor (the implicit copy constructor)|" + "function (the implicit copy assignment operator)|" + "constructor (inherited)}0%1 not viable: " + "%select{%ordinal6|'this'}5 argument (%2) has " + "%select{no|__unsafe_unretained|__strong|__weak|__autoreleasing}3 ownership," + " but parameter has %select{no|__unsafe_unretained|__strong|__weak|" + "__autoreleasing}4 ownership">; def note_ovl_candidate_bad_cvr_this : Note<"candidate " "%select{|function|||function||||" "function (the implicit copy assignment operator)|}0 not viable: " @@ -1871,8 +1931,11 @@ def err_not_class_template_specialization : Error< "parameter}0">; def err_function_specialization_in_class : Error< "cannot specialize a function %0 within class scope">; -def err_explicit_specialization_storage_class : Error< +def ext_explicit_specialization_storage_class : ExtWarn< "explicit specialization cannot have a storage class">; +def err_explicit_specialization_inconsistent_storage_class : Error< + "explicit specialization has extraneous, inconsistent storage class " + "'%select{none|extern|static|__private_extern__|auto|register}0'">; // C++ class template specializations and out-of-line definitions def err_template_spec_needs_header : Error< @@ -2180,7 +2243,7 @@ def err_undeclared_var_use : Error<"use of undeclared identifier %0">; def note_dependent_var_use : Note<"must qualify identifier to find this " "declaration in dependent base class">; def err_not_found_by_two_phase_lookup : Error<"call to function %0 that is neither " - "visible in the template definition nor found by argument dependent lookup">; + "visible in the template definition nor found by argument-dependent lookup">; def note_not_found_by_two_phase_lookup : Note<"%0 should be declared prior to the " "call site%select{| or in %2| or in an associated namespace of one of its arguments}1">; def err_undeclared_use : Error<"use of undeclared %0">; @@ -2199,8 +2262,8 @@ def err_unavailable_message : Error<"%0 is unavailable: %1">; def warn_unavailable_fwdclass_message : Warning< "%0 maybe unavailable because receiver type is unknown">; def note_unavailable_here : Note< - "function has been explicitly marked " - "%select{unavailable|deleted|deprecated}0 here">; + "%select{declaration|function}0 has been explicitly marked " + "%select{unavailable|deleted|deprecated}1 here">; def warn_not_enough_argument : Warning< "not enough variable arguments in %0 declaration to fit a sentinel">; def warn_missing_sentinel : Warning < @@ -2237,6 +2300,8 @@ def err_inline_declaration_block_scope : Error< "inline declaration of %0 not allowed in block scope">; def err_static_non_static : Error< "static declaration of %0 follows non-static declaration">; +def warn_weak_import : Warning < + "an already-declared variable is made a weak_import declaration %0">; def warn_static_non_static : ExtWarn< "static declaration of %0 follows non-static declaration">; def err_non_static_static : Error< @@ -2418,6 +2483,8 @@ def err_indirect_goto_in_protected_scope : Error< def note_indirect_goto_target : Note<"possible target of indirect goto">; def note_protected_by_variable_init : Note< "jump bypasses variable initialization">; +def note_protected_by_variable_nontriv_destructor : Note< + "jump bypasses variable with a non-trivial destructor">; def note_protected_by_cleanup : Note< "jump bypasses initialization of variable with __attribute__((cleanup))">; def note_protected_by_vla_typedef : Note< @@ -2434,12 +2501,22 @@ def note_protected_by_objc_finally : Note< "jump bypasses initialization of @finally block">; def note_protected_by_objc_synchronized : Note< "jump bypasses initialization of @synchronized block">; +def note_protected_by_objc_autoreleasepool : Note< + "jump bypasses auto release push of @autoreleasepool block">; def note_protected_by_cxx_try : Note< "jump bypasses initialization of try block">; def note_protected_by_cxx_catch : Note< "jump bypasses initialization of catch block">; def note_protected_by___block : Note< "jump bypasses setup of __block variable">; +def note_protected_by_objc_ownership : Note< + "jump bypasses initialization of retaining variable">; +def note_enters_block_captures_cxx_obj : Note< + "jump enters lifetime of block which captures a destructible c++ object">; +def note_enters_block_captures_strong : Note< + "jump enters lifetime of block which strongly captures a variable">; +def note_enters_block_captures_weak : Note< + "jump enters lifetime of block which weakly captures a variable">; def note_exits_cleanup : Note< "jump exits scope of variable with __attribute__((cleanup))">; @@ -2459,6 +2536,16 @@ def note_exits_cxx_try : Note< "jump exits try block">; def note_exits_cxx_catch : Note< "jump exits catch block">; +def note_exits_objc_autoreleasepool : Note< + "jump exits autoreleasepool block">; +def note_exits_objc_ownership : Note< + "jump exits scope of retaining variable">; +def note_exits_block_captures_cxx_obj : Note< + "jump exits lifetime of block which captures a destructible c++ object">; +def note_exits_block_captures_strong : Note< + "jump exits lifetime of block which strongly captures a variable">; +def note_exits_block_captures_weak : Note< + "jump exits lifetime of block which weakly captures a variable">; def err_func_returning_array_function : Error< "function cannot return %select{array|function}0 type %1">; @@ -2490,6 +2577,152 @@ def ext_flexible_array_empty_aggregate_gnu : Extension< def ext_flexible_array_union_gnu : Extension< "flexible array member %0 in a union is a GNU extension">, InGroup<GNU>; +let CategoryName = "Automatic Reference Counting Issue" in { + +// ARC-mode diagnostics. +def err_arc_weak_no_runtime : Error< + "the current deployment target does not support automated __weak references">; +def err_arc_unsupported_weak_class : Error< + "class is incompatible with __weak references">; +def err_arc_weak_unavailable_assign : Error< + "assignment of a weak-unavailable object to a __weak object">; +def err_arc_convesion_of_weak_unavailable : Error< + "%select{implicit conversion|cast}0 of weak-unavailable object of type %1 to" + " a __weak object of type %2">; +def err_arc_illegal_explicit_message : Error< + "ARC forbids explicit message send of %0">; +def err_arc_unused_init_message : Error< + "the result of a delegate init call must be immediately returned " + "or assigned to 'self'">; +def err_arc_mismatched_cast : Error< + "%select{implicit conversion|cast}0 of " + "%select{%2|a non-Objective-C pointer type %2|a block pointer|" + "an Objective-C pointer|an indirect pointer to an Objective-C pointer}1" + " to %3 is disallowed with ARC">; +def err_arc_objc_object_in_struct : Error< + "ARC forbids Objective-C objects in structs or unions">; +def err_arc_objc_property_default_assign_on_object : Error< + "ARC forbids synthesizing a property of an Objective-C object " + "with unspecified storage attribute">; +def err_arc_illegal_selector : Error< + "ARC forbids use of %0 in a @selector">; +def err_arc_illegal_method_def : Error< + "ARC forbids implementation of %0">; +def err_arc_lost_method_convention : Error< + "method was declared as %select{an 'alloc'|a 'copy'|an 'init'|a 'new'}0 " + "method, but its implementation doesn't match because %select{" + "its result type is not an object pointer|" + "its result type is unrelated to its receiver type}1">; +def note_arc_lost_method_convention : Note<"declaration in interface">; +def err_arc_gained_method_convention : Error< + "method implementation does not match its declaration">; +def note_arc_gained_method_convention : Note< + "declaration in interface is not in the '%select{alloc|copy|init|new}0' " + "family because %select{its result type is not an object pointer|" + "its result type is unrelated to its receiver type}1">; +def err_typecheck_arr_assign_self : Error< + "cannot assign to 'self' outside of a method in the init family">; +def err_typecheck_arr_assign_enumeration : Error< + "fast enumeration variables can't be modified in ARC by default; " + "declare the variable __strong to allow this">; +def warn_arc_non_pod_class_with_object_member : Warning< + "%0 cannot be shared between ARC and non-ARC " + "code; add a copy constructor, a copy assignment operator, and a destructor " + "to make it ABI-compatible">, InGroup<AutomaticReferenceCountingABI>, + DefaultIgnore; +def warn_arc_retained_assign : Warning< + "assigning retained object to %select{weak|unsafe_unretained}0 variable" + "; object will be released after assignment">, + InGroup<ARCUnsafeRetainedAssign>; +def warn_arc_retained_property_assign : Warning< + "assigning retained object to unsafe property" + "; object will be released after assignment">, + InGroup<ARCUnsafeRetainedAssign>; +def warn_arc_trivial_member_function_with_object_member : Warning< + "%0 cannot be shared between ARC and non-ARC " + "code; add a non-trivial %select{copy constructor|copy assignment operator|" + "destructor}1 to make it ABI-compatible">, + InGroup<AutomaticReferenceCountingABI>, DefaultIgnore; +def err_arc_new_array_without_ownership : Error< + "'new' cannot allocate an array of %0 with no explicit ownership">; +def warn_err_new_delete_object_array : Warning< + "%select{allocating|destroying}0 an array of %1; this array must not " + "%select{be deleted in|have been allocated from}0 non-ARC code">, + InGroup<AutomaticReferenceCountingABI>, DefaultIgnore; +def err_arc_autoreleasing_var : Error< + "%select{__block variables|global variables|fields|ivars}0 cannot have " + "__autoreleasing ownership">; +def err_arc_thread_ownership : Error< + "thread-local variable has non-trivial ownership: type is %0">; +def err_arc_indirect_no_ownership : Error< + "%select{pointer|reference}1 to non-const type %0 with no explicit ownership">, + InGroup<AutomaticReferenceCounting>; +def err_arc_array_param_no_ownership : Error< + "must explicitly describe intended ownership of an object array parameter">; +def err_arc_pseudo_dtor_inconstant_quals : Error< + "pseudo-destructor destroys object of type %0 with inconsistently-qualified " + "type %1">; +def err_arc_init_method_unrelated_result_type : Error< + "init methods must return a type related to the receiver type">; +def err_arc_nonlocal_writeback : Error< + "passing address of %select{non-local|non-scalar}0 object to " + "__autoreleasing parameter for write-back">; +def err_arc_method_not_found : Error< + "no known %select{instance|class}1 method for selector %0">; +def err_arc_receiver_forward_class : Error< + "receiver %0 for class message is a forward declaration">; +def err_arc_may_not_respond : Error< + "receiver type %0 for instance message does not declare a method with " + "selector %1">; +def err_arc_receiver_forward_instance : Error< + "receiver type %0 for instance message is a forward declaration">; +def err_arc_multiple_method_decl : Error< + "multiple methods named %0 found with mismatched result, " + "parameter type or attributes">; +def warn_arc_retain_cycle : Warning< + "capturing %0 strongly in this block is likely to lead to a retain cycle">, + InGroup<ARCRetainCycles>; +def note_arc_retain_cycle_owner : Note< + "block will be retained by %select{the captured object|an object strongly " + "retained by the captured object}0">; +def note_nontrivial_objc_ownership : Note< + "because type %0 has %select{no|no|__strong|__weak|__autoreleasing}1 " + "ownership">; +def warn_arc_object_memaccess : Warning< + "%select{destination for|source of}0 this %1 call is a pointer to " + "ownership-qualified type %2">, InGroup<ARCNonPodMemAccess>; + +def err_arc_strong_property_ownership : Error< + "existing ivar %1 for strong property %0 may not be " + "%select{|__unsafe_unretained||__weak}2">; +def err_arc_assign_property_ownership : Error< + "existing ivar %1 for unsafe_unretained property %0 must be __unsafe_unretained">; +def err_arc_inconsistent_property_ownership : Error< + "%select{strong|weak|unsafe_unretained}1 property %0 may not also be " + "declared %select{|__unsafe_unretained|__strong|__weak|__autoreleasing}2">; +def err_arc_atomic_ownership : Error< + "cannot perform atomic operation on a pointer to type %0: type has " + "non-trivial ownership">; + +def err_arc_bridge_cast_incompatible : Error< + "incompatible types casting %0 to %1 with a %select{__bridge|" + "__bridge_transfer|__bridge_retained}2 cast">; +def err_arc_bridge_cast_wrong_kind : Error< + "cast of %select{Objective-C|block|C}0 pointer type %1 to " + "%select{Objective-C|block|C}2 pointer type %3 cannot use %select{__bridge|" + "__bridge_transfer|__bridge_retained}4">; +def err_arc_cast_requires_bridge : Error< + "cast of %select{Objective-C|block|C}0 pointer type %1 to " + "%select{Objective-C|block|C}2 pointer type %3 requires a bridged cast">; +def note_arc_bridge : Note< + "use __bridge to convert directly (no change in ownership)">; +def note_arc_bridge_transfer : Note< + "use __bridge_transfer to transfer ownership of a +1 %0 into ARC">; +def note_arc_bridge_retained : Note< + "use __bridge_retained to make an ARC object available as a +1 %0">; + +} // ARC category name + def err_flexible_array_init_needs_braces : Error< "flexible array requires brace-enclosed initializer">; def err_illegal_decl_array_of_functions : Error< @@ -2563,11 +2796,11 @@ 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">, + "signed shift result (%0) requires %1 bits to represent, but %2 only has " + "%3 bits">, InGroup<DiagGroup<"shift-overflow">>; +def warn_shift_result_sets_sign_bit : Warning< + "signed shift result (%0) sets 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< @@ -2579,17 +2812,22 @@ def note_precedence_bitwise_silence : Note< "place parentheses around the %0 expression to silence this warning">; def warn_precedence_conditional : Warning< - "?: has lower precedence than %0; %0 will be evaluated first">, + "operator '?:' has lower precedence than '%0'; '%0' will be evaluated first">, InGroup<Parentheses>; def note_precedence_conditional_first : Note< - "place parentheses around the ?: expression to evaluate it first">; + "place parentheses around the '?:' expression to evaluate it first">; def note_precedence_conditional_silence : Note< - "place parentheses around the %0 expression to silence this warning">; + "place parentheses around the '%0' expression to silence this warning">; def warn_logical_instead_of_bitwise : Warning< "use of logical %0 with constant operand; switch to bitwise %1 or " "remove constant">, InGroup<DiagGroup<"constant-logical-operand">>; +def warn_bitwise_and_in_bitwise_or : Warning< + "'&' within '|'">, InGroup<BitwiseOpParentheses>; +def note_bitwise_and_in_bitwise_or_silence : Note< + "place parentheses around the '&' expression to silence this warning">; + def warn_logical_and_in_logical_or : Warning< "'&&' within '||'">, InGroup<LogicalOpParentheses>; def note_logical_and_in_logical_or_silence : Note< @@ -2599,6 +2837,10 @@ def warn_self_assignment : Warning< "explicitly assigning a variable of type %0 to itself">, InGroup<SelfAssignment>, DefaultIgnore; +def warn_sizeof_array_param : Warning< + "sizeof on array function parameter will return size of %0 instead of %1">, + InGroup<SizeofArrayArgument>; + def err_sizeof_nonfragile_interface : Error< "invalid application of '%select{alignof|sizeof}1' to interface %0 in " "non-fragile ABI">; @@ -2623,10 +2865,15 @@ def err_subscript_function_type : Error< "subscript of pointer to function type %0">; def err_subscript_incomplete_type : Error< "subscript of pointer to incomplete type %0">; +def ext_gnu_subscript_void_type : Extension< + "subscript of a pointer to void is a GNU extension">, InGroup<PointerArith>; def err_typecheck_member_reference_struct_union : Error< "member reference base type %0 is not a structure or union">; def err_typecheck_member_reference_ivar : Error< "%0 does not have a member named %1">; +def error_arc_weak_ivar_access : Error< + "dereferencing a __weak pointer is not allowed due to possible " + "null value caused by race condition, assign it to strong variable first">; def err_typecheck_member_reference_arrow : Error< "member reference type %0 is not a pointer">; def err_typecheck_member_reference_suggestion : Error< @@ -2658,7 +2905,7 @@ def err_member_def_undefined_record : Error< def err_member_def_does_not_match : Error< "out-of-line definition of %0 does not match any declaration in %1">; def err_member_def_does_not_match_ret_type : Error< - "out-of-line definition of %q0 differ from the declaration in the return type">; + "out-of-line definition of %q0 differs from the declaration in the return type">; def err_nonstatic_member_out_of_line : Error< "non-static data member defined out-of-line">; def err_nonstatic_flexible_variable : Error< @@ -2682,11 +2929,12 @@ def err_ivar_reference_type : Error< def err_typecheck_illegal_increment_decrement : Error< "cannot %select{decrement|increment}1 value of type %0">; def err_typecheck_arithmetic_incomplete_type : Error< - "arithmetic on pointer to incomplete type %0">; + "arithmetic on a pointer to an incomplete type %0">; def err_typecheck_pointer_arith_function_type : Error< - "arithmetic on pointer to function type %0">; + "arithmetic on%select{ a|}0 pointer%select{|s}0 to%select{ the|}2 " + "function type%select{|s}2 %1%select{| and %3}2">; def err_typecheck_pointer_arith_void_type : Error< - "arithmetic on pointer to void type">; + "arithmetic on%select{ a|}0 pointer%select{|s}0 to void">; def err_typecheck_decl_incomplete_type : Error< "variable has incomplete type %0">; def ext_typecheck_decl_incomplete_type : ExtWarn< @@ -2803,6 +3051,9 @@ def warn_runsigned_always_true_comparison : Warning< def warn_comparison_of_mixed_enum_types : Warning< "comparison of two values with different enumeration types (%0 and %1)">, InGroup<DiagGroup<"enum-compare">>; +def warn_null_in_arithmetic_operation : Warning< + "use of NULL in arithmetic operation">, + InGroup<DiagGroup<"null-arithmetic">>; def err_invalid_this_use : Error< "invalid use of 'this' outside of a nonstatic member function">; @@ -2871,9 +3122,11 @@ def note_forward_class : Note< def err_duplicate_property : Error< "property has a previous declaration">; def ext_gnu_void_ptr : Extension< - "use of GNU void* extension">, InGroup<PointerArith>; + "arithmetic on%select{ a|}0 pointer%select{|s}0 to void is a GNU extension">, + InGroup<PointerArith>; def ext_gnu_ptr_func_arith : Extension< - "arithmetic on pointer to function type %0 is a GNU extension">, + "arithmetic on%select{ a|}0 pointer%select{|s}0 to%select{ the|}2 function " + "type%select{|s}2 %1%select{| and %3}2 is a GNU extension">, InGroup<PointerArith>; def error_readonly_property_assignment : Error< "assigning to property with 'readonly' attribute not allowed">; @@ -2942,9 +3195,9 @@ def err_qualified_objc_catch_parm : Error< "@catch parameter declarator cannot be qualified">; def err_objc_pointer_cxx_catch_gnu : Error< "can't catch Objective C exceptions in C++ in the GNU runtime">; -def err_objc_pointer_cxx_catch_fragile : Error< - "can't catch Objective C exceptions in C++ in the non-unified " - "exception model">; +def warn_objc_pointer_cxx_catch_fragile : Warning< + "can not catch an exception thrown with @throw in C++ in the non-unified " + "exception model">, InGroup<ObjCNonUnifiedException>; def err_objc_object_catch : Error< "can't catch an Objective C object by value">; def err_incomplete_type_objc_at_encode : Error< @@ -3328,6 +3581,15 @@ def err_typecheck_incompatible_address_space : Error< "|sending %0 to parameter of type %1" "|casting %0 to type %1}2" " changes address space of pointer">; +def err_typecheck_incompatible_ownership : Error< + "%select{assigning %1 to %0" + "|passing %0 to parameter of type %1" + "|returning %0 from a function with result type %1" + "|converting %0 to type %1" + "|initializing %0 with an expression of type %1" + "|sending %0 to parameter of type %1" + "|casting %0 to type %1}2" + " changes retain/release properties of pointer">; def err_typecheck_convert_ambiguous : Error< "ambiguity in initializing value of type %0 with initializer of type %1">; def err_typecheck_comparison_of_distinct_blocks : Error< @@ -3544,6 +3806,9 @@ def ext_in_class_initializer_float_type : ExtWarn< def err_in_class_initializer_non_constant : Error< "in-class initializer is not a constant expression">; +def ext_in_class_initializer_non_constant : Extension< + "in-class initializer is not a constant expression, accepted as an extension">; + // C++ anonymous unions and GNU anonymous structs/unions def ext_anonymous_union : Extension< "anonymous unions are a GNU extension in C">, InGroup<GNU>; @@ -3929,12 +4194,23 @@ def err_switch_incomplete_class_type : Error< "switch condition has incomplete class type %0">; def warn_empty_if_body : Warning< "if statement has empty body">, InGroup<EmptyBody>; + def err_va_start_used_in_non_variadic_function : Error< "'va_start' used in function with fixed args">; def warn_second_parameter_of_va_start_not_last_named_argument : Warning< "second parameter of 'va_start' not last named argument">; def err_first_argument_to_va_arg_not_of_type_va_list : Error< "first argument to 'va_arg' is of type %0 and not 'va_list'">; +def err_second_parameter_to_va_arg_incomplete: Error< + "second argument to 'va_arg' is of incomplete type %0">; +def err_second_parameter_to_va_arg_abstract: Error< + "second argument to 'va_arg' is of abstract type %0">; +def warn_second_parameter_to_va_arg_not_pod : Warning< + "second argument to 'va_arg' is of non-POD type %0">, + InGroup<DiagGroup<"non-pod-varargs">>, DefaultError; +def warn_second_parameter_to_va_arg_never_compatible : Warning< + "second argument to 'va_arg' is of promotable type %0; this va_arg has " + "undefined behavior because arguments will be promoted to %1">; def warn_return_missing_expr : Warning< "non-void %select{function|method}1 %0 should return a value">, DefaultError, @@ -3943,8 +4219,9 @@ def ext_return_missing_expr : ExtWarn< "non-void %select{function|method}1 %0 should return a value">, DefaultError, InGroup<ReturnType>; def ext_return_has_expr : ExtWarn< - "void %select{function|method}1 %0 should not return a value">, DefaultError, - InGroup<ReturnType>; + "%select{void function|void method|constructor|destructor}1 %0 " + "should not return a value">, + DefaultError, InGroup<ReturnType>; def ext_return_has_void_expr : Extension< "void %select{function|method}1 %0 should not return void expression">; def warn_noreturn_function_has_return_expr : Warning< @@ -4074,6 +4351,11 @@ def err_typecheck_member_reference_ivar_suggest : Error< "%0 does not have a member named %1; did you mean %2?">; def err_property_not_found_suggest : Error< "property %0 not found on object of type %1; did you mean %2?">; +def err_ivar_access_using_property_syntax_suggest : Error< + "property %0 not found on object of type %1; did you mean to access ivar %2?">; +def err_property_found_suggest : Error< + "property %0 found on object of type %1; did you mean to access " + "it with the \".\" operator?">; def err_undef_interface_suggest : Error< "cannot find interface declaration for %0; did you mean %1?">; def warn_undef_interface_suggest : Warning< diff --git a/include/clang/Basic/FileManager.h b/include/clang/Basic/FileManager.h index 2ca344d55370..1324533fa03e 100644 --- a/include/clang/Basic/FileManager.h +++ b/include/clang/Basic/FileManager.h @@ -21,10 +21,13 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/Support/Allocator.h" -#include "llvm/Config/config.h" // for mode_t // FIXME: Enhance libsystem to support inode and other fields in stat. #include <sys/types.h> +#ifdef _MSC_VER +typedef unsigned short mode_t; +#endif + struct stat; namespace llvm { diff --git a/include/clang/Basic/IdentifierTable.h b/include/clang/Basic/IdentifierTable.h index b4eca6d8fbdb..bebcffdddede 100644 --- a/include/clang/Basic/IdentifierTable.h +++ b/include/clang/Basic/IdentifierTable.h @@ -411,23 +411,15 @@ public: return II; } - IdentifierInfo &get(const char *NameStart, const char *NameEnd) { - return get(llvm::StringRef(NameStart, NameEnd-NameStart)); - } - - IdentifierInfo &get(const char *Name, size_t NameLen) { - return get(llvm::StringRef(Name, NameLen)); - } - /// \brief Gets an IdentifierInfo for the given name without consulting /// external sources. /// /// This is a version of get() meant for external sources that want to /// introduce or modify an identifier. If they called get(), they would /// likely end up in a recursion. - IdentifierInfo &getOwn(const char *NameStart, const char *NameEnd) { + IdentifierInfo &getOwn(llvm::StringRef Name) { llvm::StringMapEntry<IdentifierInfo*> &Entry = - HashTable.GetOrCreateValue(NameStart, NameEnd); + HashTable.GetOrCreateValue(Name); IdentifierInfo *II = Entry.getValue(); if (!II) { @@ -444,9 +436,6 @@ public: return *II; } - IdentifierInfo &getOwn(llvm::StringRef Name) { - return getOwn(Name.begin(), Name.end()); - } typedef HashTableTy::const_iterator iterator; typedef HashTableTy::const_iterator const_iterator; @@ -499,7 +488,10 @@ enum ObjCMethodFamily { OMF_release, OMF_retain, OMF_retainCount, - OMF_self + OMF_self, + + // performSelector families + OMF_performSelector }; /// Enough bits to store any enumerator in ObjCMethodFamily or diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h index f0f1432ca0b8..dc77d4c1496b 100644 --- a/include/clang/Basic/LangOptions.h +++ b/include/clang/Basic/LangOptions.h @@ -119,6 +119,8 @@ public: unsigned InlineVisibilityHidden : 1; // Whether inline C++ methods have // hidden visibility by default. unsigned ParseUnknownAnytype: 1; /// Let the user write __unknown_anytype. + unsigned DebuggerSupport : 1; /// Do things that only make sense when + /// supporting a debugger unsigned SpellChecking : 1; // Whether to perform spell-checking for error // recovery. @@ -130,6 +132,10 @@ public: unsigned DefaultFPContract : 1; // Default setting for FP_CONTRACT // FIXME: This is just a temporary option, for testing purposes. unsigned NoBitFieldTypeAlign : 1; + unsigned ObjCAutoRefCount : 1; // Objective C automated reference counting + unsigned ObjCRuntimeHasWeak : 1; // The ARC runtime supports __weak + unsigned ObjCInferRelatedReturnType : 1; // Infer Objective-C related return + // types unsigned FakeAddressSpaceMap : 1; // Use a fake address space map, for // testing languages such as OpenCL. @@ -172,10 +178,13 @@ public: Trigraphs = BCPLComment = Bool = DollarIdents = AsmPreprocessor = 0; GNUMode = GNUKeywords = ImplicitInt = Digraphs = 0; HexFloats = 0; + ObjCAutoRefCount = 0; + ObjCRuntimeHasWeak = 0; + ObjCInferRelatedReturnType = 0; GC = ObjC1 = ObjC2 = ObjCNonFragileABI = ObjCNonFragileABI2 = 0; AppleKext = 0; ObjCDefaultSynthProperties = 0; - ObjCInferRelatedResultType = 0; + ObjCInferRelatedResultType = 1; NoConstantCFStrings = 0; InlineVisibilityHidden = 0; C99 = C1X = Microsoft = Borland = CPlusPlus = CPlusPlus0x = 0; CXXOperatorNames = PascalStrings = WritableStrings = ConstStrings = 0; @@ -234,7 +243,7 @@ public: FakeAddressSpaceMap = 0; MRTD = 0; DelayedTemplateParsing = 0; - ParseUnknownAnytype = 0; + ParseUnknownAnytype = DebuggerSupport = 0; } GCMode getGCMode() const { return (GCMode) GC; } diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h index df5074cb42e6..6301f3197859 100644 --- a/include/clang/Basic/SourceManager.h +++ b/include/clang/Basic/SourceManager.h @@ -36,6 +36,7 @@ class SourceManager; class FileManager; class FileEntry; class LineTableInfo; +class LangOptions; /// SrcMgr - Public enums and private classes that are part of the /// SourceManager implementation. @@ -89,7 +90,7 @@ namespace SrcMgr { /// getBuffer - Returns the memory buffer for the associated content. /// - /// \param Diag Object through which diagnostics will be emitted it the + /// \param Diag Object through which diagnostics will be emitted if the /// buffer cannot be retrieved. /// /// \param Loc If specified, is the location that invalid file diagnostics @@ -238,8 +239,11 @@ namespace SrcMgr { /// InstantiationLocStart/InstantiationLocEnd - In a macro expansion, these /// indicate the start and end of the instantiation. In object-like macros, /// these will be the same. In a function-like macro instantiation, the - /// start will be the identifier and the end will be the ')'. + /// start will be the identifier and the end will be the ')'. Finally, in + /// macro-argument instantitions, the end will be 'SourceLocation()', an + /// invalid location. unsigned InstantiationLocStart, InstantiationLocEnd; + public: SourceLocation getSpellingLoc() const { return SourceLocation::getFromRawEncoding(SpellingLoc); @@ -248,7 +252,9 @@ namespace SrcMgr { return SourceLocation::getFromRawEncoding(InstantiationLocStart); } SourceLocation getInstantiationLocEnd() const { - return SourceLocation::getFromRawEncoding(InstantiationLocEnd); + SourceLocation EndLoc = + SourceLocation::getFromRawEncoding(InstantiationLocEnd); + return EndLoc.isInvalid() ? getInstantiationLocStart() : EndLoc; } std::pair<SourceLocation,SourceLocation> getInstantiationLocRange() const { @@ -256,19 +262,52 @@ namespace SrcMgr { getInstantiationLocEnd()); } - /// get - Return a InstantiationInfo for an expansion. IL specifies - /// the instantiation location (where the macro is expanded), and SL - /// specifies the spelling location (where the characters from the token - /// come from). IL and PL can both refer to normal File SLocs or + bool isMacroArgInstantiation() const { + // Note that this needs to return false for default constructed objects. + return getInstantiationLocStart().isValid() && + SourceLocation::getFromRawEncoding(InstantiationLocEnd).isInvalid(); + } + + /// create - Return a InstantiationInfo for an expansion. ILStart and + /// ILEnd specify the instantiation range (where the macro is expanded), + /// and SL specifies the spelling location (where the characters from the + /// token come from). All three can refer to normal File SLocs or /// instantiation locations. - static InstantiationInfo get(SourceLocation ILStart, SourceLocation ILEnd, - SourceLocation SL) { + static InstantiationInfo create(SourceLocation SL, + SourceLocation ILStart, + SourceLocation ILEnd) { InstantiationInfo X; X.SpellingLoc = SL.getRawEncoding(); X.InstantiationLocStart = ILStart.getRawEncoding(); X.InstantiationLocEnd = ILEnd.getRawEncoding(); return X; } + + /// createForMacroArg - Return a special InstantiationInfo for the + /// expansion of a macro argument into a function-like macro's body. IL + /// specifies the instantiation location (where the macro is expanded). + /// This doesn't need to be a range because a macro is always instantiated + /// at a macro parameter reference, and macro parameters are always exactly + /// one token. SL specifies the spelling location (where the characters + /// from the token come from). IL and SL can both refer to normal File + /// SLocs or instantiation locations. + /// + /// Given the code: + /// \code + /// #define F(x) f(x) + /// F(42); + /// \endcode + /// + /// When expanding '\c F(42)', the '\c x' would call this with an SL + /// pointing at '\c 42' anad an IL pointing at its location in the + /// definition of '\c F'. + static InstantiationInfo createForMacroArg(SourceLocation SL, + SourceLocation IL) { + // We store an intentionally invalid source location for the end of the + // instantiation range to mark that this is a macro argument instantation + // rather than a normal one. + return create(SL, IL, SourceLocation()); + } }; /// SLocEntry - This is a discriminated union of FileInfo and @@ -500,8 +539,8 @@ public: //===--------------------------------------------------------------------===// /// createFileID - Create a new FileID that represents the specified file - /// being #included from the specified IncludePosition. This returns 0 on - /// error and translates NULL into standard input. + /// being #included from the specified IncludePosition. This translates NULL + /// into standard input. /// PreallocateID should be non-zero to specify which pre-allocated, /// lazily computed source location is being filled in by this operation. FileID createFileID(const FileEntry *SourceFile, SourceLocation IncludePos, @@ -532,9 +571,17 @@ public: return MainFileID; } + /// createMacroArgInstantiationLoc - Return a new SourceLocation that encodes + /// the fact that a token from SpellingLoc should actually be referenced from + /// InstantiationLoc, and that it represents the instantiation of a macro + /// argument into the function-like macro body. + SourceLocation createMacroArgInstantiationLoc(SourceLocation Loc, + SourceLocation InstantiationLoc, + unsigned TokLength); + /// createInstantiationLoc - Return a new SourceLocation that encodes the fact - /// that a token at Loc should actually be referenced from InstantiationLoc. - /// TokLength is the length of the token being instantiated. + /// that a token from SpellingLoc should actually be referenced from + /// InstantiationLoc. SourceLocation createInstantiationLoc(SourceLocation Loc, SourceLocation InstantiationLocStart, SourceLocation InstantiationLocEnd, @@ -721,7 +768,7 @@ public: if (Loc.isFileID()) return std::make_pair(FID, Offset); - return getDecomposedInstantiationLocSlowCase(E, Offset); + return getDecomposedInstantiationLocSlowCase(E); } /// getDecomposedSpellingLoc - Decompose the specified location into a raw @@ -745,6 +792,12 @@ public: return getDecomposedLoc(SpellingLoc).second; } + /// isMacroArgInstantiation - This method tests whether the given source + /// location represents a macro argument's instantiation into the + /// function-like macro definition. Such source locations only appear inside + /// of the instantiation locations representing where a particular + /// function-like macro was expanded. + bool isMacroArgInstantiation(SourceLocation Loc) const; //===--------------------------------------------------------------------===// // Queries about the code at a SourceLocation. @@ -831,13 +884,38 @@ public: return getFileCharacteristic(Loc) == SrcMgr::C_ExternCSystem; } - /// \brief Returns true if the given MacroID location points at the first - /// token of the macro instantiation. - bool isAtStartOfMacroInstantiation(SourceLocation Loc) const; + /// \brief Given a specific chunk of a FileID (FileID with offset+length), + /// returns true if \arg Loc is inside that chunk and sets relative offset + /// (offset of \arg Loc from beginning of chunk) to \arg relativeOffset. + bool isInFileID(SourceLocation Loc, + FileID FID, unsigned offset, unsigned length, + unsigned *relativeOffset = 0) const { + assert(!FID.isInvalid()); + if (Loc.isInvalid()) + return false; + + unsigned start = getSLocEntry(FID).getOffset() + offset; + unsigned end = start + length; + +#ifndef NDEBUG + // Make sure offset/length describe a chunk inside the given FileID. + unsigned NextOffset; + if (FID.ID+1 == SLocEntryTable.size()) + NextOffset = getNextOffset(); + else + NextOffset = getSLocEntry(FID.ID+1).getOffset(); + assert(start < NextOffset); + assert(end < NextOffset); +#endif - /// \brief Returns true if the given MacroID location points at the last - /// token of the macro instantiation. - bool isAtEndOfMacroInstantiation(SourceLocation Loc) const; + if (Loc.getOffset() >= start && Loc.getOffset() < end) { + if (relativeOffset) + *relativeOffset = Loc.getOffset() - start; + return true; + } + + return false; + } //===--------------------------------------------------------------------===// // Line Table Manipulation Routines @@ -845,7 +923,7 @@ public: /// getLineTableFilenameID - Return the uniqued ID for the specified filename. /// - unsigned getLineTableFilenameID(const char *Ptr, unsigned Len); + unsigned getLineTableFilenameID(llvm::StringRef Str); /// AddLineNote - Add a line note to the line table for the FileID and offset /// specified by Loc. If FilenameID is -1, it is considered to be @@ -899,6 +977,19 @@ public: /// \returns true if LHS source location comes before RHS, false otherwise. bool isBeforeInTranslationUnit(SourceLocation LHS, SourceLocation RHS) const; + /// \brief Determines the order of 2 source locations in the "source location + /// address space". + static bool isBeforeInSourceLocationOffset(SourceLocation LHS, + SourceLocation RHS) { + return isBeforeInSourceLocationOffset(LHS, RHS.getOffset()); + } + + /// \brief Determines the order of a source location and a source location + /// offset in the "source location address space". + static bool isBeforeInSourceLocationOffset(SourceLocation LHS, unsigned RHS) { + return LHS.getOffset() < RHS; + } + // Iterators over FileInfos. typedef llvm::DenseMap<const FileEntry*, SrcMgr::ContentCache*> ::const_iterator fileinfo_iterator; @@ -952,6 +1043,14 @@ public: private: const llvm::MemoryBuffer *getFakeBufferForRecovery() const; + /// createInstantiationLoc - Implements the common elements of storing an + /// instantiation info struct into the SLocEntry table and producing a source + /// location that refers to it. + SourceLocation createInstantiationLocImpl(const SrcMgr::InstantiationInfo &II, + unsigned TokLength, + unsigned PreallocatedID = 0, + unsigned Offset = 0); + /// isOffsetInFileID - Return true if the specified FileID contains the /// specified SourceLocation offset. This is a very hot method. inline bool isOffsetInFileID(FileID FID, unsigned SLocOffset) const { @@ -989,8 +1088,7 @@ private: SourceLocation getSpellingLocSlowCase(SourceLocation Loc) const; std::pair<FileID, unsigned> - getDecomposedInstantiationLocSlowCase(const SrcMgr::SLocEntry *E, - unsigned Offset) const; + getDecomposedInstantiationLocSlowCase(const SrcMgr::SLocEntry *E) const; std::pair<FileID, unsigned> getDecomposedSpellingLocSlowCase(const SrcMgr::SLocEntry *E, unsigned Offset) const; diff --git a/include/clang/Basic/SourceManagerInternals.h b/include/clang/Basic/SourceManagerInternals.h index 258989cb7787..3f5d1a35e595 100644 --- a/include/clang/Basic/SourceManagerInternals.h +++ b/include/clang/Basic/SourceManagerInternals.h @@ -97,7 +97,7 @@ public: ~LineTableInfo() {} - unsigned getLineTableFilenameID(const char *Ptr, unsigned Len); + unsigned getLineTableFilenameID(llvm::StringRef Str); const char *getFilename(unsigned ID) const { assert(ID < FilenamesByID.size() && "Invalid FilenameID"); return FilenamesByID[ID]->getKeyData(); diff --git a/include/clang/Basic/Specifiers.h b/include/clang/Basic/Specifiers.h index d21bda7d9a2e..cfce0ccbc9dd 100644 --- a/include/clang/Basic/Specifiers.h +++ b/include/clang/Basic/Specifiers.h @@ -83,7 +83,7 @@ namespace clang { /// ExprValueKind - The categorization of expression values, /// currently following the C++0x scheme. enum ExprValueKind { - /// An r-value expression (a gr-value in the C++0x taxonomy) + /// An r-value expression (a pr-value in the C++0x taxonomy) /// produces a temporary value. VK_RValue, diff --git a/include/clang/Basic/StmtNodes.td b/include/clang/Basic/StmtNodes.td index 03f4cc3ec6d8..73996e43d5da 100644 --- a/include/clang/Basic/StmtNodes.td +++ b/include/clang/Basic/StmtNodes.td @@ -37,6 +37,7 @@ def ObjCAtFinallyStmt : Stmt; def ObjCAtThrowStmt : Stmt; def ObjCAtSynchronizedStmt : Stmt; def ObjCForCollectionStmt : Stmt; +def ObjCAutoreleasePoolStmt : Stmt; // C++ statments def CXXCatchStmt : Stmt; @@ -119,7 +120,9 @@ def UnresolvedMemberExpr : DStmt<OverloadExpr>; def CXXNoexceptExpr : DStmt<Expr>; def PackExpansionExpr : DStmt<Expr>; def SizeOfPackExpr : DStmt<Expr>; +def SubstNonTypeTemplateParmExpr : DStmt<Expr>; def SubstNonTypeTemplateParmPackExpr : DStmt<Expr>; +def MaterializeTemporaryExpr : DStmt<Expr>; // Obj-C Expressions. def ObjCStringLiteral : DStmt<Expr>; @@ -130,6 +133,10 @@ def ObjCProtocolExpr : DStmt<Expr>; def ObjCIvarRefExpr : DStmt<Expr>; def ObjCPropertyRefExpr : DStmt<Expr>; def ObjCIsaExpr : DStmt<Expr>; +def ObjCIndirectCopyRestoreExpr : DStmt<Expr>; + +// Obj-C ARC Expressions. +def ObjCBridgedCastExpr : DStmt<ExplicitCastExpr>; // CUDA Expressions. def CUDAKernelCallExpr : DStmt<CallExpr>; diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h index 76006d4292e8..4559cf2f64be 100644 --- a/include/clang/Basic/TargetInfo.h +++ b/include/clang/Basic/TargetInfo.h @@ -240,6 +240,14 @@ public: return getTypeWidth(IntMaxType); } + /// getRegisterWidth - Return the "preferred" register width on this target. + uint64_t getRegisterWidth() const { + // Currently we assume the register width on the target matches the pointer + // width, we can introduce a new variable for this if/when some target wants + // it. + return LongWidth; + } + /// getUserLabelPrefix - This returns the default value of the /// __USER_LABEL_PREFIX__ macro, which is the prefix given to user symbols by /// default. On most platforms this is "_", but it is "" on some, and "." on @@ -295,6 +303,11 @@ public: /// __builtin_va_list, which is target-specific. virtual const char *getVAListDeclaration() const = 0; + /// isValidClobber - Returns whether the passed in string is + /// a valid clobber in an inline asm statement. This is used by + /// Sema. + bool isValidClobber(llvm::StringRef Name) const; + /// isValidGCCRegisterName - Returns whether the passed in string /// is a valid register name according to GCC. This is used by Sema for /// inline asm statements. @@ -396,6 +409,11 @@ public: const char * const Register; }; + struct AddlRegName { + const char * const Names[5]; + const unsigned RegNum; + }; + virtual bool useGlobalsForAutomaticVariables() const { return false; } /// getCFStringSection - Return the section to use for CFString @@ -511,6 +529,7 @@ public: // getRegParmMax - Returns maximal number of args passed in registers. unsigned getRegParmMax() const { + assert(RegParmMax < 7 && "RegParmMax value is larger than AST can handle"); return RegParmMax; } @@ -566,6 +585,11 @@ protected: unsigned &NumNames) const = 0; virtual void getGCCRegAliases(const GCCRegAlias *&Aliases, unsigned &NumAliases) const = 0; + virtual void getGCCAddlRegNames(const AddlRegName *&Addl, + unsigned &NumAddl) const { + Addl = 0; + NumAddl = 0; + } virtual bool validateAsmConstraint(const char *&Name, TargetInfo::ConstraintInfo &info) const= 0; }; diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def index dfba7eec8ae7..86172b83ff42 100644 --- a/include/clang/Basic/TokenKinds.def +++ b/include/clang/Basic/TokenKinds.def @@ -422,6 +422,12 @@ KEYWORD(__pascal , KEYALL) KEYWORD(__vector , KEYALTIVEC) KEYWORD(__pixel , KEYALTIVEC) +// Objective-C ARC keywords. +KEYWORD(__bridge , KEYARC) +KEYWORD(__bridge_transfer , KEYARC) +KEYWORD(__bridge_retained , KEYARC) +KEYWORD(__bridge_retain , KEYARC) + // Alternate spelling for various tokens. There are GCC extensions in all // languages, but should not be disabled in strict conformance mode. ALIAS("__alignof__" , __alignof , KEYALL) @@ -507,6 +513,7 @@ OBJC1_AT_KEYWORD(try) OBJC1_AT_KEYWORD(catch) OBJC1_AT_KEYWORD(finally) OBJC1_AT_KEYWORD(synchronized) +OBJC1_AT_KEYWORD(autoreleasepool) OBJC2_AT_KEYWORD(property) OBJC2_AT_KEYWORD(package) diff --git a/include/clang/Basic/arm_neon.td b/include/clang/Basic/arm_neon.td index b3da12254a84..71a0aa2726c0 100644 --- a/include/clang/Basic/arm_neon.td +++ b/include/clang/Basic/arm_neon.td @@ -182,7 +182,7 @@ def VMAX : SInst<"vmax", "ddd", "csiUcUsUifQcQsQiQUcQUsQUiQf">; def VMIN : SInst<"vmin", "ddd", "csiUcUsUifQcQsQiQUcQUsQUiQf">; //////////////////////////////////////////////////////////////////////////////// -// E.3.7 Pairdise Addition +// E.3.7 Pairwise Addition def VPADD : IInst<"vpadd", "ddd", "csiUcUsUif">; def VPADDL : SInst<"vpaddl", "nd", "csiUcUsUiQcQsQiQUcQUsQUi">; def VPADAL : SInst<"vpadal", "nnd", "csiUcUsUiQcQsQiQUcQUsQUi">; @@ -352,7 +352,7 @@ def VEXT : WInst<"vext", "dddi", "cUcPcsUsPsiUilUlfQcQUcQPcQsQUsQPsQiQUiQlQUlQf">; //////////////////////////////////////////////////////////////////////////////// -// E.3.27 Reverse vector elements (sdap endianness) +// E.3.27 Reverse vector elements def VREV64 : Inst<"vrev64", "dd", "csiUcUsUiPcPsfQcQsQiQUcQUsQUiQPcQPsQf", OP_REV64>; def VREV32 : Inst<"vrev32", "dd", "csUcUsPcPsQcQsQUcQUsQPcQPs", OP_REV32>; diff --git a/include/clang/CodeGen/BackendUtil.h b/include/clang/CodeGen/BackendUtil.h index abcef8130dbc..9636d6e527c2 100644 --- a/include/clang/CodeGen/BackendUtil.h +++ b/include/clang/CodeGen/BackendUtil.h @@ -19,6 +19,7 @@ namespace clang { class Diagnostic; class CodeGenOptions; class TargetOptions; + class LangOptions; enum BackendAction { Backend_EmitAssembly, ///< Emit native assembly files @@ -30,7 +31,8 @@ namespace clang { }; void EmitBackendOutput(Diagnostic &Diags, const CodeGenOptions &CGOpts, - const TargetOptions &TOpts, llvm::Module *M, + const TargetOptions &TOpts, const LangOptions &LOpts, + llvm::Module *M, BackendAction Action, llvm::raw_ostream *OS); } diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index 14d8f67b9de3..d8e9e3d3e88b 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -143,6 +143,8 @@ def femit_coverage_data: Flag<"-femit-coverage-data">, def coverage_file : Separate<"-coverage-file">, HelpText<"Emit coverage data to this filename. The extension will be replaced.">; def coverage_file_EQ : Joined<"-coverage-file=">, Alias<coverage_file>; +def fuse_register_sized_bitfield_access: Flag<"-fuse-register-sized-bitfield-access">, + HelpText<"Use register sized accesses to bit-fields, when possible.">; def relaxed_aliasing : Flag<"-relaxed-aliasing">, HelpText<"Turn off Type Based Alias Analysis">; def masm_verbose : Flag<"-masm-verbose">, @@ -157,6 +159,8 @@ def mfloat_abi : Separate<"-mfloat-abi">, HelpText<"The float ABI to use">; def mlimit_float_precision : Separate<"-mlimit-float-precision">, HelpText<"Limit float precision to the given value">; +def mno_exec_stack : Flag<"-mnoexecstack">, + HelpText<"Mark the file as not needing an executable stack">; def mno_zero_initialized_in_bss : Flag<"-mno-zero-initialized-in-bss">, HelpText<"Do not put zero initialized data in the BSS">; def momit_leaf_frame_pointer : Flag<"-momit-leaf-frame-pointer">, @@ -204,6 +208,7 @@ def MQ : Separate<"-MQ">, HelpText<"Specify target to quote for dependency">; def MT : Separate<"-MT">, HelpText<"Specify target for dependency">; def MP : Flag<"-MP">, HelpText<"Create phony target for each dependency (other than main file)">; +def MG : Flag<"-MG">, HelpText<"Add missing headers to dependency list">; //===----------------------------------------------------------------------===// // Diagnostic Options @@ -259,7 +264,7 @@ def ftabstop : Separate<"-ftabstop">, MetaVarName<"<N>">, def ferror_limit : Separate<"-ferror-limit">, MetaVarName<"<N>">, HelpText<"Set the maximum number of errors to emit before stopping (0 = no limit).">; def fmacro_backtrace_limit : Separate<"-fmacro-backtrace-limit">, MetaVarName<"<N>">, - HelpText<"Set the maximum number of entries to print in a macro instantiation backtrace (0 = no limit).">; + HelpText<"Set the maximum number of entries to print in a macro expansion backtrace (0 = no limit).">; def ftemplate_backtrace_limit : Separate<"-ftemplate-backtrace-limit">, MetaVarName<"<N>">, HelpText<"Set the maximum number of entries to print in a template instantiation backtrace (0 = no limit).">; def fmessage_length : Separate<"-fmessage-length">, MetaVarName<"<N>">, @@ -352,8 +357,6 @@ def ast_dump_xml : Flag<"-ast-dump-xml">, HelpText<"Build ASTs and then debug dump them in a verbose XML format">; def ast_view : Flag<"-ast-view">, HelpText<"Build ASTs and view them with GraphViz">; -def boostcon : Flag<"-boostcon">, - HelpText<"BoostCon workshop mode">; def print_decl_contexts : Flag<"-print-decl-contexts">, HelpText<"Print DeclContexts and their Decls">; def emit_pth : Flag<"-emit-pth">, @@ -383,6 +386,15 @@ def create_module : Flag<"-create-module">, HelpText<"Create a module definition file">; } +def arcmt_check : Flag<"-arcmt-check">, + HelpText<"Check for ARC migration issues that need manual handling">; +def arcmt_modify : Flag<"-arcmt-modify">, + HelpText<"Apply modifications to files to conform to ARC">; +def arcmt_migrate : Flag<"-arcmt-migrate">, + HelpText<"Apply modifications and produces temporary files that conform to ARC">; +def arcmt_migrate_directory : Separate<"-arcmt-migrate-directory">, + HelpText<"Directory for temporary files produced during ARC migration">; + def import_module : Separate<"-import-module">, HelpText<"Import a module definition file">; @@ -452,6 +464,8 @@ def fhidden_weak_vtables : Flag<"-fhidden-weak-vtables">, HelpText<"Generate weak vtables and RTTI with hidden visibility">; def std_EQ : Joined<"-std=">, HelpText<"Language standard to compile for">; +def stdlib_EQ : Joined<"-stdlib=">, + HelpText<"C++ standard library to use">; def fmath_errno : Flag<"-fmath-errno">, HelpText<"Require math functions to indicate errors by setting errno">; def fms_extensions : Flag<"-fms-extensions">, @@ -479,6 +493,18 @@ def fconstant_string_class : Separate<"-fconstant-string-class">, HelpText<"Specify the class to use for constant Objective-C string objects.">; def fno_constant_cfstrings : Flag<"-fno-constant-cfstrings">, HelpText<"Enable creation of CodeFoundation-type constant strings">; +def fobjc_arc : Flag<"-fobjc-arc">, + HelpText<"Synthesize retain and release calls for Objective-C pointers">; +def fobjc_arc_cxxlib_EQ : Joined<"-fobjc-arc-cxxlib=">, + HelpText<"Objective-C++ Automatic Reference Counting standard library kind">; +def fobjc_arc_exceptions : Flag<"-fobjc-arc-exceptions">, + HelpText<"Use EH-safe code when synthesizing retains and releases in -fobjc-arc">; +def fobjc_runtime_has_arc : Flag<"-fobjc-runtime-has-arc">, + HelpText<"The target Objective-C runtime provides ARC entrypoints">; +def fobjc_runtime_has_weak : Flag<"-fobjc-runtime-has-weak">, + HelpText<"The target Objective-C runtime supports ARC weak operations">; +def fobjc_runtime_has_terminate : Flag<"-fobjc-runtime-has-terminate">, + HelpText<"The target Objective-C runtime provides an objc_terminate entrypoint">; def fobjc_gc : Flag<"-fobjc-gc">, HelpText<"Enable Objective-C garbage collection">; def fobjc_gc_only : Flag<"-fobjc-gc-only">, @@ -493,8 +519,10 @@ def print_ivar_layout : Flag<"-print-ivar-layout">, HelpText<"Enable Objective-C Ivar layout bitmap print trace">; def fobjc_nonfragile_abi : Flag<"-fobjc-nonfragile-abi">, HelpText<"enable objective-c's nonfragile abi">; -def fobjc_infer_related_result_type : Flag<"-fobjc-infer-related-result-type">, - HelpText<"infer Objective-C related result type based on method family">; +def fno_objc_infer_related_result_type : Flag< + "-fno-objc-infer-related-result-type">, + HelpText< + "do not infer Objective-C related result type based on method family">; def ftrapv : Flag<"-ftrapv">, HelpText<"Trap on integer overflow">; def ftrapv_handler : Separate<"-ftrapv-handler">, @@ -554,6 +582,8 @@ def fdelayed_template_parsing : Flag<"-fdelayed-template-parsing">, "translation unit ">; def funknown_anytype : Flag<"-funknown-anytype">, HelpText<"Enable parser support for the __unknown_anytype type; for testing purposes only">; +def fdebugger_support : Flag<"-fdebugger-support">, + HelpText<"Enable special debugger support behavior">; def fdeprecated_macro : Flag<"-fdeprecated-macro">, HelpText<"Defines the __DEPRECATED macro">; def fno_deprecated_macro : Flag<"-fno-deprecated-macro">, diff --git a/include/clang/Driver/Compilation.h b/include/clang/Driver/Compilation.h index 22d6b4ec6c8f..2db712d9321f 100644 --- a/include/clang/Driver/Compilation.h +++ b/include/clang/Driver/Compilation.h @@ -14,7 +14,6 @@ #include "clang/Driver/Util.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/SmallVector.h" namespace llvm { class raw_ostream; diff --git a/include/clang/Driver/Driver.h b/include/clang/Driver/Driver.h index 5a7d830b069d..b6951663148b 100644 --- a/include/clang/Driver/Driver.h +++ b/include/clang/Driver/Driver.h @@ -357,6 +357,8 @@ public: bool ShouldUseClangCompiler(const Compilation &C, const JobAction &JA, const llvm::Triple &ArchName) const; + bool IsUsingLTO(const ArgList &Args) const; + /// @} /// GetReleaseVersion - Parse (([0-9]+)(.([0-9]+)(.([0-9]+)?))?)? and diff --git a/include/clang/Driver/ObjCRuntime.h b/include/clang/Driver/ObjCRuntime.h new file mode 100644 index 000000000000..55164604338d --- /dev/null +++ b/include/clang/Driver/ObjCRuntime.h @@ -0,0 +1,46 @@ +//===--- ObjCRuntime.h - Objective C runtime features -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef CLANG_DRIVER_OBJCRUNTIME_H_ +#define CLANG_DRIVER_OBJCRUNTIME_H_ + +namespace clang { +namespace driver { + +class ObjCRuntime { +public: + enum Kind { GNU, NeXT }; +private: + unsigned RuntimeKind : 1; +public: + void setKind(Kind k) { RuntimeKind = k; } + Kind getKind() const { return static_cast<Kind>(RuntimeKind); } + + /// True if the runtime provides native ARC entrypoints. ARC may + /// still be usable without this if the tool-chain provides a + /// statically-linked runtime support library. + unsigned HasARC : 1; + + /// True if the runtime supports ARC zeroing __weak. + unsigned HasWeak : 1; + + /// True if the runtime provides the following entrypoint: + /// void objc_terminate(void); + /// If available, this will be called instead of abort() when an + /// exception is thrown out of an EH cleanup. + unsigned HasTerminate : 1; + + ObjCRuntime() : RuntimeKind(NeXT), HasARC(false), HasWeak(false), + HasTerminate(false) {} +}; + +} +} + +#endif diff --git a/include/clang/Driver/Option.h b/include/clang/Driver/Option.h index 9625465f48f4..9dfa4614009f 100644 --- a/include/clang/Driver/Option.h +++ b/include/clang/Driver/Option.h @@ -11,6 +11,7 @@ #define CLANG_DRIVER_OPTION_H_ #include "clang/Driver/OptSpecifier.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Support/Casting.h" using llvm::isa; using llvm::cast; @@ -64,7 +65,7 @@ namespace driver { OptSpecifier ID; /// The option name. - const char *Name; + llvm::StringRef Name; /// Group this option is a member of, if any. const OptionGroup *Group; @@ -103,7 +104,7 @@ namespace driver { unsigned getID() const { return ID.getID(); } OptionClass getKind() const { return Kind; } - const char *getName() const { return Name; } + llvm::StringRef getName() const { return Name; } const OptionGroup *getGroup() const { return Group; } const Option *getAlias() const { return Alias; } @@ -143,7 +144,7 @@ namespace driver { /// getRenderName - Return the name to use when rendering this /// option. - const char *getRenderName() const { + llvm::StringRef getRenderName() const { return getUnaliasedOption()->getName(); } diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index 72039766d907..d5482765e756 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -112,6 +112,17 @@ def ccc_print_phases : Flag<"-ccc-print-phases">, CCCDebugOpt, def ccc_print_bindings : Flag<"-ccc-print-bindings">, CCCDebugOpt, HelpText<"Show bindings of tools to actions">; +def ccc_arcmt_check : Flag<"-ccc-arcmt-check">, CCCDriverOpt, + HelpText<"Check for ARC migration issues that need manual handling">; +def ccc_arcmt_modify : Flag<"-ccc-arcmt-modify">, CCCDriverOpt, + HelpText<"Apply modifications to files to conform to ARC">; +def ccc_arrmt_check : Flag<"-ccc-arrmt-check">, Alias<ccc_arcmt_check>; +def ccc_arrmt_modify : Flag<"-ccc-arrmt-modify">, Alias<ccc_arcmt_modify>; +def ccc_arcmt_migrate : Separate<"-ccc-arcmt-migrate">, CCCDriverOpt, + HelpText<"Apply modifications and produces temporary files that conform to ARC">; +def ccc_arcmt_migrate_EQ : Joined<"-ccc-arcmt-migrate=">, CCCDriverOpt, + Alias<ccc_arcmt_migrate>; + // Make sure all other -ccc- options are rejected. def ccc_ : Joined<"-ccc-">, Group<ccc_Group>, Flags<[Unsupported]>; @@ -382,6 +393,10 @@ def fno_verbose_asm : Flag<"-fno-verbose-asm">, Group<f_Group>; def fno_working_directory : Flag<"-fno-working-directory">, Group<f_Group>; def fno_wrapv : Flag<"-fno-wrapv">, Group<f_Group>; def fno_zero_initialized_in_bss : Flag<"-fno-zero-initialized-in-bss">, Group<f_Group>; +def fobjc_arc : Flag<"-fobjc-arc">, Group<f_Group>; +def fno_objc_arc : Flag<"-fno-objc-arc">, Group<f_Group>; +def fobjc_arc_exceptions : Flag<"-fobjc-arc-exceptions">, Group<f_Group>; +def fno_objc_arc_exceptions : Flag<"-fno-objc-arc-exceptions">, Group<f_Group>; def fobjc_atdefs : Flag<"-fobjc-atdefs">, Group<clang_ignored_f_Group>; def fobjc_call_cxx_cdtors : Flag<"-fobjc-call-cxx-cdtors">, Group<clang_ignored_f_Group>; def fobjc_default_synthesize_properties : @@ -409,6 +424,7 @@ def fomit_frame_pointer : Flag<"-fomit-frame-pointer">, Group<f_Group>; def fopenmp : Flag<"-fopenmp">, Group<f_Group>; def force__cpusubtype__ALL : Flag<"-force_cpusubtype_ALL">; def force__flat__namespace : Flag<"-force_flat_namespace">; +def force__load : Separate<"-force_load">; def foutput_class_dir_EQ : Joined<"-foutput-class-dir=">, Group<f_Group>; def fpascal_strings : Flag<"-fpascal-strings">, Group<f_Group>; def fpch_preprocess : Flag<"-fpch-preprocess">, Group<f_Group>; @@ -803,8 +819,8 @@ def _specs : Separate<"--specs">, Alias<specs_EQ>; def _static : Flag<"--static">, Alias<static>; def _std_EQ : Joined<"--std=">, Alias<std_EQ>; def _std : Separate<"--std">, Alias<std_EQ>; -def _stdlib_EQ : Joined<"--stdlib=">, Alias<std_EQ>; -def _stdlib : Separate<"--stdlib">, Alias<std_EQ>; +def _stdlib_EQ : Joined<"--stdlib=">, Alias<stdlib_EQ>; +def _stdlib : Separate<"--stdlib">, Alias<stdlib_EQ>; def _sysroot_EQ : Joined<"--sysroot=">; def _sysroot : Separate<"--sysroot">, Alias<_sysroot_EQ>; def _target_help : Flag<"--target-help">; diff --git a/include/clang/Driver/ToolChain.h b/include/clang/Driver/ToolChain.h index 626d54c37b8a..4836d3ffac22 100644 --- a/include/clang/Driver/ToolChain.h +++ b/include/clang/Driver/ToolChain.h @@ -26,6 +26,7 @@ namespace driver { class HostInfo; class InputArgList; class JobAction; + class ObjCRuntime; class Tool; /// ToolChain - Access to tools for a single platform. @@ -177,6 +178,12 @@ public: /// Clang. virtual std::string ComputeEffectiveClangTriple(const ArgList &Args) const; + /// configureObjCRuntime - Configure the known properties of the + /// Objective-C runtime for this platform. + /// + /// FIXME: this doesn't really belong here. + virtual void configureObjCRuntime(ObjCRuntime &runtime) const; + // GetCXXStdlibType - Determine the C++ standard library type to use with the // given compilation arguments. virtual CXXStdlibType GetCXXStdlibType(const ArgList &Args) const; @@ -184,7 +191,8 @@ public: /// AddClangCXXStdlibIncludeArgs - Add the clang -cc1 level arguments to set /// the include paths to use for the given C++ standard library type. virtual void AddClangCXXStdlibIncludeArgs(const ArgList &Args, - ArgStringList &CmdArgs) const; + ArgStringList &CmdArgs, + bool ObjCXXAutoRefCount) const; /// AddCXXStdlibLibArgs - Add the system specific linker arguments to use /// for the given C++ standard library type. diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h index 339297eb9362..58a60a1f9d87 100644 --- a/include/clang/Frontend/ASTUnit.h +++ b/include/clang/Frontend/ASTUnit.h @@ -249,9 +249,9 @@ private: /// \brief Whether we should be caching code-completion results. bool ShouldCacheCodeCompletionResults; - /// \brief Whether we want to include nested macro instantiations in the + /// \brief Whether we want to include nested macro expansions in the /// detailed preprocessing record. - bool NestedMacroInstantiations; + bool NestedMacroExpansions; static void ConfigureDiags(llvm::IntrusiveRefCntPtr<Diagnostic> &Diags, const char **ArgBegin, const char **ArgEnd, @@ -363,7 +363,7 @@ private: unsigned MaxLines, bool &CreatedBuffer); llvm::MemoryBuffer *getMainBufferWithPrecompiledPreamble( - CompilerInvocation PreambleInvocation, + const CompilerInvocation &PreambleInvocationIn, bool AllowRebuild = true, unsigned MaxLines = 0); void RealizeTopLevelDeclsFromPreamble(); @@ -612,7 +612,7 @@ public: bool PrecompilePreamble = false, bool CompleteTranslationUnit = true, bool CacheCodeCompletionResults = false, - bool NestedMacroInstantiations = true); + bool NestedMacroExpansions = true); /// LoadFromCommandLine - Create an ASTUnit from a vector of command line /// arguments, which must specify exactly one source file. @@ -642,7 +642,7 @@ public: bool CacheCodeCompletionResults = false, bool CXXPrecompilePreamble = false, bool CXXChainedPCH = false, - bool NestedMacroInstantiations = true); + bool NestedMacroExpansions = true); /// \brief Reparse the source files using the same command-line options that /// were originally used to produce this translation unit. @@ -680,8 +680,8 @@ public: /// \brief Save this translation unit to a file with the given name. /// - /// \returns True if an error occurred, false otherwise. - bool Save(llvm::StringRef File); + /// \returns An indication of whether the save was successful or not. + CXSaveError Save(llvm::StringRef File); /// \brief Serialize this translation unit with the given output stream. /// diff --git a/include/clang/Frontend/CodeGenOptions.h b/include/clang/Frontend/CodeGenOptions.h index 1c686c76df5f..5d040b4f266c 100644 --- a/include/clang/Frontend/CodeGenOptions.h +++ b/include/clang/Frontend/CodeGenOptions.h @@ -36,6 +36,7 @@ public: }; unsigned AsmVerbose : 1; /// -dA, -fverbose-asm. + unsigned ObjCAutoRefCountExceptions : 1; /// Whether ARC should be EH-safe. unsigned CXAAtExit : 1; /// Use __cxa_atexit for calling destructors. unsigned CXXCtorDtorAliases: 1; /// Emit complete ctors/dtors as linker /// aliases to base ctors when possible. @@ -69,11 +70,14 @@ public: unsigned MergeAllConstants : 1; /// Merge identical constants. unsigned NoCommon : 1; /// Set when -fno-common or C++ is enabled. unsigned NoDwarf2CFIAsm : 1; /// Set when -fno-dwarf2-cfi-asm is enabled. + unsigned NoExecStack : 1; /// Set when -Wa,--noexecstack is enabled. unsigned NoImplicitFloat : 1; /// Set when -mno-implicit-float is enabled. unsigned NoInfsFPMath : 1; /// Assume FP arguments, results not +-Inf. unsigned NoNaNsFPMath : 1; /// Assume FP arguments, results not NaN. unsigned NoZeroInitializedInBSS : 1; /// -fno-zero-initialized-in-bss unsigned ObjCDispatchMethod : 2; /// Method of Objective-C dispatch to use. + unsigned ObjCRuntimeHasARC : 1; /// The target runtime supports ARC natively + unsigned ObjCRuntimeHasTerminate : 1; /// The ObjC runtime has objc_terminate unsigned OmitLeafFramePointer : 1; /// Set when -momit-leaf-frame-pointer is /// enabled. unsigned OptimizationLevel : 3; /// The -O[0-4] option specified. @@ -89,6 +93,11 @@ public: unsigned UnrollLoops : 1; /// Control whether loops are unrolled. unsigned UnsafeFPMath : 1; /// Allow unsafe floating point optzns. unsigned UnwindTables : 1; /// Emit unwind tables. + + /// Attempt to use register sized accesses to bit-fields in structures, when + /// possible. + unsigned UseRegisterSizedBitfieldAccess : 1; + unsigned VerifyModule : 1; /// Control whether the module should be run /// through the LLVM Verifier. @@ -159,7 +168,10 @@ public: NoNaNsFPMath = 0; NoZeroInitializedInBSS = 0; NumRegisterParameters = 0; + ObjCAutoRefCountExceptions = 0; ObjCDispatchMethod = Legacy; + ObjCRuntimeHasARC = 0; + ObjCRuntimeHasTerminate = 0; OmitLeafFramePointer = 0; OptimizationLevel = 0; OptimizeSize = 0; @@ -173,6 +185,7 @@ public: UnrollLoops = 0; UnsafeFPMath = 0; UnwindTables = 0; + UseRegisterSizedBitfieldAccess = 0; VerifyModule = 1; Inlining = NoInlining; diff --git a/include/clang/Frontend/DependencyOutputOptions.h b/include/clang/Frontend/DependencyOutputOptions.h index 35aa6c6aace6..1e22c227fcea 100644 --- a/include/clang/Frontend/DependencyOutputOptions.h +++ b/include/clang/Frontend/DependencyOutputOptions.h @@ -24,6 +24,7 @@ public: unsigned UsePhonyTargets : 1; ///< Include phony targets for each /// dependency, which can avoid some 'make' /// problems. + unsigned AddMissingHeaderDeps : 1; ///< Add missing headers to dependency list /// The file to write dependency output to. std::string OutputFile; @@ -43,6 +44,7 @@ public: IncludeSystemHeaders = 0; ShowHeaderIncludes = 0; UsePhonyTargets = 0; + AddMissingHeaderDeps = 0; } }; diff --git a/include/clang/Frontend/DiagnosticOptions.h b/include/clang/Frontend/DiagnosticOptions.h index 56093c3c950c..5ae8eb367788 100644 --- a/include/clang/Frontend/DiagnosticOptions.h +++ b/include/clang/Frontend/DiagnosticOptions.h @@ -49,8 +49,7 @@ public: /// input source file. unsigned ErrorLimit; /// Limit # errors emitted. - unsigned MacroBacktraceLimit; /// Limit depth of macro instantiation - /// backtrace. + unsigned MacroBacktraceLimit; /// Limit depth of macro expansion backtrace. unsigned TemplateBacktraceLimit; /// Limit depth of instantiation backtrace. /// The distance between tab stops. diff --git a/include/clang/Frontend/FrontendAction.h b/include/clang/Frontend/FrontendAction.h index ee0863a4776f..f335475665fd 100644 --- a/include/clang/Frontend/FrontendAction.h +++ b/include/clang/Frontend/FrontendAction.h @@ -51,6 +51,7 @@ class FrontendAction { llvm::OwningPtr<ASTUnit> CurrentASTUnit; CompilerInstance *Instance; friend class ASTMergeAction; + friend class WrapperFrontendAction; private: ASTConsumer* CreateWrappedASTConsumer(CompilerInstance &CI, @@ -77,6 +78,14 @@ protected: virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, llvm::StringRef InFile) = 0; + /// \brief Callback before starting processing a single input, giving the + /// opportunity to modify the CompilerInvocation or do some other action + /// before BeginSourceFileAction is called. + /// + /// \return True on success; on failure \see BeginSourceFileAction() and + /// ExecutionAction() and EndSourceFileAction() will not be called. + virtual bool BeginInvocation(CompilerInstance &CI) { return true; } + /// BeginSourceFileAction - Callback at the start of processing a single /// input. /// @@ -253,6 +262,36 @@ public: virtual bool usesPreprocessorOnly() const { return true; } }; +/// WrapperFrontendAction - A frontend action which simply wraps some other +/// runtime specified frontend action. Deriving from this class allows an +/// action to inject custom logic around some existing action's behavior. It +/// implements every virtual method in the FrontendAction interface by +/// forwarding to the wrapped action. +class WrapperFrontendAction : public FrontendAction { + llvm::OwningPtr<FrontendAction> WrappedAction; + +protected: + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + llvm::StringRef InFile); + virtual bool BeginInvocation(CompilerInstance &CI); + virtual bool BeginSourceFileAction(CompilerInstance &CI, + llvm::StringRef Filename); + virtual void ExecuteAction(); + virtual void EndSourceFileAction(); + +public: + /// Construct a WrapperFrontendAction from an existing action, taking + /// ownership of it. + WrapperFrontendAction(FrontendAction *WrappedAction); + + virtual bool usesPreprocessorOnly() const; + virtual bool usesCompleteTranslationUnit(); + virtual bool hasPCHSupport() const; + virtual bool hasASTFileSupport() const; + virtual bool hasIRSupport() const; + virtual bool hasCodeCompletionSupport() const; +}; + } // end namespace clang #endif diff --git a/include/clang/Frontend/FrontendActions.h b/include/clang/Frontend/FrontendActions.h index 4e67449b8549..b409ad1e0963 100644 --- a/include/clang/Frontend/FrontendActions.h +++ b/include/clang/Frontend/FrontendActions.h @@ -97,12 +97,6 @@ public: virtual bool hasCodeCompletionSupport() const { return true; } }; -class BoostConAction : public SyntaxOnlyAction { -protected: - virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - llvm::StringRef InFile); -}; - /** * \brief Frontend action adaptor that merges ASTs together. * diff --git a/include/clang/Frontend/FrontendOptions.h b/include/clang/Frontend/FrontendOptions.h index 02f6f868fe49..225a955b4ac6 100644 --- a/include/clang/Frontend/FrontendOptions.h +++ b/include/clang/Frontend/FrontendOptions.h @@ -24,7 +24,6 @@ namespace frontend { ASTDumpXML, ///< Parse ASTs and dump them in XML. ASTPrint, ///< Parse ASTs and print them. ASTView, ///< Parse ASTs and view them in Graphviz. - BoostCon, ///< BoostCon mode. CreateModule, ///< Create module definition DumpRawTokens, ///< Dump out raw tokens. DumpTokens, ///< Dump out preprocessed tokens. @@ -77,6 +76,15 @@ public: unsigned FixWhatYouCan : 1; ///< Apply fixes even if there are /// unfixable errors. + enum { + ARCMT_None, + ARCMT_Check, + ARCMT_Modify, + ARCMT_Migrate + } ARCMTAction; + + std::string ARCMTMigrateDir; + /// The input files and their types. std::vector<std::pair<InputKind, std::string> > Inputs; @@ -131,6 +139,7 @@ public: ShowStats = 0; ShowTimers = 0; ShowVersion = 0; + ARCMTAction = ARCMT_None; } /// getInputKindForExtension - Return the appropriate input kind for a file diff --git a/include/clang/Frontend/HeaderSearchOptions.h b/include/clang/Frontend/HeaderSearchOptions.h index b0669eba4ccc..0347f98fd5ba 100644 --- a/include/clang/Frontend/HeaderSearchOptions.h +++ b/include/clang/Frontend/HeaderSearchOptions.h @@ -17,10 +17,12 @@ namespace clang { namespace frontend { /// IncludeDirGroup - Identifiers the group a include entry belongs to, which - /// represents its relative positive in the search list. + /// represents its relative positive in the search list. A #include of a "" + /// path starts at the -iquote group, then searches the Angled group, then + /// searches the system group, etc. enum IncludeDirGroup { - Quoted = 0, ///< `#include ""` paths. Thing `gcc -iquote`. - Angled, ///< Paths for both `#include ""` and `#include <>`. (`-I`) + Quoted = 0, ///< '#include ""' paths, added by'gcc -iquote'. + Angled, ///< Paths for '#include <>' added by '-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. @@ -37,15 +39,15 @@ public: unsigned IsUserSupplied : 1; unsigned IsFramework : 1; - /// IsSysRootRelative - This is true if an absolute path should be treated - /// relative to the sysroot, or false if it should always be the absolute + /// IgnoreSysRoot - This is false if an absolute path should be treated + /// relative to the sysroot, or true if it should always be the absolute /// path. - unsigned IsSysRootRelative : 1; + unsigned IgnoreSysRoot : 1; Entry(llvm::StringRef path, frontend::IncludeDirGroup group, - bool isUserSupplied, bool isFramework, bool isSysRootRelative) + bool isUserSupplied, bool isFramework, bool ignoreSysRoot) : Path(path), Group(group), IsUserSupplied(isUserSupplied), - IsFramework(isFramework), IsSysRootRelative(isSysRootRelative) {} + IsFramework(isFramework), IgnoreSysRoot(ignoreSysRoot) {} }; /// If non-empty, the directory to use as a "virtual system root" for include @@ -80,20 +82,23 @@ public: /// Include the system standard C++ library include search directories. unsigned UseStandardCXXIncludes : 1; + /// Use libc++ instead of the default libstdc++. + unsigned UseLibcxx : 1; + /// Whether header search information should be output as for -v. unsigned Verbose : 1; public: HeaderSearchOptions(llvm::StringRef _Sysroot = "/") : Sysroot(_Sysroot), UseBuiltinIncludes(true), - UseStandardIncludes(true), UseStandardCXXIncludes(true), + UseStandardIncludes(true), UseStandardCXXIncludes(true), UseLibcxx(false), Verbose(false) {} /// AddPath - Add the \arg Path path to the specified \arg Group list. void AddPath(llvm::StringRef Path, frontend::IncludeDirGroup Group, - bool IsUserSupplied, bool IsFramework, bool IsSysRootRelative) { + bool IsUserSupplied, bool IsFramework, bool IgnoreSysRoot) { UserEntries.push_back(Entry(Path, Group, IsUserSupplied, IsFramework, - IsSysRootRelative)); + IgnoreSysRoot)); } }; diff --git a/include/clang/Frontend/PreprocessorOptions.h b/include/clang/Frontend/PreprocessorOptions.h index e471c5cf1d82..2e16c97e7d43 100644 --- a/include/clang/Frontend/PreprocessorOptions.h +++ b/include/clang/Frontend/PreprocessorOptions.h @@ -1,4 +1,4 @@ -//===--- PreprocessorOptionms.h ---------------------------------*- C++ -*-===// +//===--- PreprocessorOptions.h ----------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -26,6 +26,15 @@ namespace clang { class Preprocessor; class LangOptions; +/// \brief Enumerate the kinds of standard library that +enum ObjCXXARCStandardLibraryKind { + ARCXX_nolib, + /// \brief libc++ + ARCXX_libcxx, + /// \brief libstdc++ + ARCXX_libstdcxx +}; + /// PreprocessorOptions - This class is used for passing the various options /// used in preprocessor initialization to InitializePreprocessor(). class PreprocessorOptions { @@ -39,11 +48,11 @@ public: unsigned DetailedRecord : 1; /// Whether we should maintain a detailed /// record of all macro definitions and - /// instantiations. + /// expansions. /// \brief Whether the detailed preprocessing record includes nested macro - /// instantiations. - unsigned DetailedRecordIncludesNestedMacroInstantiations : 1; + /// expansions. + unsigned DetailedRecordIncludesNestedMacroExpansions : 1; /// The implicit PCH included at the start of the translation unit, or empty. std::string ImplicitPCHInclude; @@ -104,6 +113,11 @@ public: /// compiler invocation and its buffers will be reused. bool RetainRemappedFileBuffers; + /// \brief The Objective-C++ ARC standard library that we should support, + /// by providing appropriate definitions to retrofit the standard library + /// with support for lifetime-qualified pointers. + ObjCXXARCStandardLibraryKind ObjCXXARCStandardLibrary; + typedef std::vector<std::pair<std::string, std::string> >::iterator remapped_file_iterator; typedef std::vector<std::pair<std::string, std::string> >::const_iterator @@ -140,12 +154,13 @@ public: public: PreprocessorOptions() : UsePredefines(true), DetailedRecord(false), - DetailedRecordIncludesNestedMacroInstantiations(true), + DetailedRecordIncludesNestedMacroExpansions(true), DisablePCHValidation(false), DisableStatCache(false), DumpDeserializedPCHDecls(false), PrecompiledPreambleBytes(0, true), RemappedFilesKeepOriginalName(true), - RetainRemappedFileBuffers(false) { } + RetainRemappedFileBuffers(false), + ObjCXXARCStandardLibrary(ARCXX_nolib) { } void addMacroDef(llvm::StringRef Name) { Macros.push_back(std::make_pair(Name, false)); diff --git a/include/clang/Frontend/TextDiagnosticPrinter.h b/include/clang/Frontend/TextDiagnosticPrinter.h index d7d2692cb547..79a9916cb435 100644 --- a/include/clang/Frontend/TextDiagnosticPrinter.h +++ b/include/clang/Frontend/TextDiagnosticPrinter.h @@ -62,18 +62,17 @@ public: std::string &CaretLine, const std::string &SourceLine); - void EmitCaretDiagnostic(Diagnostic::Level Level, SourceLocation Loc, - CharSourceRange *Ranges, unsigned NumRanges, - const SourceManager &SM, - const FixItHint *Hints, - unsigned NumHints, - unsigned Columns, - unsigned OnMacroInst, - unsigned MacroSkipStart, - unsigned MacroSkipEnd); - virtual void HandleDiagnostic(Diagnostic::Level Level, const DiagnosticInfo &Info); + +private: + void EmitCaretDiagnostic(SourceLocation Loc, CharSourceRange *Ranges, + unsigned NumRanges, const SourceManager &SM, + const FixItHint *Hints, + unsigned NumHints, unsigned Columns, + unsigned OnMacroInst, unsigned MacroSkipStart, + unsigned MacroSkipEnd); + }; } // end namespace clang diff --git a/include/clang/Frontend/Utils.h b/include/clang/Frontend/Utils.h index 3c34c2dce24b..93d2c7d501e7 100644 --- a/include/clang/Frontend/Utils.h +++ b/include/clang/Frontend/Utils.h @@ -19,6 +19,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/Support/raw_ostream.h" +#include "clang/Basic/Diagnostic.h" namespace llvm { class Triple; diff --git a/include/clang/Lex/Lexer.h b/include/clang/Lex/Lexer.h index 7c3d863bd3d3..f4297627e86f 100644 --- a/include/clang/Lex/Lexer.h +++ b/include/clang/Lex/Lexer.h @@ -95,8 +95,8 @@ public: /// _Pragma expansion. This has a variety of magic semantics that this method /// sets up. It returns a new'd Lexer that must be delete'd when done. static Lexer *Create_PragmaLexer(SourceLocation SpellingLoc, - SourceLocation InstantiationLocStart, - SourceLocation InstantiationLocEnd, + SourceLocation ExpansionLocStart, + SourceLocation ExpansionLocEnd, unsigned TokLen, Preprocessor &PP); @@ -241,8 +241,8 @@ public: /// is not necessary to copy any data, then the returned string may /// not point into the provided buffer. /// - /// This method lexes at the instantiation depth of the given - /// location and does not jump to the instantiation or spelling + /// This method lexes at the expansion depth of the given + /// location and does not jump to the expansion or spelling /// location. static llvm::StringRef getSpelling(SourceLocation loc, llvm::SmallVectorImpl<char> &buffer, @@ -293,7 +293,19 @@ public: static SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset, const SourceManager &SM, const LangOptions &Features); - + + /// \brief Returns true if the given MacroID location points at the first + /// token of the macro expansion. + static bool isAtStartOfMacroExpansion(SourceLocation loc, + const SourceManager &SM, + const LangOptions &LangOpts); + + /// \brief Returns true if the given MacroID location points at the last + /// token of the macro expansion. + static bool isAtEndOfMacroExpansion(SourceLocation loc, + const SourceManager &SM, + const LangOptions &LangOpts); + /// \brief Compute the preamble of the given file. /// /// The preamble of a file contains the initial comments, include directives, diff --git a/include/clang/Lex/LiteralSupport.h b/include/clang/Lex/LiteralSupport.h index ec3d9c58d67e..0dbcd6d72d63 100644 --- a/include/clang/Lex/LiteralSupport.h +++ b/include/clang/Lex/LiteralSupport.h @@ -167,7 +167,9 @@ public: bool AnyWide; bool Pascal; - const char *GetString() { return ResultBuf.data(); } + llvm::StringRef GetString() const { + return llvm::StringRef(ResultBuf.data(), GetStringLength()); + } unsigned GetStringLength() const { return ResultPtr-ResultBuf.data(); } unsigned GetNumStringChars() const { diff --git a/include/clang/Lex/MacroInfo.h b/include/clang/Lex/MacroInfo.h index 7c4cfb007233..9e9d7cf500a4 100644 --- a/include/clang/Lex/MacroInfo.h +++ b/include/clang/Lex/MacroInfo.h @@ -43,6 +43,10 @@ class MacroInfo { /// to. llvm::SmallVector<Token, 8> ReplacementTokens; + /// \brief Length in characters of the macro definition. + mutable unsigned DefinitionLength; + mutable bool IsDefinitionLengthCached : 1; + /// IsFunctionLike - True if this macro is a function-like macro, false if it /// is an object-like macro. bool IsFunctionLike : 1; @@ -116,6 +120,13 @@ public: /// getDefinitionEndLoc - Return the location of the last token in the macro. /// SourceLocation getDefinitionEndLoc() const { return EndLocation; } + + /// \brief Get length in characters of the macro definition. + unsigned getDefinitionLength(SourceManager &SM) const { + if (IsDefinitionLengthCached) + return DefinitionLength; + return getDefinitionLengthSlow(SM); + } /// isIdenticalTo - Return true if the specified macro definition is equal to /// this macro in spelling, arguments, and whitespace. This is used to emit @@ -232,6 +243,8 @@ public: /// AddTokenToBody - Add the specified token to the replacement text for the /// macro. void AddTokenToBody(const Token &Tok) { + assert(!IsDefinitionLengthCached && + "Changing replacement tokens after definition length got calculated"); ReplacementTokens.push_back(Tok); } @@ -248,6 +261,9 @@ public: assert(!IsDisabled && "Cannot disable an already-disabled macro!"); IsDisabled = true; } + +private: + unsigned getDefinitionLengthSlow(SourceManager &SM) const; }; } // end namespace clang diff --git a/include/clang/Lex/PPCallbacks.h b/include/clang/Lex/PPCallbacks.h index fd07a29f8e9d..a7948153a728 100644 --- a/include/clang/Lex/PPCallbacks.h +++ b/include/clang/Lex/PPCallbacks.h @@ -16,6 +16,7 @@ #include "clang/Lex/DirectoryLookup.h" #include "clang/Basic/SourceLocation.h" +#include "clang/Basic/DiagnosticIDs.h" #include "llvm/ADT/StringRef.h" #include <string> @@ -124,6 +125,24 @@ public: virtual void PragmaMessage(SourceLocation Loc, llvm::StringRef Str) { } + /// PragmaDiagnosticPush - This callback is invoked when a + /// #pragma gcc dianostic push directive is read. + virtual void PragmaDiagnosticPush(SourceLocation Loc, + llvm::StringRef Namespace) { + } + + /// PragmaDiagnosticPop - This callback is invoked when a + /// #pragma gcc dianostic pop directive is read. + virtual void PragmaDiagnosticPop(SourceLocation Loc, + llvm::StringRef Namespace) { + } + + /// PragmaDiagnostic - This callback is invoked when a + /// #pragma gcc dianostic directive is read. + virtual void PragmaDiagnostic(SourceLocation Loc, llvm::StringRef Namespace, + diag::Mapping mapping, llvm::StringRef Str) { + } + /// MacroExpands - This is called by /// Preprocessor::HandleMacroExpandedIdentifier when a macro invocation is /// found. @@ -232,6 +251,24 @@ public: Second->PragmaMessage(Loc, Str); } + virtual void PragmaDiagnosticPush(SourceLocation Loc, + llvm::StringRef Namespace) { + First->PragmaDiagnosticPush(Loc, Namespace); + Second->PragmaDiagnosticPush(Loc, Namespace); + } + + virtual void PragmaDiagnosticPop(SourceLocation Loc, + llvm::StringRef Namespace) { + First->PragmaDiagnosticPop(Loc, Namespace); + Second->PragmaDiagnosticPop(Loc, Namespace); + } + + virtual void PragmaDiagnostic(SourceLocation Loc, llvm::StringRef Namespace, + diag::Mapping mapping, llvm::StringRef Str) { + First->PragmaDiagnostic(Loc, Namespace, mapping, Str); + Second->PragmaDiagnostic(Loc, Namespace, mapping, Str); + } + virtual void MacroExpands(const Token &MacroNameTok, const MacroInfo* MI) { First->MacroExpands(MacroNameTok, MI); Second->MacroExpands(MacroNameTok, MI); diff --git a/include/clang/Lex/PreprocessingRecord.h b/include/clang/Lex/PreprocessingRecord.h index e498e9d0a020..b38303a2f40b 100644 --- a/include/clang/Lex/PreprocessingRecord.h +++ b/include/clang/Lex/PreprocessingRecord.h @@ -38,13 +38,13 @@ namespace clang { class FileEntry; /// \brief Base class that describes a preprocessed entity, which may be a - /// preprocessor directive or macro instantiation. + /// preprocessor directive or macro expansion. class PreprocessedEntity { public: /// \brief The kind of preprocessed entity an object describes. enum EntityKind { - /// \brief A macro instantiation. - MacroInstantiationKind, + /// \brief A macro expansion. + MacroExpansionKind, /// \brief A preprocessing directive whose kind is not specified. /// @@ -110,31 +110,31 @@ namespace clang { void operator delete(void* data) throw(); }; - /// \brief Records the location of a macro instantiation. - class MacroInstantiation : public PreprocessedEntity { - /// \brief The name of the macro being instantiation. + /// \brief Records the location of a macro expansion. + class MacroExpansion : public PreprocessedEntity { + /// \brief The name of the macro being expanded. IdentifierInfo *Name; /// \brief The definition of this macro. MacroDefinition *Definition; public: - MacroInstantiation(IdentifierInfo *Name, SourceRange Range, - MacroDefinition *Definition) - : PreprocessedEntity(MacroInstantiationKind, Range), Name(Name), + MacroExpansion(IdentifierInfo *Name, SourceRange Range, + MacroDefinition *Definition) + : PreprocessedEntity(MacroExpansionKind, Range), Name(Name), Definition(Definition) { } - /// \brief The name of the macro being instantiated. + /// \brief The name of the macro being expanded. IdentifierInfo *getName() const { return Name; } - /// \brief The definition of the macro being instantiated. + /// \brief The definition of the macro being expanded. MacroDefinition *getDefinition() const { return Definition; } // Implement isa/cast/dyncast/etc. static bool classof(const PreprocessedEntity *PE) { - return PE->getKind() == MacroInstantiationKind; + return PE->getKind() == MacroExpansionKind; } - static bool classof(const MacroInstantiation *) { return true; } + static bool classof(const MacroExpansion *) { return true; } }; @@ -256,11 +256,11 @@ namespace clang { /// \brief A record of the steps taken while preprocessing a source file, /// including the various preprocessing directives processed, macros - /// instantiated, etc. + /// expanded, etc. class PreprocessingRecord : public PPCallbacks { - /// \brief Whether we should include nested macro instantiations in + /// \brief Whether we should include nested macro expansions in /// the preprocessing record. - bool IncludeNestedMacroInstantiations; + bool IncludeNestedMacroExpansions; /// \brief Allocator used to store preprocessing objects. llvm::BumpPtrAllocator BumpAlloc; @@ -286,7 +286,7 @@ namespace clang { public: /// \brief Construct - explicit PreprocessingRecord(bool IncludeNestedMacroInstantiations); + explicit PreprocessingRecord(bool IncludeNestedMacroExpansions); /// \brief Allocate memory in the preprocessing record. void *Allocate(unsigned Size, unsigned Align = 8) { diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index 76e3f59ef4c4..f6f3205099a0 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/include/clang/Lex/Preprocessor.h @@ -29,6 +29,7 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/Support/Allocator.h" #include <vector> @@ -120,7 +121,7 @@ class Preprocessor : public llvm::RefCountedBase<Preprocessor> { /// Selectors - This table contains all the selectors in the program. Unlike /// IdentifierTable above, this table *isn't* populated by the preprocessor. - /// It is declared/instantiated here because it's role/lifetime is + /// It is declared/expanded here because it's role/lifetime is /// conceptually similar the IdentifierTable. In addition, the current control /// flow (in clang::ParseAST()), make it convenient to put here. /// FIXME: Make sure the lifetime of Identifiers/Selectors *isn't* tied to @@ -219,9 +220,9 @@ class Preprocessor : public llvm::RefCountedBase<Preprocessor> { /// previous macro value. llvm::DenseMap<IdentifierInfo*, std::vector<MacroInfo*> > PragmaPushMacroInfo; - /// \brief Instantiation source location for the last macro that expanded + /// \brief Expansion source location for the last macro that expanded /// to no tokens. - SourceLocation LastEmptyMacroInstantiationLoc; + SourceLocation LastEmptyMacroExpansionLoc; // Various statistics we track for performance analysis. unsigned NumDirectives, NumIncluded, NumDefined, NumUndefined, NumPragma; @@ -240,7 +241,15 @@ class Preprocessor : public llvm::RefCountedBase<Preprocessor> { unsigned NumCachedTokenLexers; TokenLexer *TokenLexerCache[TokenLexerCacheSize]; - /// \brief A record of the macro definitions and instantiations that + /// \brief Keeps macro expanded tokens for TokenLexers. + // + /// Works like a stack; a TokenLexer adds the macro expanded tokens that is + /// going to lex in the cache and when it finishes the tokens are removed + /// from the end of the cache. + llvm::SmallVector<Token, 16> MacroExpandedTokens; + std::vector<std::pair<TokenLexer *, size_t> > MacroExpandingLexersStack; + + /// \brief A record of the macro definitions and expansions that /// occurred during preprocessing. /// /// This is an optional side structure that can be enabled with @@ -371,10 +380,10 @@ public: macro_iterator macro_begin(bool IncludeExternalMacros = true) const; macro_iterator macro_end(bool IncludeExternalMacros = true) const; - /// \brief Instantiation source location for the last macro that expanded + /// \brief Expansion source location for the last macro that expanded /// to no tokens. - SourceLocation getLastEmptyMacroInstantiationLoc() const { - return LastEmptyMacroInstantiationLoc; + SourceLocation getLastEmptyMacroExpansionLoc() const { + return LastEmptyMacroExpansionLoc; } const std::string &getPredefines() const { return Predefines; } @@ -442,7 +451,7 @@ public: /// \brief Create a new preprocessing record, which will keep track of /// all macro expansions, macro definitions, etc. - void createPreprocessingRecord(bool IncludeNestedMacroInstantiations); + void createPreprocessingRecord(bool IncludeNestedMacroExpansions); /// EnterMainSourceFile - Enter the specified FileID as the main source file, /// which implicitly adds the builtin defines etc. @@ -658,7 +667,7 @@ public: /// getSpelling() - Return the 'spelling' of the token at the given /// location; does not go up to the spelling location or down to the - /// instantiation location. + /// expansion location. /// /// \param buffer A buffer which will be used only if the token requires /// "cleaning", e.g. if it contains trigraphs or escaped newlines @@ -721,7 +730,7 @@ public: /// CreateString - Plop the specified string into a scratch buffer and set the /// specified token's location and length to it. If specified, the source - /// location provides a location of the instantiation point of the token. + /// location provides a location of the expansion point of the token. void CreateString(const char *Buf, unsigned Len, Token &Tok, SourceLocation SourceLoc = SourceLocation()); @@ -744,6 +753,18 @@ public: return Lexer::getLocForEndOfToken(Loc, Offset, SourceMgr, Features); } + /// \brief Returns true if the given MacroID location points at the first + /// token of the macro expansion. + bool isAtStartOfMacroExpansion(SourceLocation loc) const { + return Lexer::isAtStartOfMacroExpansion(loc, SourceMgr, Features); + } + + /// \brief Returns true if the given MacroID location points at the last + /// token of the macro expansion. + bool isAtEndOfMacroExpansion(SourceLocation loc) const { + return Lexer::isAtEndOfMacroExpansion(loc, SourceMgr, Features); + } + /// DumpToken - Print the token to stderr, used for debugging. /// void DumpToken(const Token &Tok, bool DumpFlags = false) const; @@ -770,6 +791,8 @@ public: void PrintStats(); + size_t getTotalMemory() const; + /// HandleMicrosoftCommentPaste - When the macro expander pastes together a /// comment (/##/) in microsoft mode, this method handles updating the current /// state, returning the token on the next source line. @@ -977,6 +1000,16 @@ private: /// the macro should not be expanded return true, otherwise return false. bool HandleMacroExpandedIdentifier(Token &Tok, MacroInfo *MI); + /// \brief Cache macro expanded tokens for TokenLexers. + // + /// Works like a stack; a TokenLexer adds the macro expanded tokens that is + /// going to lex in the cache and when it finishes the tokens are removed + /// from the end of the cache. + Token *cacheMacroExpandedTokens(TokenLexer *tokLexer, + llvm::ArrayRef<Token> tokens); + void removeCachedMacroExpandedTokensOfLastLexer(); + friend void TokenLexer::ExpandFunctionArguments(); + /// isNextPPTokenLParen - Determine whether the next preprocessor token to be /// lexed is a '('. If so, consume the token and return true, if not, this /// method should have no observable side-effect on the lexed tokens. @@ -986,7 +1019,7 @@ private: /// invoked to read all of the formal arguments specified for the macro /// invocation. This returns null on error. MacroArgs *ReadFunctionLikeMacroArgs(Token &MacroName, MacroInfo *MI, - SourceLocation &InstantiationEnd); + SourceLocation &ExpansionEnd); /// ExpandBuiltinMacro - If an identifier token is read that is to be expanded /// as a builtin macro, handle it and return the next token as 'Tok'. diff --git a/include/clang/Lex/Token.h b/include/clang/Lex/Token.h index edcfcc10d2ee..9cf11d9a64c4 100644 --- a/include/clang/Lex/Token.h +++ b/include/clang/Lex/Token.h @@ -63,9 +63,7 @@ class Token { /// Kind - The actual flavor of token this is. /// - unsigned char Kind; // DON'T make Kind a 'tok::TokenKind'; - // MSVC will treat it as a signed char and - // TokenKinds > 127 won't be handled correctly. + unsigned short Kind; /// Flags - Bits we track about this token, members of the TokenFlags enum. unsigned char Flags; diff --git a/include/clang/Lex/TokenLexer.h b/include/clang/Lex/TokenLexer.h index 6ae00cd58658..45ff8a03442e 100644 --- a/include/clang/Lex/TokenLexer.h +++ b/include/clang/Lex/TokenLexer.h @@ -43,10 +43,13 @@ class TokenLexer { /// Tokens - This is the pointer to an array of tokens that the macro is /// defined to, with arguments expanded for function-like macros. If this is /// a token stream, these are the tokens we are returning. This points into - /// the macro definition we are lexing from, a scratch buffer allocated from - /// the preprocessor's bump pointer allocator, or some other buffer that we - /// may or may not own (depending on OwnsTokens). + /// the macro definition we are lexing from, a cache buffer that is owned by + /// the preprocessor, or some other buffer that we may or may not own + /// (depending on OwnsTokens). + /// Note that if it points into Preprocessor's cache buffer, the Preprocessor + /// may update the pointer as needed. const Token *Tokens; + friend class Preprocessor; /// NumTokens - This is the length of the Tokens array. /// @@ -56,9 +59,20 @@ class TokenLexer { /// unsigned CurToken; - /// InstantiateLocStart/End - The source location range where this macro was - /// instantiated. - SourceLocation InstantiateLocStart, InstantiateLocEnd; + /// ExpandLocStart/End - The source location range where this macro was + /// expanded. + SourceLocation ExpandLocStart, ExpandLocEnd; + + /// \brief Source location pointing at the source location entry chunk that + /// was reserved for the current macro expansion. + SourceLocation MacroExpansionStart; + + /// \brief The offset of the macro expansion in the + /// "source location address space". + unsigned MacroStartSLocOffset; + + /// \brief FileID/offset of the start of the macro definition. + std::pair<FileID, unsigned> MacroDefStartInfo; /// Lexical information about the expansion point of the macro: the identifier /// that the macro expanded from had these properties. @@ -148,9 +162,14 @@ private: /// HandleMicrosoftCommentPaste - In microsoft compatibility mode, /##/ pastes /// together to form a comment that comments out everything in the current /// macro, other active macros, and anything left on the current physical - /// source line of the instantiated buffer. Handle this by returning the + /// source line of the expanded buffer. Handle this by returning the /// first token on the next line. void HandleMicrosoftCommentPaste(Token &Tok); + + /// \brief If \arg loc is a FileID and points inside the current macro + /// definition, returns the appropriate source location pointing at the + /// macro expansion source location entry. + SourceLocation getMacroExpansionLocation(SourceLocation loc) const; }; } // end namespace clang diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index e4cdc27c436a..8f49ddad2cec 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -15,6 +15,7 @@ #define LLVM_CLANG_PARSE_PARSER_H #include "clang/Basic/Specifiers.h" +#include "clang/Basic/DelayedCleanupPool.h" #include "clang/Lex/Preprocessor.h" #include "cla |