diff --git a/.arcconfig b/.arcconfig index 048706ac96ee84b99458c8eba12343be7e22b9ea..b258e7a34c4d63aae671d4f32d7938ce14ef6762 100644 --- a/.arcconfig +++ b/.arcconfig @@ -1,4 +1,4 @@ { - "project_id" : "clang", + "repository.callsign" : "C", "conduit_uri" : "https://reviews.llvm.org/" } diff --git a/CMakeLists.txt b/CMakeLists.txt index 42d580077d878a4c855ac91d9e845238e10d279b..a2fcaec9c394e674bcee9e3fe4d9f32c7b60cbdb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -132,6 +132,9 @@ Please install Python or specify the PYTHON_EXECUTABLE CMake variable.") if(EXISTS ${LLVM_MAIN_SRC_DIR}/utils/lit/lit.py) # Note: path not really used, except for checking if lit was found set(LLVM_LIT ${LLVM_MAIN_SRC_DIR}/utils/lit/lit.py) + if(EXISTS ${LLVM_MAIN_SRC_DIR}/utils/llvm-lit) + add_subdirectory(${LLVM_MAIN_SRC_DIR}/utils/llvm-lit utils/llvm-lit) + endif() if(NOT LLVM_UTILS_PROVIDED) add_subdirectory(${LLVM_MAIN_SRC_DIR}/utils/FileCheck utils/FileCheck) add_subdirectory(${LLVM_MAIN_SRC_DIR}/utils/count utils/count) @@ -232,17 +235,21 @@ if (NOT(CLANG_DEFAULT_RTLIB STREQUAL "" OR "Default runtime library to use (\"libgcc\" or \"compiler-rt\", empty for platform default)" FORCE) endif() +set(CLANG_DEFAULT_OBJCOPY "objcopy" CACHE STRING + "Default objcopy executable to use.") + set(CLANG_DEFAULT_OPENMP_RUNTIME "libomp" CACHE STRING "Default OpenMP runtime used by -fopenmp.") -# OpenMP offloading requires at least sm_30 because we use shuffle instructions -# to generate efficient code for reductions. -set(CLANG_OPENMP_NVPTX_DEFAULT_ARCH "sm_30" CACHE STRING +# OpenMP offloading requires at least sm_35 because we use shuffle instructions +# to generate efficient code for reductions and the atomicMax instruction on +# 64-bit integers in the implementation of conditional lastprivate. +set(CLANG_OPENMP_NVPTX_DEFAULT_ARCH "sm_35" CACHE STRING "Default architecture for OpenMP offloading to Nvidia GPUs.") string(REGEX MATCH "^sm_([0-9]+)$" MATCHED_ARCH "${CLANG_OPENMP_NVPTX_DEFAULT_ARCH}") -if (NOT DEFINED MATCHED_ARCH OR "${CMAKE_MATCH_1}" LESS 30) - message(WARNING "Resetting default architecture for OpenMP offloading to Nvidia GPUs to sm_30") - set(CLANG_OPENMP_NVPTX_DEFAULT_ARCH "sm_30" CACHE STRING +if (NOT DEFINED MATCHED_ARCH OR "${CMAKE_MATCH_1}" LESS 35) + message(WARNING "Resetting default architecture for OpenMP offloading to Nvidia GPUs to sm_35") + set(CLANG_OPENMP_NVPTX_DEFAULT_ARCH "sm_35" CACHE STRING "Default architecture for OpenMP offloading to Nvidia GPUs." FORCE) endif() @@ -429,6 +436,7 @@ add_subdirectory(include) # All targets below may depend on all tablegen'd files. get_property(CLANG_TABLEGEN_TARGETS GLOBAL PROPERTY CLANG_TABLEGEN_TARGETS) add_custom_target(clang-tablegen-targets DEPENDS ${CLANG_TABLEGEN_TARGETS}) +set_target_properties(clang-tablegen-targets PROPERTIES FOLDER "Misc") list(APPEND LLVM_COMMON_DEPENDS clang-tablegen-targets) # Force target to be built as soon as possible. Clang modules builds depend @@ -533,8 +541,8 @@ if (CLANG_ENABLE_BOOTSTRAP) set(NEXT_CLANG_STAGE ${NEXT_CLANG_STAGE}-instrumented) endif() message(STATUS "Setting next clang stage to: ${NEXT_CLANG_STAGE}") - - + + set(STAMP_DIR ${CMAKE_CURRENT_BINARY_DIR}/${NEXT_CLANG_STAGE}-stamps/) set(BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/${NEXT_CLANG_STAGE}-bins/) @@ -596,7 +604,9 @@ if (CLANG_ENABLE_BOOTSTRAP) LLVM_BINUTILS_INCDIR CLANG_REPOSITORY_STRING CMAKE_MAKE_PROGRAM - CMAKE_OSX_ARCHITECTURES) + CMAKE_OSX_ARCHITECTURES + LLVM_ENABLE_PROJECTS + LLVM_ENABLE_RUNTIMES) # We don't need to depend on compiler-rt if we're building instrumented # because the next stage will use the same compiler used to build this stage. @@ -614,7 +624,8 @@ if (CLANG_ENABLE_BOOTSTRAP) set(COMPILER_OPTIONS -DCMAKE_CXX_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/${CXX_COMPILER} -DCMAKE_C_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/${C_COMPILER} - -DCMAKE_ASM_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/${C_COMPILER}) + -DCMAKE_ASM_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/${C_COMPILER} + -DCMAKE_ASM_COMPILER_ID=Clang) if(BOOTSTRAP_LLVM_BUILD_INSTRUMENTED) add_dependencies(clang-bootstrap-deps llvm-profdata) @@ -646,7 +657,7 @@ if (CLANG_ENABLE_BOOTSTRAP) foreach(variableName ${variableNames}) if(variableName MATCHES "^BOOTSTRAP_") string(SUBSTRING ${variableName} 10 -1 varName) - string(REPLACE ";" "\;" value "${${variableName}}") + string(REPLACE ";" "|" value "${${variableName}}") list(APPEND PASSTHROUGH_VARIABLES -D${varName}=${value}) endif() @@ -662,7 +673,7 @@ if (CLANG_ENABLE_BOOTSTRAP) if("${${variableName}}" STREQUAL "") set(value "") else() - string(REPLACE ";" "\;" value ${${variableName}}) + string(REPLACE ";" "|" value "${${variableName}}") endif() list(APPEND PASSTHROUGH_VARIABLES -D${variableName}=${value}) @@ -690,6 +701,7 @@ if (CLANG_ENABLE_BOOTSTRAP) USES_TERMINAL_CONFIGURE 1 USES_TERMINAL_BUILD 1 USES_TERMINAL_INSTALL 1 + LIST_SEPARATOR | ) # exclude really-install from main target diff --git a/CODE_OWNERS.TXT b/CODE_OWNERS.TXT index 0aa156b858e890cb4d95075dfdb1d55b6dd4ca24..2fa9f215b66d159a177474f3945c3d1ca6d98209 100644 --- a/CODE_OWNERS.TXT +++ b/CODE_OWNERS.TXT @@ -25,6 +25,10 @@ N: Eric Christopher E: echristo@gmail.com D: Debug Information, inline assembly +N: Devin Coughlin +E: dcoughlin@apple.com +D: Clang Static Analyzer + N: Doug Gregor E: dgregor@apple.com D: Emeritus owner @@ -41,10 +45,6 @@ N: Anton Korobeynikov E: anton@korobeynikov.info D: Exception handling, Windows codegen, ARM EABI -N: Anna Zaks -E: ganna@apple.com -D: Clang Static Analyzer - N: John McCall E: rjmccall@apple.com D: Clang LLVM IR generation diff --git a/README.txt b/README.txt index 5477b9c8bac03b37f8973bad716d1d205825c083..b5f33bb66dd3763bf503c362e508dd5df788055b 100644 --- a/README.txt +++ b/README.txt @@ -13,10 +13,10 @@ different source-level tools. One example of this is the Clang Static Analyzer. If you're interested in more (including how to build Clang) it is best to read the relevant web sites. Here are some pointers: -Information on Clang: http://clang.llvm.org/ -Building and using Clang: http://clang.llvm.org/get_started.html -Clang Static Analyzer: http://clang-analyzer.llvm.org/ -Information on the LLVM project: http://llvm.org/ +Information on Clang: http://clang.llvm.org/ +Building and using Clang: http://clang.llvm.org/get_started.html +Clang Static Analyzer: http://clang-analyzer.llvm.org/ +Information on the LLVM project: http://llvm.org/ If you have questions or comments about Clang, a great place to discuss them is on the Clang development mailing list: diff --git a/bindings/python/README.txt b/bindings/python/README.txt index 742cf8fbb8fc5c3f3c21aad951facab63919980e..8a0bf99b30e3d7c1531b492024707282239e2321 100644 --- a/bindings/python/README.txt +++ b/bindings/python/README.txt @@ -5,11 +5,12 @@ This directory implements Python bindings for Clang. You may need to alter LD_LIBRARY_PATH so that the Clang library can be -found. The unit tests are designed to be run with 'nosetests'. For example: +found. The unit tests are designed to be run with any standard test +runner. For example: -- $ env PYTHONPATH=$(echo ~/llvm/tools/clang/bindings/python/) \ LD_LIBRARY_PATH=$(llvm-config --libdir) \ - nosetests -v + python -m unittest discover -v tests.cindex.test_index.test_create ... ok ... diff --git a/bindings/python/clang/cindex.py b/bindings/python/clang/cindex.py index 1dc1760e4f8804a675543dea12716e000a463422..b53661a4d0ae90445fe2623a35fd099bc1abd4cd 100644 --- a/bindings/python/clang/cindex.py +++ b/bindings/python/clang/cindex.py @@ -94,6 +94,9 @@ if sys.version_info[0] == 3: return cls(param) if isinstance(param, bytes): return cls(param) + if param is None: + # Support passing null to C functions expecting char arrays + return None raise TypeError("Cannot convert '{}' to '{}'".format(type(param).__name__, cls.__name__)) @staticmethod @@ -1476,6 +1479,12 @@ class Cursor(Structure): """ return conf.lib.clang_CXXMethod_isVirtual(self) + def is_abstract_record(self): + """Returns True if the cursor refers to a C++ record declaration + that has pure virtual member functions. + """ + return conf.lib.clang_CXXRecord_isAbstract(self) + def is_scoped_enum(self): """Returns True if the cursor refers to a scoped enum declaration. """ @@ -3398,6 +3407,10 @@ functionList = [ [Cursor], bool), + ("clang_CXXRecord_isAbstract", + [Cursor], + bool), + ("clang_EnumDecl_isScoped", [Cursor], bool), diff --git a/bindings/python/tests/cindex/test_access_specifiers.py b/bindings/python/tests/cindex/test_access_specifiers.py index cfa04dc86574c33ee1d42eab895e1b426ca4a290..2f6144be082c6033172cb51874371db52602dc2f 100644 --- a/bindings/python/tests/cindex/test_access_specifiers.py +++ b/bindings/python/tests/cindex/test_access_specifiers.py @@ -6,10 +6,14 @@ from clang.cindex import TranslationUnit from .util import get_cursor from .util import get_tu -def test_access_specifiers(): - """Ensure that C++ access specifiers are available on cursors""" +import unittest - tu = get_tu(""" + +class TestAccessSpecifiers(unittest.TestCase): + def test_access_specifiers(self): + """Ensure that C++ access specifiers are available on cursors""" + + tu = get_tu(""" class test_class { public: void public_member_function(); @@ -20,15 +24,14 @@ private: }; """, lang = 'cpp') - test_class = get_cursor(tu, "test_class") - assert test_class.access_specifier == AccessSpecifier.INVALID; - - public = get_cursor(tu.cursor, "public_member_function") - assert public.access_specifier == AccessSpecifier.PUBLIC + test_class = get_cursor(tu, "test_class") + self.assertEqual(test_class.access_specifier, AccessSpecifier.INVALID) - protected = get_cursor(tu.cursor, "protected_member_function") - assert protected.access_specifier == AccessSpecifier.PROTECTED + public = get_cursor(tu.cursor, "public_member_function") + self.assertEqual(public.access_specifier, AccessSpecifier.PUBLIC) - private = get_cursor(tu.cursor, "private_member_function") - assert private.access_specifier == AccessSpecifier.PRIVATE + protected = get_cursor(tu.cursor, "protected_member_function") + self.assertEqual(protected.access_specifier, AccessSpecifier.PROTECTED) + private = get_cursor(tu.cursor, "private_member_function") + self.assertEqual(private.access_specifier, AccessSpecifier.PRIVATE) diff --git a/bindings/python/tests/cindex/test_cdb.py b/bindings/python/tests/cindex/test_cdb.py index 35fe3e108a12e4b749bb4b6810af8208e24924e9..bd6e77329f6923d75338fab306a1b7dd2c9850b8 100644 --- a/bindings/python/tests/cindex/test_cdb.py +++ b/bindings/python/tests/cindex/test_cdb.py @@ -4,114 +4,116 @@ from clang.cindex import CompileCommands from clang.cindex import CompileCommand import os import gc +import unittest + kInputsDir = os.path.join(os.path.dirname(__file__), 'INPUTS') -def test_create_fail(): - """Check we fail loading a database with an assertion""" - path = os.path.dirname(__file__) - try: - cdb = CompilationDatabase.fromDirectory(path) - except CompilationDatabaseError as e: - assert e.cdb_error == CompilationDatabaseError.ERROR_CANNOTLOADDATABASE - else: - assert False -def test_create(): - """Check we can load a compilation database""" - cdb = CompilationDatabase.fromDirectory(kInputsDir) +class TestCDB(unittest.TestCase): + def test_create_fail(self): + """Check we fail loading a database with an assertion""" + path = os.path.dirname(__file__) + with self.assertRaises(CompilationDatabaseError) as cm: + cdb = CompilationDatabase.fromDirectory(path) + e = cm.exception + self.assertEqual(e.cdb_error, + CompilationDatabaseError.ERROR_CANNOTLOADDATABASE) -def test_lookup_fail(): - """Check file lookup failure""" - cdb = CompilationDatabase.fromDirectory(kInputsDir) - assert cdb.getCompileCommands('file_do_not_exist.cpp') == None + def test_create(self): + """Check we can load a compilation database""" + cdb = CompilationDatabase.fromDirectory(kInputsDir) -def test_lookup_succeed(): - """Check we get some results if the file exists in the db""" - cdb = CompilationDatabase.fromDirectory(kInputsDir) - cmds = cdb.getCompileCommands('/home/john.doe/MyProject/project.cpp') - assert len(cmds) != 0 + def test_lookup_fail(self): + """Check file lookup failure""" + cdb = CompilationDatabase.fromDirectory(kInputsDir) + self.assertIsNone(cdb.getCompileCommands('file_do_not_exist.cpp')) -def test_all_compilecommand(): - """Check we get all results from the db""" - cdb = CompilationDatabase.fromDirectory(kInputsDir) - cmds = cdb.getAllCompileCommands() - assert len(cmds) == 3 - expected = [ - { 'wd': '/home/john.doe/MyProject', - 'file': '/home/john.doe/MyProject/project.cpp', - 'line': ['clang++', '-o', 'project.o', '-c', - '/home/john.doe/MyProject/project.cpp']}, - { 'wd': '/home/john.doe/MyProjectA', - 'file': '/home/john.doe/MyProject/project2.cpp', - 'line': ['clang++', '-o', 'project2.o', '-c', - '/home/john.doe/MyProject/project2.cpp']}, - { 'wd': '/home/john.doe/MyProjectB', - 'file': '/home/john.doe/MyProject/project2.cpp', - 'line': ['clang++', '-DFEATURE=1', '-o', 'project2-feature.o', '-c', - '/home/john.doe/MyProject/project2.cpp']}, + def test_lookup_succeed(self): + """Check we get some results if the file exists in the db""" + cdb = CompilationDatabase.fromDirectory(kInputsDir) + cmds = cdb.getCompileCommands('/home/john.doe/MyProject/project.cpp') + self.assertNotEqual(len(cmds), 0) - ] - for i in range(len(cmds)): - assert cmds[i].directory == expected[i]['wd'] - assert cmds[i].filename == expected[i]['file'] - for arg, exp in zip(cmds[i].arguments, expected[i]['line']): - assert arg == exp + def test_all_compilecommand(self): + """Check we get all results from the db""" + cdb = CompilationDatabase.fromDirectory(kInputsDir) + cmds = cdb.getAllCompileCommands() + self.assertEqual(len(cmds), 3) + expected = [ + { 'wd': '/home/john.doe/MyProject', + 'file': '/home/john.doe/MyProject/project.cpp', + 'line': ['clang++', '-o', 'project.o', '-c', + '/home/john.doe/MyProject/project.cpp']}, + { 'wd': '/home/john.doe/MyProjectA', + 'file': '/home/john.doe/MyProject/project2.cpp', + 'line': ['clang++', '-o', 'project2.o', '-c', + '/home/john.doe/MyProject/project2.cpp']}, + { 'wd': '/home/john.doe/MyProjectB', + 'file': '/home/john.doe/MyProject/project2.cpp', + 'line': ['clang++', '-DFEATURE=1', '-o', 'project2-feature.o', '-c', + '/home/john.doe/MyProject/project2.cpp']}, -def test_1_compilecommand(): - """Check file with single compile command""" - cdb = CompilationDatabase.fromDirectory(kInputsDir) - file = '/home/john.doe/MyProject/project.cpp' - cmds = cdb.getCompileCommands(file) - assert len(cmds) == 1 - assert cmds[0].directory == os.path.dirname(file) - assert cmds[0].filename == file - expected = [ 'clang++', '-o', 'project.o', '-c', - '/home/john.doe/MyProject/project.cpp'] - for arg, exp in zip(cmds[0].arguments, expected): - assert arg == exp + ] + for i in range(len(cmds)): + self.assertEqual(cmds[i].directory, expected[i]['wd']) + self.assertEqual(cmds[i].filename, expected[i]['file']) + for arg, exp in zip(cmds[i].arguments, expected[i]['line']): + self.assertEqual(arg, exp) -def test_2_compilecommand(): - """Check file with 2 compile commands""" - cdb = CompilationDatabase.fromDirectory(kInputsDir) - cmds = cdb.getCompileCommands('/home/john.doe/MyProject/project2.cpp') - assert len(cmds) == 2 - expected = [ - { 'wd': '/home/john.doe/MyProjectA', - 'line': ['clang++', '-o', 'project2.o', '-c', - '/home/john.doe/MyProject/project2.cpp']}, - { 'wd': '/home/john.doe/MyProjectB', - 'line': ['clang++', '-DFEATURE=1', '-o', 'project2-feature.o', '-c', - '/home/john.doe/MyProject/project2.cpp']} - ] - for i in range(len(cmds)): - assert cmds[i].directory == expected[i]['wd'] - for arg, exp in zip(cmds[i].arguments, expected[i]['line']): - assert arg == exp + def test_1_compilecommand(self): + """Check file with single compile command""" + cdb = CompilationDatabase.fromDirectory(kInputsDir) + file = '/home/john.doe/MyProject/project.cpp' + cmds = cdb.getCompileCommands(file) + self.assertEqual(len(cmds), 1) + self.assertEqual(cmds[0].directory, os.path.dirname(file)) + self.assertEqual(cmds[0].filename, file) + expected = [ 'clang++', '-o', 'project.o', '-c', + '/home/john.doe/MyProject/project.cpp'] + for arg, exp in zip(cmds[0].arguments, expected): + self.assertEqual(arg, exp) -def test_compilecommand_iterator_stops(): - """Check that iterator stops after the correct number of elements""" - cdb = CompilationDatabase.fromDirectory(kInputsDir) - count = 0 - for cmd in cdb.getCompileCommands('/home/john.doe/MyProject/project2.cpp'): - count += 1 - assert count <= 2 + def test_2_compilecommand(self): + """Check file with 2 compile commands""" + cdb = CompilationDatabase.fromDirectory(kInputsDir) + cmds = cdb.getCompileCommands('/home/john.doe/MyProject/project2.cpp') + self.assertEqual(len(cmds), 2) + expected = [ + { 'wd': '/home/john.doe/MyProjectA', + 'line': ['clang++', '-o', 'project2.o', '-c', + '/home/john.doe/MyProject/project2.cpp']}, + { 'wd': '/home/john.doe/MyProjectB', + 'line': ['clang++', '-DFEATURE=1', '-o', 'project2-feature.o', '-c', + '/home/john.doe/MyProject/project2.cpp']} + ] + for i in range(len(cmds)): + self.assertEqual(cmds[i].directory, expected[i]['wd']) + for arg, exp in zip(cmds[i].arguments, expected[i]['line']): + self.assertEqual(arg, exp) -def test_compilationDB_references(): - """Ensure CompilationsCommands are independent of the database""" - cdb = CompilationDatabase.fromDirectory(kInputsDir) - cmds = cdb.getCompileCommands('/home/john.doe/MyProject/project.cpp') - del cdb - gc.collect() - workingdir = cmds[0].directory + def test_compilecommand_iterator_stops(self): + """Check that iterator stops after the correct number of elements""" + cdb = CompilationDatabase.fromDirectory(kInputsDir) + count = 0 + for cmd in cdb.getCompileCommands('/home/john.doe/MyProject/project2.cpp'): + count += 1 + self.assertLessEqual(count, 2) -def test_compilationCommands_references(): - """Ensure CompilationsCommand keeps a reference to CompilationCommands""" - cdb = CompilationDatabase.fromDirectory(kInputsDir) - cmds = cdb.getCompileCommands('/home/john.doe/MyProject/project.cpp') - del cdb - cmd0 = cmds[0] - del cmds - gc.collect() - workingdir = cmd0.directory + def test_compilationDB_references(self): + """Ensure CompilationsCommands are independent of the database""" + cdb = CompilationDatabase.fromDirectory(kInputsDir) + cmds = cdb.getCompileCommands('/home/john.doe/MyProject/project.cpp') + del cdb + gc.collect() + workingdir = cmds[0].directory + def test_compilationCommands_references(self): + """Ensure CompilationsCommand keeps a reference to CompilationCommands""" + cdb = CompilationDatabase.fromDirectory(kInputsDir) + cmds = cdb.getCompileCommands('/home/john.doe/MyProject/project.cpp') + del cdb + cmd0 = cmds[0] + del cmds + gc.collect() + workingdir = cmd0.directory diff --git a/bindings/python/tests/cindex/test_code_completion.py b/bindings/python/tests/cindex/test_code_completion.py index 357d50db5131401883bd604757d882b598783016..a56bb304cd711a9d7f012eef587df745789a22ab 100644 --- a/bindings/python/tests/cindex/test_code_completion.py +++ b/bindings/python/tests/cindex/test_code_completion.py @@ -1,16 +1,20 @@ from clang.cindex import TranslationUnit -def check_completion_results(cr, expected): - assert cr is not None - assert len(cr.diagnostics) == 0 +import unittest - completions = [str(c) for c in cr.results] - for c in expected: - assert c in completions +class TestCodeCompletion(unittest.TestCase): + def check_completion_results(self, cr, expected): + self.assertIsNotNone(cr) + self.assertEqual(len(cr.diagnostics), 0) -def test_code_complete(): - files = [('fake.c', """ + completions = [str(c) for c in cr.results] + + for c in expected: + self.assertIn(c, completions) + + def test_code_complete(self): + files = [('fake.c', """ /// Aaa. int test1; @@ -22,20 +26,20 @@ void f() { } """)] - tu = TranslationUnit.from_source('fake.c', ['-std=c99'], unsaved_files=files, - options=TranslationUnit.PARSE_INCLUDE_BRIEF_COMMENTS_IN_CODE_COMPLETION) + tu = TranslationUnit.from_source('fake.c', ['-std=c99'], unsaved_files=files, + options=TranslationUnit.PARSE_INCLUDE_BRIEF_COMMENTS_IN_CODE_COMPLETION) - cr = tu.codeComplete('fake.c', 9, 1, unsaved_files=files, include_brief_comments=True) + cr = tu.codeComplete('fake.c', 9, 1, unsaved_files=files, include_brief_comments=True) - expected = [ - "{'int', ResultType} | {'test1', TypedText} || Priority: 50 || Availability: Available || Brief comment: Aaa.", - "{'void', ResultType} | {'test2', TypedText} | {'(', LeftParen} | {')', RightParen} || Priority: 50 || Availability: Available || Brief comment: Bbb.", - "{'return', TypedText} || Priority: 40 || Availability: Available || Brief comment: None" - ] - check_completion_results(cr, expected) + expected = [ + "{'int', ResultType} | {'test1', TypedText} || Priority: 50 || Availability: Available || Brief comment: Aaa.", + "{'void', ResultType} | {'test2', TypedText} | {'(', LeftParen} | {')', RightParen} || Priority: 50 || Availability: Available || Brief comment: Bbb.", + "{'return', TypedText} || Priority: 40 || Availability: Available || Brief comment: None" + ] + self.check_completion_results(cr, expected) -def test_code_complete_availability(): - files = [('fake.cpp', """ + def test_code_complete_availability(self): + files = [('fake.cpp', """ class P { protected: int member; @@ -52,24 +56,24 @@ void f(P x, Q y) { } """)] - tu = TranslationUnit.from_source('fake.cpp', ['-std=c++98'], unsaved_files=files) - - cr = tu.codeComplete('fake.cpp', 12, 5, unsaved_files=files) - - expected = [ - "{'const', TypedText} || Priority: 40 || Availability: Available || Brief comment: None", - "{'volatile', TypedText} || Priority: 40 || Availability: Available || Brief comment: None", - "{'operator', TypedText} || Priority: 40 || Availability: Available || Brief comment: None", - "{'P', TypedText} | {'::', Text} || Priority: 75 || Availability: Available || Brief comment: None", - "{'Q', TypedText} | {'::', Text} || Priority: 75 || Availability: Available || Brief comment: None" - ] - check_completion_results(cr, expected) - - cr = tu.codeComplete('fake.cpp', 13, 5, unsaved_files=files) - expected = [ - "{'P', TypedText} | {'::', Text} || Priority: 75 || Availability: Available || Brief comment: None", - "{'P &', ResultType} | {'operator=', TypedText} | {'(', LeftParen} | {'const P &', Placeholder} | {')', RightParen} || Priority: 34 || Availability: Available || Brief comment: None", - "{'int', ResultType} | {'member', TypedText} || Priority: 35 || Availability: NotAccessible || Brief comment: None", - "{'void', ResultType} | {'~P', TypedText} | {'(', LeftParen} | {')', RightParen} || Priority: 34 || Availability: Available || Brief comment: None" - ] - check_completion_results(cr, expected) + tu = TranslationUnit.from_source('fake.cpp', ['-std=c++98'], unsaved_files=files) + + cr = tu.codeComplete('fake.cpp', 12, 5, unsaved_files=files) + + expected = [ + "{'const', TypedText} || Priority: 40 || Availability: Available || Brief comment: None", + "{'volatile', TypedText} || Priority: 40 || Availability: Available || Brief comment: None", + "{'operator', TypedText} || Priority: 40 || Availability: Available || Brief comment: None", + "{'P', TypedText} | {'::', Text} || Priority: 75 || Availability: Available || Brief comment: None", + "{'Q', TypedText} | {'::', Text} || Priority: 75 || Availability: Available || Brief comment: None" + ] + self.check_completion_results(cr, expected) + + cr = tu.codeComplete('fake.cpp', 13, 5, unsaved_files=files) + expected = [ + "{'P', TypedText} | {'::', Text} || Priority: 75 || Availability: Available || Brief comment: None", + "{'P &', ResultType} | {'operator=', TypedText} | {'(', LeftParen} | {'const P &', Placeholder} | {')', RightParen} || Priority: 79 || Availability: Available || Brief comment: None", + "{'int', ResultType} | {'member', TypedText} || Priority: 35 || Availability: NotAccessible || Brief comment: None", + "{'void', ResultType} | {'~P', TypedText} | {'(', LeftParen} | {')', RightParen} || Priority: 79 || Availability: Available || Brief comment: None" + ] + self.check_completion_results(cr, expected) diff --git a/bindings/python/tests/cindex/test_comment.py b/bindings/python/tests/cindex/test_comment.py index d8f3129ac51e7f5643327d177424ac5d821fbf7c..d6c6d8e5c5b009fb270ac19ce622f78339bf97cf 100644 --- a/bindings/python/tests/cindex/test_comment.py +++ b/bindings/python/tests/cindex/test_comment.py @@ -1,8 +1,12 @@ from clang.cindex import TranslationUnit from tests.cindex.util import get_cursor -def test_comment(): - files = [('fake.c', """ +import unittest + + +class TestComment(unittest.TestCase): + def test_comment(self): + files = [('fake.c', """ /// Aaa. int test1; @@ -14,27 +18,25 @@ void f() { } """)] - # make a comment-aware TU - tu = TranslationUnit.from_source('fake.c', ['-std=c99'], unsaved_files=files, - options=TranslationUnit.PARSE_INCLUDE_BRIEF_COMMENTS_IN_CODE_COMPLETION) - test1 = get_cursor(tu, 'test1') - assert test1 is not None, "Could not find test1." - assert test1.type.is_pod() - raw = test1.raw_comment - brief = test1.brief_comment - assert raw == """/// Aaa.""" - assert brief == """Aaa.""" - - test2 = get_cursor(tu, 'test2') - raw = test2.raw_comment - brief = test2.brief_comment - assert raw == """/// Bbb.\n/// x""" - assert brief == """Bbb. x""" - - f = get_cursor(tu, 'f') - raw = f.raw_comment - brief = f.brief_comment - assert raw is None - assert brief is None + # make a comment-aware TU + tu = TranslationUnit.from_source('fake.c', ['-std=c99'], unsaved_files=files, + options=TranslationUnit.PARSE_INCLUDE_BRIEF_COMMENTS_IN_CODE_COMPLETION) + test1 = get_cursor(tu, 'test1') + self.assertIsNotNone(test1, "Could not find test1.") + self.assertTrue(test1.type.is_pod()) + raw = test1.raw_comment + brief = test1.brief_comment + self.assertEqual(raw, """/// Aaa.""") + self.assertEqual(brief, """Aaa.""") + test2 = get_cursor(tu, 'test2') + raw = test2.raw_comment + brief = test2.brief_comment + self.assertEqual(raw, """/// Bbb.\n/// x""") + self.assertEqual(brief, """Bbb. x""") + f = get_cursor(tu, 'f') + raw = f.raw_comment + brief = f.brief_comment + self.assertIsNone(raw) + self.assertIsNone(brief) diff --git a/bindings/python/tests/cindex/test_cursor.py b/bindings/python/tests/cindex/test_cursor.py index 8ff06951546edb483906c8873e0d617c6510adc0..c2a4eb57d02f02e1fa2d686959e1006b4f6e616e 100644 --- a/bindings/python/tests/cindex/test_cursor.py +++ b/bindings/python/tests/cindex/test_cursor.py @@ -1,5 +1,6 @@ import ctypes import gc +import unittest from clang.cindex import AvailabilityKind from clang.cindex import CursorKind @@ -10,6 +11,7 @@ from .util import get_cursor from .util import get_cursors from .util import get_tu + kInput = """\ struct s0 { int a; @@ -30,257 +32,6 @@ void f0(int a0, int a1) { } """ -def test_get_children(): - tu = get_tu(kInput) - - it = tu.cursor.get_children() - tu_nodes = list(it) - - assert len(tu_nodes) == 3 - for cursor in tu_nodes: - assert cursor.translation_unit is not None - - assert tu_nodes[0] != tu_nodes[1] - assert tu_nodes[0].kind == CursorKind.STRUCT_DECL - assert tu_nodes[0].spelling == 's0' - assert tu_nodes[0].is_definition() == True - assert tu_nodes[0].location.file.name == 't.c' - assert tu_nodes[0].location.line == 1 - assert tu_nodes[0].location.column == 8 - assert tu_nodes[0].hash > 0 - assert tu_nodes[0].translation_unit is not None - - s0_nodes = list(tu_nodes[0].get_children()) - assert len(s0_nodes) == 2 - assert s0_nodes[0].kind == CursorKind.FIELD_DECL - assert s0_nodes[0].spelling == 'a' - assert s0_nodes[0].type.kind == TypeKind.INT - assert s0_nodes[1].kind == CursorKind.FIELD_DECL - assert s0_nodes[1].spelling == 'b' - assert s0_nodes[1].type.kind == TypeKind.INT - - assert tu_nodes[1].kind == CursorKind.STRUCT_DECL - assert tu_nodes[1].spelling == 's1' - assert tu_nodes[1].displayname == 's1' - assert tu_nodes[1].is_definition() == False - - assert tu_nodes[2].kind == CursorKind.FUNCTION_DECL - assert tu_nodes[2].spelling == 'f0' - assert tu_nodes[2].displayname == 'f0(int, int)' - assert tu_nodes[2].is_definition() == True - -def test_references(): - """Ensure that references to TranslationUnit are kept.""" - tu = get_tu('int x;') - cursors = list(tu.cursor.get_children()) - assert len(cursors) > 0 - - cursor = cursors[0] - assert isinstance(cursor.translation_unit, TranslationUnit) - - # Delete reference to TU and perform a full GC. - del tu - gc.collect() - assert isinstance(cursor.translation_unit, TranslationUnit) - - # If the TU was destroyed, this should cause a segfault. - parent = cursor.semantic_parent - -def test_canonical(): - source = 'struct X; struct X; struct X { int member; };' - tu = get_tu(source) - - cursors = [] - for cursor in tu.cursor.get_children(): - if cursor.spelling == 'X': - cursors.append(cursor) - - assert len(cursors) == 3 - assert cursors[1].canonical == cursors[2].canonical - -def test_is_const_method(): - """Ensure Cursor.is_const_method works.""" - source = 'class X { void foo() const; void bar(); };' - tu = get_tu(source, lang='cpp') - - cls = get_cursor(tu, 'X') - foo = get_cursor(tu, 'foo') - bar = get_cursor(tu, 'bar') - assert cls is not None - assert foo is not None - assert bar is not None - - assert foo.is_const_method() - assert not bar.is_const_method() - -def test_is_converting_constructor(): - """Ensure Cursor.is_converting_constructor works.""" - source = 'class X { explicit X(int); X(double); X(); };' - tu = get_tu(source, lang='cpp') - - xs = get_cursors(tu, 'X') - - assert len(xs) == 4 - assert xs[0].kind == CursorKind.CLASS_DECL - cs = xs[1:] - assert cs[0].kind == CursorKind.CONSTRUCTOR - assert cs[1].kind == CursorKind.CONSTRUCTOR - assert cs[2].kind == CursorKind.CONSTRUCTOR - - assert not cs[0].is_converting_constructor() - assert cs[1].is_converting_constructor() - assert not cs[2].is_converting_constructor() - - -def test_is_copy_constructor(): - """Ensure Cursor.is_copy_constructor works.""" - source = 'class X { X(); X(const X&); X(X&&); };' - tu = get_tu(source, lang='cpp') - - xs = get_cursors(tu, 'X') - assert xs[0].kind == CursorKind.CLASS_DECL - cs = xs[1:] - assert cs[0].kind == CursorKind.CONSTRUCTOR - assert cs[1].kind == CursorKind.CONSTRUCTOR - assert cs[2].kind == CursorKind.CONSTRUCTOR - - assert not cs[0].is_copy_constructor() - assert cs[1].is_copy_constructor() - assert not cs[2].is_copy_constructor() - -def test_is_default_constructor(): - """Ensure Cursor.is_default_constructor works.""" - source = 'class X { X(); X(int); };' - tu = get_tu(source, lang='cpp') - - xs = get_cursors(tu, 'X') - assert xs[0].kind == CursorKind.CLASS_DECL - cs = xs[1:] - assert cs[0].kind == CursorKind.CONSTRUCTOR - assert cs[1].kind == CursorKind.CONSTRUCTOR - - assert cs[0].is_default_constructor() - assert not cs[1].is_default_constructor() - -def test_is_move_constructor(): - """Ensure Cursor.is_move_constructor works.""" - source = 'class X { X(); X(const X&); X(X&&); };' - tu = get_tu(source, lang='cpp') - - xs = get_cursors(tu, 'X') - assert xs[0].kind == CursorKind.CLASS_DECL - cs = xs[1:] - assert cs[0].kind == CursorKind.CONSTRUCTOR - assert cs[1].kind == CursorKind.CONSTRUCTOR - assert cs[2].kind == CursorKind.CONSTRUCTOR - - assert not cs[0].is_move_constructor() - assert not cs[1].is_move_constructor() - assert cs[2].is_move_constructor() - -def test_is_default_method(): - """Ensure Cursor.is_default_method works.""" - source = 'class X { X() = default; }; class Y { Y(); };' - tu = get_tu(source, lang='cpp') - - xs = get_cursors(tu, 'X') - ys = get_cursors(tu, 'Y') - - assert len(xs) == 2 - assert len(ys) == 2 - - xc = xs[1] - yc = ys[1] - - assert xc.is_default_method() - assert not yc.is_default_method() - -def test_is_mutable_field(): - """Ensure Cursor.is_mutable_field works.""" - source = 'class X { int x_; mutable int y_; };' - tu = get_tu(source, lang='cpp') - - cls = get_cursor(tu, 'X') - x_ = get_cursor(tu, 'x_') - y_ = get_cursor(tu, 'y_') - assert cls is not None - assert x_ is not None - assert y_ is not None - - assert not x_.is_mutable_field() - assert y_.is_mutable_field() - -def test_is_static_method(): - """Ensure Cursor.is_static_method works.""" - - source = 'class X { static void foo(); void bar(); };' - tu = get_tu(source, lang='cpp') - - cls = get_cursor(tu, 'X') - foo = get_cursor(tu, 'foo') - bar = get_cursor(tu, 'bar') - assert cls is not None - assert foo is not None - assert bar is not None - - assert foo.is_static_method() - assert not bar.is_static_method() - -def test_is_pure_virtual_method(): - """Ensure Cursor.is_pure_virtual_method works.""" - source = 'class X { virtual void foo() = 0; virtual void bar(); };' - tu = get_tu(source, lang='cpp') - - cls = get_cursor(tu, 'X') - foo = get_cursor(tu, 'foo') - bar = get_cursor(tu, 'bar') - assert cls is not None - assert foo is not None - assert bar is not None - - assert foo.is_pure_virtual_method() - assert not bar.is_pure_virtual_method() - -def test_is_virtual_method(): - """Ensure Cursor.is_virtual_method works.""" - source = 'class X { virtual void foo(); void bar(); };' - tu = get_tu(source, lang='cpp') - - cls = get_cursor(tu, 'X') - foo = get_cursor(tu, 'foo') - bar = get_cursor(tu, 'bar') - assert cls is not None - assert foo is not None - assert bar is not None - - assert foo.is_virtual_method() - assert not bar.is_virtual_method() - -def test_is_scoped_enum(): - """Ensure Cursor.is_scoped_enum works.""" - source = 'class X {}; enum RegularEnum {}; enum class ScopedEnum {};' - tu = get_tu(source, lang='cpp') - - cls = get_cursor(tu, 'X') - regular_enum = get_cursor(tu, 'RegularEnum') - scoped_enum = get_cursor(tu, 'ScopedEnum') - assert cls is not None - assert regular_enum is not None - assert scoped_enum is not None - - assert not cls.is_scoped_enum() - assert not regular_enum.is_scoped_enum() - assert scoped_enum.is_scoped_enum() - -def test_underlying_type(): - tu = get_tu('typedef int foo;') - typedef = get_cursor(tu, 'foo') - assert typedef is not None - - assert typedef.kind.is_declaration() - underlying = typedef.underlying_typedef_type - assert underlying.kind == TypeKind.INT - kParentTest = """\ class C { void f(); @@ -288,250 +39,514 @@ kParentTest = """\ void C::f() { } """ -def test_semantic_parent(): - tu = get_tu(kParentTest, 'cpp') - curs = get_cursors(tu, 'f') - decl = get_cursor(tu, 'C') - assert(len(curs) == 2) - assert(curs[0].semantic_parent == curs[1].semantic_parent) - assert(curs[0].semantic_parent == decl) - -def test_lexical_parent(): - tu = get_tu(kParentTest, 'cpp') - curs = get_cursors(tu, 'f') - decl = get_cursor(tu, 'C') - assert(len(curs) == 2) - assert(curs[0].lexical_parent != curs[1].lexical_parent) - assert(curs[0].lexical_parent == decl) - assert(curs[1].lexical_parent == tu.cursor) - -def test_enum_type(): - tu = get_tu('enum TEST { FOO=1, BAR=2 };') - enum = get_cursor(tu, 'TEST') - assert enum is not None - - assert enum.kind == CursorKind.ENUM_DECL - enum_type = enum.enum_type - assert enum_type.kind == TypeKind.UINT - -def test_enum_type_cpp(): - tu = get_tu('enum TEST : long long { FOO=1, BAR=2 };', lang="cpp") - enum = get_cursor(tu, 'TEST') - assert enum is not None - - assert enum.kind == CursorKind.ENUM_DECL - assert enum.enum_type.kind == TypeKind.LONGLONG - -def test_objc_type_encoding(): - tu = get_tu('int i;', lang='objc') - i = get_cursor(tu, 'i') - - assert i is not None - assert i.objc_type_encoding == 'i' - -def test_enum_values(): - tu = get_tu('enum TEST { SPAM=1, EGG, HAM = EGG * 20};') - enum = get_cursor(tu, 'TEST') - assert enum is not None - - assert enum.kind == CursorKind.ENUM_DECL - - enum_constants = list(enum.get_children()) - assert len(enum_constants) == 3 - - spam, egg, ham = enum_constants - - assert spam.kind == CursorKind.ENUM_CONSTANT_DECL - assert spam.enum_value == 1 - assert egg.kind == CursorKind.ENUM_CONSTANT_DECL - assert egg.enum_value == 2 - assert ham.kind == CursorKind.ENUM_CONSTANT_DECL - assert ham.enum_value == 40 - -def test_enum_values_cpp(): - tu = get_tu('enum TEST : long long { SPAM = -1, HAM = 0x10000000000};', lang="cpp") - enum = get_cursor(tu, 'TEST') - assert enum is not None - - assert enum.kind == CursorKind.ENUM_DECL - - enum_constants = list(enum.get_children()) - assert len(enum_constants) == 2 - - spam, ham = enum_constants - - assert spam.kind == CursorKind.ENUM_CONSTANT_DECL - assert spam.enum_value == -1 - assert ham.kind == CursorKind.ENUM_CONSTANT_DECL - assert ham.enum_value == 0x10000000000 - -def test_annotation_attribute(): - tu = get_tu('int foo (void) __attribute__ ((annotate("here be annotation attribute")));') - - foo = get_cursor(tu, 'foo') - assert foo is not None - - for c in foo.get_children(): - if c.kind == CursorKind.ANNOTATE_ATTR: - assert c.displayname == "here be annotation attribute" - break - else: - assert False, "Couldn't find annotation" - -def test_annotation_template(): - annotation = '__attribute__ ((annotate("annotation")))' - for source, kind in [ - ('int foo (T value) %s;', CursorKind.FUNCTION_TEMPLATE), - ('class %s foo {};', CursorKind.CLASS_TEMPLATE), - ]: - source = 'template ' + (source % annotation) - tu = get_tu(source, lang="cpp") +kTemplateArgTest = """\ + template + void foo(); + + template<> + void foo<-7, float, true>(); + """ + +class TestCursor(unittest.TestCase): + def test_get_children(self): + tu = get_tu(kInput) + + it = tu.cursor.get_children() + tu_nodes = list(it) + + self.assertEqual(len(tu_nodes), 3) + for cursor in tu_nodes: + self.assertIsNotNone(cursor.translation_unit) + + self.assertNotEqual(tu_nodes[0], tu_nodes[1]) + self.assertEqual(tu_nodes[0].kind, CursorKind.STRUCT_DECL) + self.assertEqual(tu_nodes[0].spelling, 's0') + self.assertEqual(tu_nodes[0].is_definition(), True) + self.assertEqual(tu_nodes[0].location.file.name, 't.c') + self.assertEqual(tu_nodes[0].location.line, 1) + self.assertEqual(tu_nodes[0].location.column, 8) + self.assertGreater(tu_nodes[0].hash, 0) + self.assertIsNotNone(tu_nodes[0].translation_unit) + + s0_nodes = list(tu_nodes[0].get_children()) + self.assertEqual(len(s0_nodes), 2) + self.assertEqual(s0_nodes[0].kind, CursorKind.FIELD_DECL) + self.assertEqual(s0_nodes[0].spelling, 'a') + self.assertEqual(s0_nodes[0].type.kind, TypeKind.INT) + self.assertEqual(s0_nodes[1].kind, CursorKind.FIELD_DECL) + self.assertEqual(s0_nodes[1].spelling, 'b') + self.assertEqual(s0_nodes[1].type.kind, TypeKind.INT) + + self.assertEqual(tu_nodes[1].kind, CursorKind.STRUCT_DECL) + self.assertEqual(tu_nodes[1].spelling, 's1') + self.assertEqual(tu_nodes[1].displayname, 's1') + self.assertEqual(tu_nodes[1].is_definition(), False) + + self.assertEqual(tu_nodes[2].kind, CursorKind.FUNCTION_DECL) + self.assertEqual(tu_nodes[2].spelling, 'f0') + self.assertEqual(tu_nodes[2].displayname, 'f0(int, int)') + self.assertEqual(tu_nodes[2].is_definition(), True) + + def test_references(self): + """Ensure that references to TranslationUnit are kept.""" + tu = get_tu('int x;') + cursors = list(tu.cursor.get_children()) + self.assertGreater(len(cursors), 0) + + cursor = cursors[0] + self.assertIsInstance(cursor.translation_unit, TranslationUnit) + + # Delete reference to TU and perform a full GC. + del tu + gc.collect() + self.assertIsInstance(cursor.translation_unit, TranslationUnit) + + # If the TU was destroyed, this should cause a segfault. + parent = cursor.semantic_parent + + def test_canonical(self): + source = 'struct X; struct X; struct X { int member; };' + tu = get_tu(source) + + cursors = [] + for cursor in tu.cursor.get_children(): + if cursor.spelling == 'X': + cursors.append(cursor) + + self.assertEqual(len(cursors), 3) + self.assertEqual(cursors[1].canonical, cursors[2].canonical) + + def test_is_const_method(self): + """Ensure Cursor.is_const_method works.""" + source = 'class X { void foo() const; void bar(); };' + tu = get_tu(source, lang='cpp') + + cls = get_cursor(tu, 'X') foo = get_cursor(tu, 'foo') - assert foo is not None - assert foo.kind == kind + bar = get_cursor(tu, 'bar') + self.assertIsNotNone(cls) + self.assertIsNotNone(foo) + self.assertIsNotNone(bar) + + self.assertTrue(foo.is_const_method()) + self.assertFalse(bar.is_const_method()) + + def test_is_converting_constructor(self): + """Ensure Cursor.is_converting_constructor works.""" + source = 'class X { explicit X(int); X(double); X(); };' + tu = get_tu(source, lang='cpp') + + xs = get_cursors(tu, 'X') + + self.assertEqual(len(xs), 4) + self.assertEqual(xs[0].kind, CursorKind.CLASS_DECL) + cs = xs[1:] + self.assertEqual(cs[0].kind, CursorKind.CONSTRUCTOR) + self.assertEqual(cs[1].kind, CursorKind.CONSTRUCTOR) + self.assertEqual(cs[2].kind, CursorKind.CONSTRUCTOR) + + self.assertFalse(cs[0].is_converting_constructor()) + self.assertTrue(cs[1].is_converting_constructor()) + self.assertFalse(cs[2].is_converting_constructor()) + + + def test_is_copy_constructor(self): + """Ensure Cursor.is_copy_constructor works.""" + source = 'class X { X(); X(const X&); X(X&&); };' + tu = get_tu(source, lang='cpp') + + xs = get_cursors(tu, 'X') + self.assertEqual(xs[0].kind, CursorKind.CLASS_DECL) + cs = xs[1:] + self.assertEqual(cs[0].kind, CursorKind.CONSTRUCTOR) + self.assertEqual(cs[1].kind, CursorKind.CONSTRUCTOR) + self.assertEqual(cs[2].kind, CursorKind.CONSTRUCTOR) + + self.assertFalse(cs[0].is_copy_constructor()) + self.assertTrue(cs[1].is_copy_constructor()) + self.assertFalse(cs[2].is_copy_constructor()) + + def test_is_default_constructor(self): + """Ensure Cursor.is_default_constructor works.""" + source = 'class X { X(); X(int); };' + tu = get_tu(source, lang='cpp') + + xs = get_cursors(tu, 'X') + self.assertEqual(xs[0].kind, CursorKind.CLASS_DECL) + cs = xs[1:] + self.assertEqual(cs[0].kind, CursorKind.CONSTRUCTOR) + self.assertEqual(cs[1].kind, CursorKind.CONSTRUCTOR) + + self.assertTrue(cs[0].is_default_constructor()) + self.assertFalse(cs[1].is_default_constructor()) + + def test_is_move_constructor(self): + """Ensure Cursor.is_move_constructor works.""" + source = 'class X { X(); X(const X&); X(X&&); };' + tu = get_tu(source, lang='cpp') + + xs = get_cursors(tu, 'X') + self.assertEqual(xs[0].kind, CursorKind.CLASS_DECL) + cs = xs[1:] + self.assertEqual(cs[0].kind, CursorKind.CONSTRUCTOR) + self.assertEqual(cs[1].kind, CursorKind.CONSTRUCTOR) + self.assertEqual(cs[2].kind, CursorKind.CONSTRUCTOR) + + self.assertFalse(cs[0].is_move_constructor()) + self.assertFalse(cs[1].is_move_constructor()) + self.assertTrue(cs[2].is_move_constructor()) + + def test_is_default_method(self): + """Ensure Cursor.is_default_method works.""" + source = 'class X { X() = default; }; class Y { Y(); };' + tu = get_tu(source, lang='cpp') + + xs = get_cursors(tu, 'X') + ys = get_cursors(tu, 'Y') + + self.assertEqual(len(xs), 2) + self.assertEqual(len(ys), 2) + + xc = xs[1] + yc = ys[1] + + self.assertTrue(xc.is_default_method()) + self.assertFalse(yc.is_default_method()) + + def test_is_mutable_field(self): + """Ensure Cursor.is_mutable_field works.""" + source = 'class X { int x_; mutable int y_; };' + tu = get_tu(source, lang='cpp') + + cls = get_cursor(tu, 'X') + x_ = get_cursor(tu, 'x_') + y_ = get_cursor(tu, 'y_') + self.assertIsNotNone(cls) + self.assertIsNotNone(x_) + self.assertIsNotNone(y_) + + self.assertFalse(x_.is_mutable_field()) + self.assertTrue(y_.is_mutable_field()) + + def test_is_static_method(self): + """Ensure Cursor.is_static_method works.""" + + source = 'class X { static void foo(); void bar(); };' + tu = get_tu(source, lang='cpp') + + cls = get_cursor(tu, 'X') + foo = get_cursor(tu, 'foo') + bar = get_cursor(tu, 'bar') + self.assertIsNotNone(cls) + self.assertIsNotNone(foo) + self.assertIsNotNone(bar) + + self.assertTrue(foo.is_static_method()) + self.assertFalse(bar.is_static_method()) + + def test_is_pure_virtual_method(self): + """Ensure Cursor.is_pure_virtual_method works.""" + source = 'class X { virtual void foo() = 0; virtual void bar(); };' + tu = get_tu(source, lang='cpp') + + cls = get_cursor(tu, 'X') + foo = get_cursor(tu, 'foo') + bar = get_cursor(tu, 'bar') + self.assertIsNotNone(cls) + self.assertIsNotNone(foo) + self.assertIsNotNone(bar) + + self.assertTrue(foo.is_pure_virtual_method()) + self.assertFalse(bar.is_pure_virtual_method()) + + def test_is_virtual_method(self): + """Ensure Cursor.is_virtual_method works.""" + source = 'class X { virtual void foo(); void bar(); };' + tu = get_tu(source, lang='cpp') + + cls = get_cursor(tu, 'X') + foo = get_cursor(tu, 'foo') + bar = get_cursor(tu, 'bar') + self.assertIsNotNone(cls) + self.assertIsNotNone(foo) + self.assertIsNotNone(bar) + + self.assertTrue(foo.is_virtual_method()) + self.assertFalse(bar.is_virtual_method()) + + def test_is_abstract_record(self): + """Ensure Cursor.is_abstract_record works.""" + source = 'struct X { virtual void x() = 0; }; struct Y : X { void x(); };' + tu = get_tu(source, lang='cpp') + + cls = get_cursor(tu, 'X') + self.assertTrue(cls.is_abstract_record()) + + cls = get_cursor(tu, 'Y') + self.assertFalse(cls.is_abstract_record()) + + def test_is_scoped_enum(self): + """Ensure Cursor.is_scoped_enum works.""" + source = 'class X {}; enum RegularEnum {}; enum class ScopedEnum {};' + tu = get_tu(source, lang='cpp') + + cls = get_cursor(tu, 'X') + regular_enum = get_cursor(tu, 'RegularEnum') + scoped_enum = get_cursor(tu, 'ScopedEnum') + self.assertIsNotNone(cls) + self.assertIsNotNone(regular_enum) + self.assertIsNotNone(scoped_enum) + + self.assertFalse(cls.is_scoped_enum()) + self.assertFalse(regular_enum.is_scoped_enum()) + self.assertTrue(scoped_enum.is_scoped_enum()) + + def test_underlying_type(self): + tu = get_tu('typedef int foo;') + typedef = get_cursor(tu, 'foo') + self.assertIsNotNone(typedef) + + self.assertTrue(typedef.kind.is_declaration()) + underlying = typedef.underlying_typedef_type + self.assertEqual(underlying.kind, TypeKind.INT) + + def test_semantic_parent(self): + tu = get_tu(kParentTest, 'cpp') + curs = get_cursors(tu, 'f') + decl = get_cursor(tu, 'C') + self.assertEqual(len(curs), 2) + self.assertEqual(curs[0].semantic_parent, curs[1].semantic_parent) + self.assertEqual(curs[0].semantic_parent, decl) + + def test_lexical_parent(self): + tu = get_tu(kParentTest, 'cpp') + curs = get_cursors(tu, 'f') + decl = get_cursor(tu, 'C') + self.assertEqual(len(curs), 2) + self.assertNotEqual(curs[0].lexical_parent, curs[1].lexical_parent) + self.assertEqual(curs[0].lexical_parent, decl) + self.assertEqual(curs[1].lexical_parent, tu.cursor) + + def test_enum_type(self): + tu = get_tu('enum TEST { FOO=1, BAR=2 };') + enum = get_cursor(tu, 'TEST') + self.assertIsNotNone(enum) + + self.assertEqual(enum.kind, CursorKind.ENUM_DECL) + enum_type = enum.enum_type + self.assertEqual(enum_type.kind, TypeKind.UINT) + + def test_enum_type_cpp(self): + tu = get_tu('enum TEST : long long { FOO=1, BAR=2 };', lang="cpp") + enum = get_cursor(tu, 'TEST') + self.assertIsNotNone(enum) + + self.assertEqual(enum.kind, CursorKind.ENUM_DECL) + self.assertEqual(enum.enum_type.kind, TypeKind.LONGLONG) + + def test_objc_type_encoding(self): + tu = get_tu('int i;', lang='objc') + i = get_cursor(tu, 'i') + + self.assertIsNotNone(i) + self.assertEqual(i.objc_type_encoding, 'i') + + def test_enum_values(self): + tu = get_tu('enum TEST { SPAM=1, EGG, HAM = EGG * 20};') + enum = get_cursor(tu, 'TEST') + self.assertIsNotNone(enum) + + self.assertEqual(enum.kind, CursorKind.ENUM_DECL) + + enum_constants = list(enum.get_children()) + self.assertEqual(len(enum_constants), 3) + + spam, egg, ham = enum_constants + + self.assertEqual(spam.kind, CursorKind.ENUM_CONSTANT_DECL) + self.assertEqual(spam.enum_value, 1) + self.assertEqual(egg.kind, CursorKind.ENUM_CONSTANT_DECL) + self.assertEqual(egg.enum_value, 2) + self.assertEqual(ham.kind, CursorKind.ENUM_CONSTANT_DECL) + self.assertEqual(ham.enum_value, 40) + + def test_enum_values_cpp(self): + tu = get_tu('enum TEST : long long { SPAM = -1, HAM = 0x10000000000};', lang="cpp") + enum = get_cursor(tu, 'TEST') + self.assertIsNotNone(enum) + + self.assertEqual(enum.kind, CursorKind.ENUM_DECL) + + enum_constants = list(enum.get_children()) + self.assertEqual(len(enum_constants), 2) + + spam, ham = enum_constants + + self.assertEqual(spam.kind, CursorKind.ENUM_CONSTANT_DECL) + self.assertEqual(spam.enum_value, -1) + self.assertEqual(ham.kind, CursorKind.ENUM_CONSTANT_DECL) + self.assertEqual(ham.enum_value, 0x10000000000) + + def test_annotation_attribute(self): + tu = get_tu('int foo (void) __attribute__ ((annotate("here be annotation attribute")));') + + foo = get_cursor(tu, 'foo') + self.assertIsNotNone(foo) for c in foo.get_children(): if c.kind == CursorKind.ANNOTATE_ATTR: - assert c.displayname == "annotation" + self.assertEqual(c.displayname, "here be annotation attribute") break else: - assert False, "Couldn't find annotation for {}".format(kind) - -def test_result_type(): - tu = get_tu('int foo();') - foo = get_cursor(tu, 'foo') - - assert foo is not None - t = foo.result_type - assert t.kind == TypeKind.INT - -def test_availability(): - tu = get_tu('class A { A(A const&) = delete; };', lang='cpp') - - # AvailabilityKind.AVAILABLE - cursor = get_cursor(tu, 'A') - assert cursor.kind == CursorKind.CLASS_DECL - assert cursor.availability == AvailabilityKind.AVAILABLE - - # AvailabilityKind.NOT_AVAILABLE - cursors = get_cursors(tu, 'A') - for c in cursors: - if c.kind == CursorKind.CONSTRUCTOR: - assert c.availability == AvailabilityKind.NOT_AVAILABLE - break - else: - assert False, "Could not find cursor for deleted constructor" - - # AvailabilityKind.DEPRECATED - tu = get_tu('void test() __attribute__((deprecated));', lang='cpp') - cursor = get_cursor(tu, 'test') - assert cursor.availability == AvailabilityKind.DEPRECATED - - # AvailabilityKind.NOT_ACCESSIBLE is only used in the code completion results - -def test_get_tokens(): - """Ensure we can map cursors back to tokens.""" - tu = get_tu('int foo(int i);') - foo = get_cursor(tu, 'foo') - - tokens = list(foo.get_tokens()) - assert len(tokens) == 6 - assert tokens[0].spelling == 'int' - assert tokens[1].spelling == 'foo' - -def test_get_token_cursor(): - """Ensure we can map tokens to cursors.""" - tu = get_tu('class A {}; int foo(A var = A());', lang='cpp') - foo = get_cursor(tu, 'foo') - - for cursor in foo.walk_preorder(): - if cursor.kind.is_expression() and not cursor.kind.is_statement(): - break - else: - assert False, "Could not find default value expression" - - tokens = list(cursor.get_tokens()) - assert len(tokens) == 4, [t.spelling for t in tokens] - assert tokens[0].spelling == '=' - assert tokens[1].spelling == 'A' - assert tokens[2].spelling == '(' - assert tokens[3].spelling == ')' - t_cursor = tokens[1].cursor - assert t_cursor.kind == CursorKind.TYPE_REF - r_cursor = t_cursor.referenced # should not raise an exception - assert r_cursor.kind == CursorKind.CLASS_DECL - -def test_get_arguments(): - tu = get_tu('void foo(int i, int j);') - foo = get_cursor(tu, 'foo') - arguments = list(foo.get_arguments()) - - assert len(arguments) == 2 - assert arguments[0].spelling == "i" - assert arguments[1].spelling == "j" + self.fail("Couldn't find annotation") + + def test_annotation_template(self): + annotation = '__attribute__ ((annotate("annotation")))' + for source, kind in [ + ('int foo (T value) %s;', CursorKind.FUNCTION_TEMPLATE), + ('class %s foo {};', CursorKind.CLASS_TEMPLATE), + ]: + source = 'template ' + (source % annotation) + tu = get_tu(source, lang="cpp") + + foo = get_cursor(tu, 'foo') + self.assertIsNotNone(foo) + self.assertEqual(foo.kind, kind) + + for c in foo.get_children(): + if c.kind == CursorKind.ANNOTATE_ATTR: + self.assertEqual(c.displayname, "annotation") + break + else: + self.fail("Couldn't find annotation for {}".format(kind)) + + def test_result_type(self): + tu = get_tu('int foo();') + foo = get_cursor(tu, 'foo') -kTemplateArgTest = """\ - template - void foo(); + self.assertIsNotNone(foo) + t = foo.result_type + self.assertEqual(t.kind, TypeKind.INT) - template<> - void foo<-7, float, true>(); - """ + def test_availability(self): + tu = get_tu('class A { A(A const&) = delete; };', lang='cpp') -def test_get_num_template_arguments(): - tu = get_tu(kTemplateArgTest, lang='cpp') - foos = get_cursors(tu, 'foo') + # AvailabilityKind.AVAILABLE + cursor = get_cursor(tu, 'A') + self.assertEqual(cursor.kind, CursorKind.CLASS_DECL) + self.assertEqual(cursor.availability, AvailabilityKind.AVAILABLE) + + # AvailabilityKind.NOT_AVAILABLE + cursors = get_cursors(tu, 'A') + for c in cursors: + if c.kind == CursorKind.CONSTRUCTOR: + self.assertEqual(c.availability, AvailabilityKind.NOT_AVAILABLE) + break + else: + self.fail("Could not find cursor for deleted constructor") - assert foos[1].get_num_template_arguments() == 3 + # AvailabilityKind.DEPRECATED + tu = get_tu('void test() __attribute__((deprecated));', lang='cpp') + cursor = get_cursor(tu, 'test') + self.assertEqual(cursor.availability, AvailabilityKind.DEPRECATED) -def test_get_template_argument_kind(): - tu = get_tu(kTemplateArgTest, lang='cpp') - foos = get_cursors(tu, 'foo') + # AvailabilityKind.NOT_ACCESSIBLE is only used in the code completion results - assert foos[1].get_template_argument_kind(0) == TemplateArgumentKind.INTEGRAL - assert foos[1].get_template_argument_kind(1) == TemplateArgumentKind.TYPE - assert foos[1].get_template_argument_kind(2) == TemplateArgumentKind.INTEGRAL + def test_get_tokens(self): + """Ensure we can map cursors back to tokens.""" + tu = get_tu('int foo(int i);') + foo = get_cursor(tu, 'foo') -def test_get_template_argument_type(): - tu = get_tu(kTemplateArgTest, lang='cpp') - foos = get_cursors(tu, 'foo') + tokens = list(foo.get_tokens()) + self.assertEqual(len(tokens), 6) + self.assertEqual(tokens[0].spelling, 'int') + self.assertEqual(tokens[1].spelling, 'foo') - assert foos[1].get_template_argument_type(1).kind == TypeKind.FLOAT + def test_get_token_cursor(self): + """Ensure we can map tokens to cursors.""" + tu = get_tu('class A {}; int foo(A var = A());', lang='cpp') + foo = get_cursor(tu, 'foo') -def test_get_template_argument_value(): - tu = get_tu(kTemplateArgTest, lang='cpp') - foos = get_cursors(tu, 'foo') + for cursor in foo.walk_preorder(): + if cursor.kind.is_expression() and not cursor.kind.is_statement(): + break + else: + self.fail("Could not find default value expression") + + tokens = list(cursor.get_tokens()) + self.assertEqual(len(tokens), 4, [t.spelling for t in tokens]) + self.assertEqual(tokens[0].spelling, '=') + self.assertEqual(tokens[1].spelling, 'A') + self.assertEqual(tokens[2].spelling, '(') + self.assertEqual(tokens[3].spelling, ')') + t_cursor = tokens[1].cursor + self.assertEqual(t_cursor.kind, CursorKind.TYPE_REF) + r_cursor = t_cursor.referenced # should not raise an exception + self.assertEqual(r_cursor.kind, CursorKind.CLASS_DECL) + + def test_get_arguments(self): + tu = get_tu('void foo(int i, int j);') + foo = get_cursor(tu, 'foo') + arguments = list(foo.get_arguments()) - assert foos[1].get_template_argument_value(0) == -7 - assert foos[1].get_template_argument_value(2) == True + self.assertEqual(len(arguments), 2) + self.assertEqual(arguments[0].spelling, "i") + self.assertEqual(arguments[1].spelling, "j") -def test_get_template_argument_unsigned_value(): - tu = get_tu(kTemplateArgTest, lang='cpp') - foos = get_cursors(tu, 'foo') + def test_get_num_template_arguments(self): + tu = get_tu(kTemplateArgTest, lang='cpp') + foos = get_cursors(tu, 'foo') - assert foos[1].get_template_argument_unsigned_value(0) == 2 ** 32 - 7 - assert foos[1].get_template_argument_unsigned_value(2) == True + self.assertEqual(foos[1].get_num_template_arguments(), 3) -def test_referenced(): - tu = get_tu('void foo(); void bar() { foo(); }') - foo = get_cursor(tu, 'foo') - bar = get_cursor(tu, 'bar') - for c in bar.get_children(): - if c.kind == CursorKind.CALL_EXPR: - assert c.referenced.spelling == foo.spelling - break + def test_get_template_argument_kind(self): + tu = get_tu(kTemplateArgTest, lang='cpp') + foos = get_cursors(tu, 'foo') -def test_mangled_name(): - kInputForMangling = """\ - int foo(int, int); - """ - tu = get_tu(kInputForMangling, lang='cpp') - foo = get_cursor(tu, 'foo') - - # Since libclang does not link in targets, we cannot pass a triple to it - # and force the target. To enable this test to pass on all platforms, accept - # all valid manglings. - # [c-index-test handles this by running the source through clang, emitting - # an AST file and running libclang on that AST file] - assert foo.mangled_name in ('_Z3fooii', '__Z3fooii', '?foo@@YAHHH') + self.assertEqual(foos[1].get_template_argument_kind(0), TemplateArgumentKind.INTEGRAL) + self.assertEqual(foos[1].get_template_argument_kind(1), TemplateArgumentKind.TYPE) + self.assertEqual(foos[1].get_template_argument_kind(2), TemplateArgumentKind.INTEGRAL) + + def test_get_template_argument_type(self): + tu = get_tu(kTemplateArgTest, lang='cpp') + foos = get_cursors(tu, 'foo') + + self.assertEqual(foos[1].get_template_argument_type(1).kind, TypeKind.FLOAT) + + def test_get_template_argument_value(self): + tu = get_tu(kTemplateArgTest, lang='cpp') + foos = get_cursors(tu, 'foo') + + self.assertEqual(foos[1].get_template_argument_value(0), -7) + self.assertEqual(foos[1].get_template_argument_value(2), True) + + def test_get_template_argument_unsigned_value(self): + tu = get_tu(kTemplateArgTest, lang='cpp') + foos = get_cursors(tu, 'foo') + + self.assertEqual(foos[1].get_template_argument_unsigned_value(0), 2 ** 32 - 7) + self.assertEqual(foos[1].get_template_argument_unsigned_value(2), True) + + def test_referenced(self): + tu = get_tu('void foo(); void bar() { foo(); }') + foo = get_cursor(tu, 'foo') + bar = get_cursor(tu, 'bar') + for c in bar.get_children(): + if c.kind == CursorKind.CALL_EXPR: + self.assertEqual(c.referenced.spelling, foo.spelling) + break + + def test_mangled_name(self): + kInputForMangling = """\ + int foo(int, int); + """ + tu = get_tu(kInputForMangling, lang='cpp') + foo = get_cursor(tu, 'foo') + + # Since libclang does not link in targets, we cannot pass a triple to it + # and force the target. To enable this test to pass on all platforms, accept + # all valid manglings. + # [c-index-test handles this by running the source through clang, emitting + # an AST file and running libclang on that AST file] + self.assertIn(foo.mangled_name, ('_Z3fooii', '__Z3fooii', '?foo@@YAHHH')) diff --git a/bindings/python/tests/cindex/test_cursor_kind.py b/bindings/python/tests/cindex/test_cursor_kind.py index 4d8d88b92131e1f9c7bba861c9239c593ee995e0..f1ee753ef8b102079585fb869ceee7283f55c718 100644 --- a/bindings/python/tests/cindex/test_cursor_kind.py +++ b/bindings/python/tests/cindex/test_cursor_kind.py @@ -1,49 +1,53 @@ from clang.cindex import CursorKind -def test_name(): - assert CursorKind.UNEXPOSED_DECL.name is 'UNEXPOSED_DECL' - -def test_get_all_kinds(): - kinds = CursorKind.get_all_kinds() - assert CursorKind.UNEXPOSED_DECL in kinds - assert CursorKind.TRANSLATION_UNIT in kinds - assert CursorKind.VARIABLE_REF in kinds - assert CursorKind.LAMBDA_EXPR in kinds - assert CursorKind.OBJ_BOOL_LITERAL_EXPR in kinds - assert CursorKind.OBJ_SELF_EXPR in kinds - assert CursorKind.MS_ASM_STMT in kinds - assert CursorKind.MODULE_IMPORT_DECL in kinds - assert CursorKind.TYPE_ALIAS_TEMPLATE_DECL in kinds - -def test_kind_groups(): - """Check that every kind classifies to exactly one group.""" - - assert CursorKind.UNEXPOSED_DECL.is_declaration() - assert CursorKind.TYPE_REF.is_reference() - assert CursorKind.DECL_REF_EXPR.is_expression() - assert CursorKind.UNEXPOSED_STMT.is_statement() - assert CursorKind.INVALID_FILE.is_invalid() - - assert CursorKind.TRANSLATION_UNIT.is_translation_unit() - assert not CursorKind.TYPE_REF.is_translation_unit() - - assert CursorKind.PREPROCESSING_DIRECTIVE.is_preprocessing() - assert not CursorKind.TYPE_REF.is_preprocessing() - - assert CursorKind.UNEXPOSED_DECL.is_unexposed() - assert not CursorKind.TYPE_REF.is_unexposed() - - for k in CursorKind.get_all_kinds(): - group = [n for n in ('is_declaration', 'is_reference', 'is_expression', - 'is_statement', 'is_invalid', 'is_attribute') - if getattr(k, n)()] - - if k in ( CursorKind.TRANSLATION_UNIT, - CursorKind.MACRO_DEFINITION, - CursorKind.MACRO_INSTANTIATION, - CursorKind.INCLUSION_DIRECTIVE, - CursorKind.PREPROCESSING_DIRECTIVE, - CursorKind.OVERLOAD_CANDIDATE): - assert len(group) == 0 - else: - assert len(group) == 1 +import unittest + + +class TestCursorKind(unittest.TestCase): + def test_name(self): + self.assertTrue(CursorKind.UNEXPOSED_DECL.name is 'UNEXPOSED_DECL') + + def test_get_all_kinds(self): + kinds = CursorKind.get_all_kinds() + self.assertIn(CursorKind.UNEXPOSED_DECL, kinds) + self.assertIn(CursorKind.TRANSLATION_UNIT, kinds) + self.assertIn(CursorKind.VARIABLE_REF, kinds) + self.assertIn(CursorKind.LAMBDA_EXPR, kinds) + self.assertIn(CursorKind.OBJ_BOOL_LITERAL_EXPR, kinds) + self.assertIn(CursorKind.OBJ_SELF_EXPR, kinds) + self.assertIn(CursorKind.MS_ASM_STMT, kinds) + self.assertIn(CursorKind.MODULE_IMPORT_DECL, kinds) + self.assertIn(CursorKind.TYPE_ALIAS_TEMPLATE_DECL, kinds) + + def test_kind_groups(self): + """Check that every kind classifies to exactly one group.""" + + self.assertTrue(CursorKind.UNEXPOSED_DECL.is_declaration()) + self.assertTrue(CursorKind.TYPE_REF.is_reference()) + self.assertTrue(CursorKind.DECL_REF_EXPR.is_expression()) + self.assertTrue(CursorKind.UNEXPOSED_STMT.is_statement()) + self.assertTrue(CursorKind.INVALID_FILE.is_invalid()) + + self.assertTrue(CursorKind.TRANSLATION_UNIT.is_translation_unit()) + self.assertFalse(CursorKind.TYPE_REF.is_translation_unit()) + + self.assertTrue(CursorKind.PREPROCESSING_DIRECTIVE.is_preprocessing()) + self.assertFalse(CursorKind.TYPE_REF.is_preprocessing()) + + self.assertTrue(CursorKind.UNEXPOSED_DECL.is_unexposed()) + self.assertFalse(CursorKind.TYPE_REF.is_unexposed()) + + for k in CursorKind.get_all_kinds(): + group = [n for n in ('is_declaration', 'is_reference', 'is_expression', + 'is_statement', 'is_invalid', 'is_attribute') + if getattr(k, n)()] + + if k in ( CursorKind.TRANSLATION_UNIT, + CursorKind.MACRO_DEFINITION, + CursorKind.MACRO_INSTANTIATION, + CursorKind.INCLUSION_DIRECTIVE, + CursorKind.PREPROCESSING_DIRECTIVE, + CursorKind.OVERLOAD_CANDIDATE): + self.assertEqual(len(group), 0) + else: + self.assertEqual(len(group), 1) diff --git a/bindings/python/tests/cindex/test_diagnostics.py b/bindings/python/tests/cindex/test_diagnostics.py index 23cbe89f658190ddee90e0dc68cec382ae1e1384..78b327daa72cd836bf29aed38737c28fbcc899f5 100644 --- a/bindings/python/tests/cindex/test_diagnostics.py +++ b/bindings/python/tests/cindex/test_diagnostics.py @@ -1,102 +1,105 @@ from clang.cindex import * from .util import get_tu +import unittest + + # FIXME: We need support for invalid translation units to test better. -def test_diagnostic_warning(): - tu = get_tu('int f0() {}\n') - assert len(tu.diagnostics) == 1 - assert tu.diagnostics[0].severity == Diagnostic.Warning - assert tu.diagnostics[0].location.line == 1 - assert tu.diagnostics[0].location.column == 11 - assert (tu.diagnostics[0].spelling == - 'control reaches end of non-void function') - -def test_diagnostic_note(): - # FIXME: We aren't getting notes here for some reason. - tu = get_tu('#define A x\nvoid *A = 1;\n') - assert len(tu.diagnostics) == 1 - assert tu.diagnostics[0].severity == Diagnostic.Warning - assert tu.diagnostics[0].location.line == 2 - assert tu.diagnostics[0].location.column == 7 - assert 'incompatible' in tu.diagnostics[0].spelling -# assert tu.diagnostics[1].severity == Diagnostic.Note -# assert tu.diagnostics[1].location.line == 1 -# assert tu.diagnostics[1].location.column == 11 -# assert tu.diagnostics[1].spelling == 'instantiated from' - -def test_diagnostic_fixit(): - tu = get_tu('struct { int f0; } x = { f0 : 1 };') - assert len(tu.diagnostics) == 1 - assert tu.diagnostics[0].severity == Diagnostic.Warning - assert tu.diagnostics[0].location.line == 1 - assert tu.diagnostics[0].location.column == 26 - assert tu.diagnostics[0].spelling.startswith('use of GNU old-style') - assert len(tu.diagnostics[0].fixits) == 1 - assert tu.diagnostics[0].fixits[0].range.start.line == 1 - assert tu.diagnostics[0].fixits[0].range.start.column == 26 - assert tu.diagnostics[0].fixits[0].range.end.line == 1 - assert tu.diagnostics[0].fixits[0].range.end.column == 30 - assert tu.diagnostics[0].fixits[0].value == '.f0 = ' - -def test_diagnostic_range(): - tu = get_tu('void f() { int i = "a" + 1; }') - assert len(tu.diagnostics) == 1 - assert tu.diagnostics[0].severity == Diagnostic.Warning - assert tu.diagnostics[0].location.line == 1 - assert tu.diagnostics[0].location.column == 16 - assert tu.diagnostics[0].spelling.startswith('incompatible pointer to') - assert len(tu.diagnostics[0].fixits) == 0 - assert len(tu.diagnostics[0].ranges) == 1 - assert tu.diagnostics[0].ranges[0].start.line == 1 - assert tu.diagnostics[0].ranges[0].start.column == 20 - assert tu.diagnostics[0].ranges[0].end.line == 1 - assert tu.diagnostics[0].ranges[0].end.column == 27 - try: - tu.diagnostics[0].ranges[1].start.line - except IndexError: - assert True - else: - assert False - -def test_diagnostic_category(): - """Ensure that category properties work.""" - tu = get_tu('int f(int i) { return 7; }', all_warnings=True) - assert len(tu.diagnostics) == 1 - d = tu.diagnostics[0] - - assert d.severity == Diagnostic.Warning - assert d.location.line == 1 - assert d.location.column == 11 - - assert d.category_number == 2 - assert d.category_name == 'Semantic Issue' - -def test_diagnostic_option(): - """Ensure that category option properties work.""" - tu = get_tu('int f(int i) { return 7; }', all_warnings=True) - assert len(tu.diagnostics) == 1 - d = tu.diagnostics[0] - - assert d.option == '-Wunused-parameter' - assert d.disable_option == '-Wno-unused-parameter' - -def test_diagnostic_children(): - tu = get_tu('void f(int x) {} void g() { f(); }') - assert len(tu.diagnostics) == 1 - d = tu.diagnostics[0] - - children = d.children - assert len(children) == 1 - assert children[0].severity == Diagnostic.Note - assert children[0].spelling.endswith('declared here') - assert children[0].location.line == 1 - assert children[0].location.column == 1 - -def test_diagnostic_string_repr(): - tu = get_tu('struct MissingSemicolon{}') - assert len(tu.diagnostics) == 1 - d = tu.diagnostics[0] - - assert repr(d) == ', spelling "expected \';\' after struct">' - + +class TestDiagnostics(unittest.TestCase): + def test_diagnostic_warning(self): + tu = get_tu('int f0() {}\n') + self.assertEqual(len(tu.diagnostics), 1) + self.assertEqual(tu.diagnostics[0].severity, Diagnostic.Warning) + self.assertEqual(tu.diagnostics[0].location.line, 1) + self.assertEqual(tu.diagnostics[0].location.column, 11) + self.assertEqual(tu.diagnostics[0].spelling, + 'control reaches end of non-void function') + + def test_diagnostic_note(self): + # FIXME: We aren't getting notes here for some reason. + tu = get_tu('#define A x\nvoid *A = 1;\n') + self.assertEqual(len(tu.diagnostics), 1) + self.assertEqual(tu.diagnostics[0].severity, Diagnostic.Warning) + self.assertEqual(tu.diagnostics[0].location.line, 2) + self.assertEqual(tu.diagnostics[0].location.column, 7) + self.assertIn('incompatible', tu.diagnostics[0].spelling) +# self.assertEqual(tu.diagnostics[1].severity, Diagnostic.Note) +# self.assertEqual(tu.diagnostics[1].location.line, 1) +# self.assertEqual(tu.diagnostics[1].location.column, 11) +# self.assertEqual(tu.diagnostics[1].spelling, 'instantiated from') + + def test_diagnostic_fixit(self): + tu = get_tu('struct { int f0; } x = { f0 : 1 };') + self.assertEqual(len(tu.diagnostics), 1) + self.assertEqual(tu.diagnostics[0].severity, Diagnostic.Warning) + self.assertEqual(tu.diagnostics[0].location.line, 1) + self.assertEqual(tu.diagnostics[0].location.column, 26) + self.assertRegexpMatches(tu.diagnostics[0].spelling, + 'use of GNU old-style.*') + self.assertEqual(len(tu.diagnostics[0].fixits), 1) + self.assertEqual(tu.diagnostics[0].fixits[0].range.start.line, 1) + self.assertEqual(tu.diagnostics[0].fixits[0].range.start.column, 26) + self.assertEqual(tu.diagnostics[0].fixits[0].range.end.line, 1) + self.assertEqual(tu.diagnostics[0].fixits[0].range.end.column, 30) + self.assertEqual(tu.diagnostics[0].fixits[0].value, '.f0 = ') + + def test_diagnostic_range(self): + tu = get_tu('void f() { int i = "a" + 1; }') + self.assertEqual(len(tu.diagnostics), 1) + self.assertEqual(tu.diagnostics[0].severity, Diagnostic.Warning) + self.assertEqual(tu.diagnostics[0].location.line, 1) + self.assertEqual(tu.diagnostics[0].location.column, 16) + self.assertRegexpMatches(tu.diagnostics[0].spelling, + 'incompatible pointer to.*') + self.assertEqual(len(tu.diagnostics[0].fixits), 0) + self.assertEqual(len(tu.diagnostics[0].ranges), 1) + self.assertEqual(tu.diagnostics[0].ranges[0].start.line, 1) + self.assertEqual(tu.diagnostics[0].ranges[0].start.column, 20) + self.assertEqual(tu.diagnostics[0].ranges[0].end.line, 1) + self.assertEqual(tu.diagnostics[0].ranges[0].end.column, 27) + with self.assertRaises(IndexError): + tu.diagnostics[0].ranges[1].start.line + + def test_diagnostic_category(self): + """Ensure that category properties work.""" + tu = get_tu('int f(int i) { return 7; }', all_warnings=True) + self.assertEqual(len(tu.diagnostics), 1) + d = tu.diagnostics[0] + + self.assertEqual(d.severity, Diagnostic.Warning) + self.assertEqual(d.location.line, 1) + self.assertEqual(d.location.column, 11) + + self.assertEqual(d.category_number, 2) + self.assertEqual(d.category_name, 'Semantic Issue') + + def test_diagnostic_option(self): + """Ensure that category option properties work.""" + tu = get_tu('int f(int i) { return 7; }', all_warnings=True) + self.assertEqual(len(tu.diagnostics), 1) + d = tu.diagnostics[0] + + self.assertEqual(d.option, '-Wunused-parameter') + self.assertEqual(d.disable_option, '-Wno-unused-parameter') + + def test_diagnostic_children(self): + tu = get_tu('void f(int x) {} void g() { f(); }') + self.assertEqual(len(tu.diagnostics), 1) + d = tu.diagnostics[0] + + children = d.children + self.assertEqual(len(children), 1) + self.assertEqual(children[0].severity, Diagnostic.Note) + self.assertRegexpMatches(children[0].spelling, + '.*declared here') + self.assertEqual(children[0].location.line, 1) + self.assertEqual(children[0].location.column, 1) + + def test_diagnostic_string_repr(self): + tu = get_tu('struct MissingSemicolon{}') + self.assertEqual(len(tu.diagnostics), 1) + d = tu.diagnostics[0] + + self.assertEqual(repr(d), ', spelling "expected \';\' after struct">') diff --git a/bindings/python/tests/cindex/test_exception_specification_kind.py b/bindings/python/tests/cindex/test_exception_specification_kind.py index 543d47f7db974ccdbfce2f1ef3976bea13202c41..80b3639a8ab35518ea144b25c35a16a8eb3237d9 100644 --- a/bindings/python/tests/cindex/test_exception_specification_kind.py +++ b/bindings/python/tests/cindex/test_exception_specification_kind.py @@ -2,6 +2,8 @@ import clang.cindex from clang.cindex import ExceptionSpecificationKind from .util import get_tu +import unittest + def find_function_declarations(node, declarations=[]): if node.kind == clang.cindex.CursorKind.FUNCTION_DECL: @@ -11,17 +13,18 @@ def find_function_declarations(node, declarations=[]): return declarations -def test_exception_specification_kind(): - source = """int square1(int x); - int square2(int x) noexcept; - int square3(int x) noexcept(noexcept(x * x));""" +class TestExceptionSpecificationKind(unittest.TestCase): + def test_exception_specification_kind(self): + source = """int square1(int x); + int square2(int x) noexcept; + int square3(int x) noexcept(noexcept(x * x));""" - tu = get_tu(source, lang='cpp', flags=['-std=c++14']) + tu = get_tu(source, lang='cpp', flags=['-std=c++14']) - declarations = find_function_declarations(tu.cursor) - expected = [ - ('square1', ExceptionSpecificationKind.NONE), - ('square2', ExceptionSpecificationKind.BASIC_NOEXCEPT), - ('square3', ExceptionSpecificationKind.COMPUTED_NOEXCEPT) - ] - assert declarations == expected + declarations = find_function_declarations(tu.cursor) + expected = [ + ('square1', ExceptionSpecificationKind.NONE), + ('square2', ExceptionSpecificationKind.BASIC_NOEXCEPT), + ('square3', ExceptionSpecificationKind.COMPUTED_NOEXCEPT) + ] + self.assertListEqual(declarations, expected) diff --git a/bindings/python/tests/cindex/test_file.py b/bindings/python/tests/cindex/test_file.py index 146e8c570528702222bd828f3ac3fe48ce079f13..98f6575262cc6c63b02a20cfc6c5fcfc13a8787d 100644 --- a/bindings/python/tests/cindex/test_file.py +++ b/bindings/python/tests/cindex/test_file.py @@ -1,9 +1,13 @@ from clang.cindex import Index, File -def test_file(): - index = Index.create() - tu = index.parse('t.c', unsaved_files = [('t.c', "")]) - file = File.from_name(tu, "t.c") - assert str(file) == "t.c" - assert file.name == "t.c" - assert repr(file) == "" +import unittest + + +class TestFile(unittest.TestCase): + def test_file(self): + index = Index.create() + tu = index.parse('t.c', unsaved_files = [('t.c', "")]) + file = File.from_name(tu, "t.c") + self.assertEqual(str(file), "t.c") + self.assertEqual(file.name, "t.c") + self.assertEqual(repr(file), "") diff --git a/bindings/python/tests/cindex/test_index.py b/bindings/python/tests/cindex/test_index.py index dc173f04d21877c4ba9ee3c178f82ec26f29f1de..cfdf98e628ac8b56c927ffcca4e07664af402986 100644 --- a/bindings/python/tests/cindex/test_index.py +++ b/bindings/python/tests/cindex/test_index.py @@ -1,15 +1,21 @@ from clang.cindex import * import os +import unittest + kInputsDir = os.path.join(os.path.dirname(__file__), 'INPUTS') -def test_create(): - index = Index.create() -# FIXME: test Index.read +class TestIndex(unittest.TestCase): + def test_create(self): + index = Index.create() + + # FIXME: test Index.read -def test_parse(): - index = Index.create() - assert isinstance(index, Index) - tu = index.parse(os.path.join(kInputsDir, 'hello.cpp')) - assert isinstance(tu, TranslationUnit) + def test_parse(self): + index = Index.create() + self.assertIsInstance(index, Index) + tu = index.parse(os.path.join(kInputsDir, 'hello.cpp')) + self.assertIsInstance(tu, TranslationUnit) + tu = index.parse(None, ['-c', os.path.join(kInputsDir, 'hello.cpp')]) + self.assertIsInstance(tu, TranslationUnit) diff --git a/bindings/python/tests/cindex/test_linkage.py b/bindings/python/tests/cindex/test_linkage.py index 2f056d51402e1e2c8a2806c3949bf2a97dd6e4ec..6b482f8081b3a8266d0f50ee9e5fb3ec0cd1f250 100644 --- a/bindings/python/tests/cindex/test_linkage.py +++ b/bindings/python/tests/cindex/test_linkage.py @@ -1,4 +1,3 @@ - from clang.cindex import LinkageKind from clang.cindex import Cursor from clang.cindex import TranslationUnit @@ -6,25 +5,29 @@ from clang.cindex import TranslationUnit from .util import get_cursor from .util import get_tu -def test_linkage(): - """Ensure that linkage specifers are available on cursors""" +import unittest + - tu = get_tu(""" +class TestLinkage(unittest.TestCase): + def test_linkage(self): + """Ensure that linkage specifers are available on cursors""" + + tu = get_tu(""" void foo() { int no_linkage; } static int internal; -namespace { extern int unique_external; } +namespace { struct unique_external_type {} } +unique_external_type unique_external; extern int external; """, lang = 'cpp') - no_linkage = get_cursor(tu.cursor, 'no_linkage') - assert no_linkage.linkage == LinkageKind.NO_LINKAGE; - - internal = get_cursor(tu.cursor, 'internal') - assert internal.linkage == LinkageKind.INTERNAL + no_linkage = get_cursor(tu.cursor, 'no_linkage') + self.assertEqual(no_linkage.linkage, LinkageKind.NO_LINKAGE) - unique_external = get_cursor(tu.cursor, 'unique_external') - assert unique_external.linkage == LinkageKind.UNIQUE_EXTERNAL + internal = get_cursor(tu.cursor, 'internal') + self.assertEqual(internal.linkage, LinkageKind.INTERNAL) - external = get_cursor(tu.cursor, 'external') - assert external.linkage == LinkageKind.EXTERNAL + unique_external = get_cursor(tu.cursor, 'unique_external') + self.assertEqual(unique_external.linkage, LinkageKind.UNIQUE_EXTERNAL) + external = get_cursor(tu.cursor, 'external') + self.assertEqual(external.linkage, LinkageKind.EXTERNAL) diff --git a/bindings/python/tests/cindex/test_location.py b/bindings/python/tests/cindex/test_location.py index 9e9ef487af18e03f73c8e1de0403cf906e14f2d6..cbc32deb4bd5902c6b98cc7eda539ecbc43b809f 100644 --- a/bindings/python/tests/cindex/test_location.py +++ b/bindings/python/tests/cindex/test_location.py @@ -5,91 +5,96 @@ from clang.cindex import SourceRange from .util import get_cursor from .util import get_tu +import unittest + + baseInput="int one;\nint two;\n" -def assert_location(loc, line, column, offset): - assert loc.line == line - assert loc.column == column - assert loc.offset == offset -def test_location(): - tu = get_tu(baseInput) - one = get_cursor(tu, 'one') - two = get_cursor(tu, 'two') +class TestLocation(unittest.TestCase): + def assert_location(self, loc, line, column, offset): + self.assertEqual(loc.line, line) + self.assertEqual(loc.column, column) + self.assertEqual(loc.offset, offset) + + def test_location(self): + tu = get_tu(baseInput) + one = get_cursor(tu, 'one') + two = get_cursor(tu, 'two') - assert one is not None - assert two is not None + self.assertIsNotNone(one) + self.assertIsNotNone(two) - assert_location(one.location,line=1,column=5,offset=4) - assert_location(two.location,line=2,column=5,offset=13) + self.assert_location(one.location,line=1,column=5,offset=4) + self.assert_location(two.location,line=2,column=5,offset=13) - # adding a linebreak at top should keep columns same - tu = get_tu('\n' + baseInput) - one = get_cursor(tu, 'one') - two = get_cursor(tu, 'two') + # adding a linebreak at top should keep columns same + tu = get_tu('\n' + baseInput) + one = get_cursor(tu, 'one') + two = get_cursor(tu, 'two') - assert one is not None - assert two is not None + self.assertIsNotNone(one) + self.assertIsNotNone(two) - assert_location(one.location,line=2,column=5,offset=5) - assert_location(two.location,line=3,column=5,offset=14) + self.assert_location(one.location,line=2,column=5,offset=5) + self.assert_location(two.location,line=3,column=5,offset=14) - # adding a space should affect column on first line only - tu = get_tu(' ' + baseInput) - one = get_cursor(tu, 'one') - two = get_cursor(tu, 'two') + # adding a space should affect column on first line only + tu = get_tu(' ' + baseInput) + one = get_cursor(tu, 'one') + two = get_cursor(tu, 'two') - assert_location(one.location,line=1,column=6,offset=5) - assert_location(two.location,line=2,column=5,offset=14) + self.assert_location(one.location,line=1,column=6,offset=5) + self.assert_location(two.location,line=2,column=5,offset=14) - # define the expected location ourselves and see if it matches - # the returned location - tu = get_tu(baseInput) + # define the expected location ourselves and see if it matches + # the returned location + tu = get_tu(baseInput) - file = File.from_name(tu, 't.c') - location = SourceLocation.from_position(tu, file, 1, 5) - cursor = Cursor.from_location(tu, location) + file = File.from_name(tu, 't.c') + location = SourceLocation.from_position(tu, file, 1, 5) + cursor = Cursor.from_location(tu, location) - one = get_cursor(tu, 'one') - assert one is not None - assert one == cursor + one = get_cursor(tu, 'one') + self.assertIsNotNone(one) + self.assertEqual(one, cursor) - # Ensure locations referring to the same entity are equivalent. - location2 = SourceLocation.from_position(tu, file, 1, 5) - assert location == location2 - location3 = SourceLocation.from_position(tu, file, 1, 4) - assert location2 != location3 + # Ensure locations referring to the same entity are equivalent. + location2 = SourceLocation.from_position(tu, file, 1, 5) + self.assertEqual(location, location2) + location3 = SourceLocation.from_position(tu, file, 1, 4) + self.assertNotEqual(location2, location3) - offset_location = SourceLocation.from_offset(tu, file, 5) - cursor = Cursor.from_location(tu, offset_location) - verified = False - for n in [n for n in tu.cursor.get_children() if n.spelling == 'one']: - assert n == cursor - verified = True + offset_location = SourceLocation.from_offset(tu, file, 5) + cursor = Cursor.from_location(tu, offset_location) + verified = False + for n in [n for n in tu.cursor.get_children() if n.spelling == 'one']: + self.assertEqual(n, cursor) + verified = True - assert verified + self.assertTrue(verified) -def test_extent(): - tu = get_tu(baseInput) - one = get_cursor(tu, 'one') - two = get_cursor(tu, 'two') + def test_extent(self): + tu = get_tu(baseInput) + one = get_cursor(tu, 'one') + two = get_cursor(tu, 'two') - assert_location(one.extent.start,line=1,column=1,offset=0) - assert_location(one.extent.end,line=1,column=8,offset=7) - assert baseInput[one.extent.start.offset:one.extent.end.offset] == "int one" + self.assert_location(one.extent.start,line=1,column=1,offset=0) + self.assert_location(one.extent.end,line=1,column=8,offset=7) + self.assertEqual(baseInput[one.extent.start.offset:one.extent.end.offset], "int one") - assert_location(two.extent.start,line=2,column=1,offset=9) - assert_location(two.extent.end,line=2,column=8,offset=16) - assert baseInput[two.extent.start.offset:two.extent.end.offset] == "int two" + self.assert_location(two.extent.start,line=2,column=1,offset=9) + self.assert_location(two.extent.end,line=2,column=8,offset=16) + self.assertEqual(baseInput[two.extent.start.offset:two.extent.end.offset], "int two") - file = File.from_name(tu, 't.c') - location1 = SourceLocation.from_position(tu, file, 1, 1) - location2 = SourceLocation.from_position(tu, file, 1, 8) + file = File.from_name(tu, 't.c') + location1 = SourceLocation.from_position(tu, file, 1, 1) + location2 = SourceLocation.from_position(tu, file, 1, 8) - range1 = SourceRange.from_locations(location1, location2) - range2 = SourceRange.from_locations(location1, location2) - assert range1 == range2 + range1 = SourceRange.from_locations(location1, location2) + range2 = SourceRange.from_locations(location1, location2) + self.assertEqual(range1, range2) - location3 = SourceLocation.from_position(tu, file, 1, 6) - range3 = SourceRange.from_locations(location1, location3) - assert range1 != range3 + location3 = SourceLocation.from_position(tu, file, 1, 6) + range3 = SourceRange.from_locations(location1, location3) + self.assertNotEqual(range1, range3) diff --git a/bindings/python/tests/cindex/test_tls_kind.py b/bindings/python/tests/cindex/test_tls_kind.py index 6a03c0d5eee2a4513c33abc4e2cfaaf64524d1c6..fbc3418a64ef9ddd378d2b4317db1395d5cf4022 100644 --- a/bindings/python/tests/cindex/test_tls_kind.py +++ b/bindings/python/tests/cindex/test_tls_kind.py @@ -1,4 +1,3 @@ - from clang.cindex import TLSKind from clang.cindex import Cursor from clang.cindex import TranslationUnit @@ -6,32 +5,45 @@ from clang.cindex import TranslationUnit from .util import get_cursor from .util import get_tu -def test_tls_kind(): - """Ensure that thread-local storage kinds are available on cursors.""" +import unittest + + +class TestTLSKind(unittest.TestCase): + def test_tls_kind(self): + """Ensure that thread-local storage kinds are available on cursors.""" - tu = get_tu(""" + tu = get_tu(""" int tls_none; thread_local int tls_dynamic; _Thread_local int tls_static; """, lang = 'cpp') - tls_none = get_cursor(tu.cursor, 'tls_none') - assert tls_none.tls_kind == TLSKind.NONE; + tls_none = get_cursor(tu.cursor, 'tls_none') + self.assertEqual(tls_none.tls_kind, TLSKind.NONE) - tls_dynamic = get_cursor(tu.cursor, 'tls_dynamic') - assert tls_dynamic.tls_kind == TLSKind.DYNAMIC + tls_dynamic = get_cursor(tu.cursor, 'tls_dynamic') + self.assertEqual(tls_dynamic.tls_kind, TLSKind.DYNAMIC) - tls_static = get_cursor(tu.cursor, 'tls_static') - assert tls_static.tls_kind == TLSKind.STATIC + tls_static = get_cursor(tu.cursor, 'tls_static') + self.assertEqual(tls_static.tls_kind, TLSKind.STATIC) - # The following case tests '__declspec(thread)'. Since it is a Microsoft - # specific extension, specific flags are required for the parser to pick - # these up. - flags = ['-fms-extensions', '-target', 'x86_64-unknown-windows-win32'] - tu = get_tu(""" -__declspec(thread) int tls_declspec; + # The following case tests '__declspec(thread)'. Since it is a Microsoft + # specific extension, specific flags are required for the parser to pick + # these up. + flags = ['-fms-extensions', '-target', 'x86_64-unknown-windows-win32', + '-fms-compatibility-version=18'] + tu = get_tu(""" +__declspec(thread) int tls_declspec_msvc18; """, lang = 'cpp', flags=flags) - tls_declspec = get_cursor(tu.cursor, 'tls_declspec') - assert tls_declspec.tls_kind == TLSKind.STATIC + tls_declspec_msvc18 = get_cursor(tu.cursor, 'tls_declspec_msvc18') + self.assertEqual(tls_declspec_msvc18.tls_kind, TLSKind.STATIC) + + flags = ['-fms-extensions', '-target', 'x86_64-unknown-windows-win32', + '-fms-compatibility-version=19'] + tu = get_tu(""" +__declspec(thread) int tls_declspec_msvc19; +""", lang = 'cpp', flags=flags) + tls_declspec_msvc19 = get_cursor(tu.cursor, 'tls_declspec_msvc19') + self.assertEqual(tls_declspec_msvc19.tls_kind, TLSKind.DYNAMIC) diff --git a/bindings/python/tests/cindex/test_token_kind.py b/bindings/python/tests/cindex/test_token_kind.py index 62ec63e0ad5844a83299f23c8f55c9161655cb38..700f95a64624094f84c6904919012b3f65169e08 100644 --- a/bindings/python/tests/cindex/test_token_kind.py +++ b/bindings/python/tests/cindex/test_token_kind.py @@ -1,43 +1,44 @@ from clang.cindex import TokenKind -from nose.tools import eq_ -from nose.tools import ok_ -from nose.tools import raises -def test_constructor(): - """Ensure TokenKind constructor works as expected.""" +import unittest - t = TokenKind(5, 'foo') - eq_(t.value, 5) - eq_(t.name, 'foo') +class TestTokenKind(unittest.TestCase): + def test_constructor(self): + """Ensure TokenKind constructor works as expected.""" -@raises(ValueError) -def test_bad_register(): - """Ensure a duplicate value is rejected for registration.""" + t = TokenKind(5, 'foo') - TokenKind.register(2, 'foo') + self.assertEqual(t.value, 5) + self.assertEqual(t.name, 'foo') -@raises(ValueError) -def test_unknown_value(): - """Ensure trying to fetch an unknown value raises.""" + def test_bad_register(self): + """Ensure a duplicate value is rejected for registration.""" - TokenKind.from_value(-1) + with self.assertRaises(ValueError): + TokenKind.register(2, 'foo') -def test_registration(): - """Ensure that items registered appear as class attributes.""" - ok_(hasattr(TokenKind, 'LITERAL')) - literal = TokenKind.LITERAL + def test_unknown_value(self): + """Ensure trying to fetch an unknown value raises.""" - ok_(isinstance(literal, TokenKind)) + with self.assertRaises(ValueError): + TokenKind.from_value(-1) -def test_from_value(): - """Ensure registered values can be obtained from from_value().""" - t = TokenKind.from_value(3) - ok_(isinstance(t, TokenKind)) - eq_(t, TokenKind.LITERAL) + def test_registration(self): + """Ensure that items registered appear as class attributes.""" + self.assertTrue(hasattr(TokenKind, 'LITERAL')) + literal = TokenKind.LITERAL -def test_repr(): - """Ensure repr() works.""" + self.assertIsInstance(literal, TokenKind) - r = repr(TokenKind.LITERAL) - eq_(r, 'TokenKind.LITERAL') + def test_from_value(self): + """Ensure registered values can be obtained from from_value().""" + t = TokenKind.from_value(3) + self.assertIsInstance(t, TokenKind) + self.assertEqual(t, TokenKind.LITERAL) + + def test_repr(self): + """Ensure repr() works.""" + + r = repr(TokenKind.LITERAL) + self.assertEqual(r, 'TokenKind.LITERAL') diff --git a/bindings/python/tests/cindex/test_tokens.py b/bindings/python/tests/cindex/test_tokens.py index 688b5c1c900e2229e79fff942d654de8e31bcdaf..c93353dc9da27014aa6f0529b0549965e6133905 100644 --- a/bindings/python/tests/cindex/test_tokens.py +++ b/bindings/python/tests/cindex/test_tokens.py @@ -3,50 +3,52 @@ from clang.cindex import Index from clang.cindex import SourceLocation from clang.cindex import SourceRange from clang.cindex import TokenKind -from nose.tools import eq_ -from nose.tools import ok_ from .util import get_tu -def test_token_to_cursor(): - """Ensure we can obtain a Cursor from a Token instance.""" - tu = get_tu('int i = 5;') - r = tu.get_extent('t.c', (0, 9)) - tokens = list(tu.get_tokens(extent=r)) +import unittest - assert len(tokens) == 4 - assert tokens[1].spelling == 'i' - assert tokens[1].kind == TokenKind.IDENTIFIER - cursor = tokens[1].cursor - assert cursor.kind == CursorKind.VAR_DECL - assert tokens[1].cursor == tokens[2].cursor +class TestTokens(unittest.TestCase): + def test_token_to_cursor(self): + """Ensure we can obtain a Cursor from a Token instance.""" + tu = get_tu('int i = 5;') + r = tu.get_extent('t.c', (0, 9)) + tokens = list(tu.get_tokens(extent=r)) -def test_token_location(): - """Ensure Token.location works.""" + self.assertEqual(len(tokens), 4) + self.assertEqual(tokens[1].spelling, 'i') + self.assertEqual(tokens[1].kind, TokenKind.IDENTIFIER) - tu = get_tu('int foo = 10;') - r = tu.get_extent('t.c', (0, 11)) + cursor = tokens[1].cursor + self.assertEqual(cursor.kind, CursorKind.VAR_DECL) + self.assertEqual(tokens[1].cursor, tokens[2].cursor) - tokens = list(tu.get_tokens(extent=r)) - eq_(len(tokens), 4) + def test_token_location(self): + """Ensure Token.location works.""" - loc = tokens[1].location - ok_(isinstance(loc, SourceLocation)) - eq_(loc.line, 1) - eq_(loc.column, 5) - eq_(loc.offset, 4) + tu = get_tu('int foo = 10;') + r = tu.get_extent('t.c', (0, 11)) -def test_token_extent(): - """Ensure Token.extent works.""" - tu = get_tu('int foo = 10;') - r = tu.get_extent('t.c', (0, 11)) + tokens = list(tu.get_tokens(extent=r)) + self.assertEqual(len(tokens), 4) - tokens = list(tu.get_tokens(extent=r)) - eq_(len(tokens), 4) + loc = tokens[1].location + self.assertIsInstance(loc, SourceLocation) + self.assertEqual(loc.line, 1) + self.assertEqual(loc.column, 5) + self.assertEqual(loc.offset, 4) - extent = tokens[1].extent - ok_(isinstance(extent, SourceRange)) + def test_token_extent(self): + """Ensure Token.extent works.""" + tu = get_tu('int foo = 10;') + r = tu.get_extent('t.c', (0, 11)) - eq_(extent.start.offset, 4) - eq_(extent.end.offset, 7) + tokens = list(tu.get_tokens(extent=r)) + self.assertEqual(len(tokens), 4) + + extent = tokens[1].extent + self.assertIsInstance(extent, SourceRange) + + self.assertEqual(extent.start.offset, 4) + self.assertEqual(extent.end.offset, 7) diff --git a/bindings/python/tests/cindex/test_translation_unit.py b/bindings/python/tests/cindex/test_translation_unit.py index 65d1ee02ffa4acad719f0169cd8016b7b32ae570..1b3973d59f6395129d0de60f24a463050d6d4691 100644 --- a/bindings/python/tests/cindex/test_translation_unit.py +++ b/bindings/python/tests/cindex/test_translation_unit.py @@ -1,6 +1,7 @@ import gc import os import tempfile +import unittest from clang.cindex import CursorKind from clang.cindex import Cursor @@ -14,83 +15,9 @@ from clang.cindex import TranslationUnit from .util import get_cursor from .util import get_tu + kInputsDir = os.path.join(os.path.dirname(__file__), 'INPUTS') -def test_spelling(): - path = os.path.join(kInputsDir, 'hello.cpp') - tu = TranslationUnit.from_source(path) - assert tu.spelling == path - -def test_cursor(): - path = os.path.join(kInputsDir, 'hello.cpp') - tu = get_tu(path) - c = tu.cursor - assert isinstance(c, Cursor) - assert c.kind is CursorKind.TRANSLATION_UNIT - -def test_parse_arguments(): - path = os.path.join(kInputsDir, 'parse_arguments.c') - tu = TranslationUnit.from_source(path, ['-DDECL_ONE=hello', '-DDECL_TWO=hi']) - spellings = [c.spelling for c in tu.cursor.get_children()] - assert spellings[-2] == 'hello' - assert spellings[-1] == 'hi' - -def test_reparse_arguments(): - path = os.path.join(kInputsDir, 'parse_arguments.c') - tu = TranslationUnit.from_source(path, ['-DDECL_ONE=hello', '-DDECL_TWO=hi']) - tu.reparse() - spellings = [c.spelling for c in tu.cursor.get_children()] - assert spellings[-2] == 'hello' - assert spellings[-1] == 'hi' - -def test_unsaved_files(): - tu = TranslationUnit.from_source('fake.c', ['-I./'], unsaved_files = [ - ('fake.c', """ -#include "fake.h" -int x; -int SOME_DEFINE; -"""), - ('./fake.h', """ -#define SOME_DEFINE y -""") - ]) - spellings = [c.spelling for c in tu.cursor.get_children()] - assert spellings[-2] == 'x' - assert spellings[-1] == 'y' - -def test_unsaved_files_2(): - try: - from StringIO import StringIO - except: - from io import StringIO - tu = TranslationUnit.from_source('fake.c', unsaved_files = [ - ('fake.c', StringIO('int x;'))]) - 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 normpaths_equal(expected[0], actual.source.name) and \ - normpaths_equal(expected[1], actual.include.name) - else: - 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 = [(src, h1), (h1, h3), (src, h2), (h2, h3)] - - tu = TranslationUnit.from_source(src) - for i in zip(inc, tu.get_includes()): - assert eq(i[0], i[1]) def save_tu(tu): """Convenience API to save a TranslationUnit to a file. @@ -102,153 +29,227 @@ def save_tu(tu): return path -def test_save(): - """Ensure TranslationUnit.save() works.""" - - tu = get_tu('int foo();') - - path = save_tu(tu) - assert os.path.exists(path) - assert os.path.getsize(path) > 0 - os.unlink(path) -def test_save_translation_errors(): - """Ensure that saving to an invalid directory raises.""" - - tu = get_tu('int foo();') - - path = '/does/not/exist/llvm-test.ast' - assert not os.path.exists(os.path.dirname(path)) - - try: - tu.save(path) - assert False - except TranslationUnitSaveError as ex: +class TestTranslationUnit(unittest.TestCase): + def test_spelling(self): + path = os.path.join(kInputsDir, 'hello.cpp') + tu = TranslationUnit.from_source(path) + self.assertEqual(tu.spelling, path) + + def test_cursor(self): + path = os.path.join(kInputsDir, 'hello.cpp') + tu = get_tu(path) + c = tu.cursor + self.assertIsInstance(c, Cursor) + self.assertIs(c.kind, CursorKind.TRANSLATION_UNIT) + + def test_parse_arguments(self): + path = os.path.join(kInputsDir, 'parse_arguments.c') + tu = TranslationUnit.from_source(path, ['-DDECL_ONE=hello', '-DDECL_TWO=hi']) + spellings = [c.spelling for c in tu.cursor.get_children()] + self.assertEqual(spellings[-2], 'hello') + self.assertEqual(spellings[-1], 'hi') + + def test_reparse_arguments(self): + path = os.path.join(kInputsDir, 'parse_arguments.c') + tu = TranslationUnit.from_source(path, ['-DDECL_ONE=hello', '-DDECL_TWO=hi']) + tu.reparse() + spellings = [c.spelling for c in tu.cursor.get_children()] + self.assertEqual(spellings[-2], 'hello') + self.assertEqual(spellings[-1], 'hi') + + def test_unsaved_files(self): + tu = TranslationUnit.from_source('fake.c', ['-I./'], unsaved_files = [ + ('fake.c', """ +#include "fake.h" +int x; +int SOME_DEFINE; +"""), + ('./fake.h', """ +#define SOME_DEFINE y +""") + ]) + spellings = [c.spelling for c in tu.cursor.get_children()] + self.assertEqual(spellings[-2], 'x') + self.assertEqual(spellings[-1], 'y') + + def test_unsaved_files_2(self): + try: + from StringIO import StringIO + except: + from io import StringIO + tu = TranslationUnit.from_source('fake.c', unsaved_files = [ + ('fake.c', StringIO('int x;'))]) + spellings = [c.spelling for c in tu.cursor.get_children()] + self.assertEqual(spellings[-1], 'x') + + def assert_normpaths_equal(self, path1, path2): + """ Compares two paths for equality after normalizing them with + os.path.normpath + """ + self.assertEqual(os.path.normpath(path1), + os.path.normpath(path2)) + + def test_includes(self): + def eq(expected, actual): + if not actual.is_input_file: + self.assert_normpaths_equal(expected[0], actual.source.name) + self.assert_normpaths_equal(expected[1], actual.include.name) + else: + self.assert_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 = [(src, h1), (h1, h3), (src, h2), (h2, h3)] + + tu = TranslationUnit.from_source(src) + for i in zip(inc, tu.get_includes()): + eq(i[0], i[1]) + + def test_save(self): + """Ensure TranslationUnit.save() works.""" + + tu = get_tu('int foo();') + + path = save_tu(tu) + self.assertTrue(os.path.exists(path)) + self.assertGreater(os.path.getsize(path), 0) + os.unlink(path) + + def test_save_translation_errors(self): + """Ensure that saving to an invalid directory raises.""" + + tu = get_tu('int foo();') + + path = '/does/not/exist/llvm-test.ast' + self.assertFalse(os.path.exists(os.path.dirname(path))) + + with self.assertRaises(TranslationUnitSaveError) as cm: + tu.save(path) + ex = cm.exception expected = TranslationUnitSaveError.ERROR_UNKNOWN - assert ex.save_error == expected + self.assertEqual(ex.save_error, expected) -def test_load(): - """Ensure TranslationUnits can be constructed from saved files.""" + def test_load(self): + """Ensure TranslationUnits can be constructed from saved files.""" - tu = get_tu('int foo();') - assert len(tu.diagnostics) == 0 - path = save_tu(tu) + tu = get_tu('int foo();') + self.assertEqual(len(tu.diagnostics), 0) + path = save_tu(tu) - assert os.path.exists(path) - assert os.path.getsize(path) > 0 + self.assertTrue(os.path.exists(path)) + self.assertGreater(os.path.getsize(path), 0) - tu2 = TranslationUnit.from_ast_file(filename=path) - assert len(tu2.diagnostics) == 0 + tu2 = TranslationUnit.from_ast_file(filename=path) + self.assertEqual(len(tu2.diagnostics), 0) - foo = get_cursor(tu2, 'foo') - assert foo is not None + foo = get_cursor(tu2, 'foo') + self.assertIsNotNone(foo) - # Just in case there is an open file descriptor somewhere. - del tu2 - - os.unlink(path) - -def test_index_parse(): - path = os.path.join(kInputsDir, 'hello.cpp') - index = Index.create() - tu = index.parse(path) - assert isinstance(tu, TranslationUnit) - -def test_get_file(): - """Ensure tu.get_file() works appropriately.""" - - tu = get_tu('int foo();') - - f = tu.get_file('t.c') - assert isinstance(f, File) - assert f.name == 't.c' - - try: - f = tu.get_file('foobar.cpp') - except: - pass - else: - assert False - -def test_get_source_location(): - """Ensure tu.get_source_location() works.""" - - tu = get_tu('int foo();') - - location = tu.get_location('t.c', 2) - assert isinstance(location, SourceLocation) - assert location.offset == 2 - assert location.file.name == 't.c' - - location = tu.get_location('t.c', (1, 3)) - assert isinstance(location, SourceLocation) - assert location.line == 1 - assert location.column == 3 - assert location.file.name == 't.c' - -def test_get_source_range(): - """Ensure tu.get_source_range() works.""" - - tu = get_tu('int foo();') - - r = tu.get_extent('t.c', (1,4)) - assert isinstance(r, SourceRange) - assert r.start.offset == 1 - assert r.end.offset == 4 - assert r.start.file.name == 't.c' - assert r.end.file.name == 't.c' - - r = tu.get_extent('t.c', ((1,2), (1,3))) - assert isinstance(r, SourceRange) - assert r.start.line == 1 - assert r.start.column == 2 - assert r.end.line == 1 - assert r.end.column == 3 - assert r.start.file.name == 't.c' - assert r.end.file.name == 't.c' - - start = tu.get_location('t.c', 0) - end = tu.get_location('t.c', 5) - - r = tu.get_extent('t.c', (start, end)) - assert isinstance(r, SourceRange) - assert r.start.offset == 0 - assert r.end.offset == 5 - assert r.start.file.name == 't.c' - assert r.end.file.name == 't.c' - -def test_get_tokens_gc(): - """Ensures get_tokens() works properly with garbage collection.""" - - tu = get_tu('int foo();') - r = tu.get_extent('t.c', (0, 10)) - tokens = list(tu.get_tokens(extent=r)) - - assert tokens[0].spelling == 'int' - gc.collect() - assert tokens[0].spelling == 'int' - - del tokens[1] - gc.collect() - assert tokens[0].spelling == 'int' - - # May trigger segfault if we don't do our job properly. - del tokens - gc.collect() - gc.collect() # Just in case. - -def test_fail_from_source(): - path = os.path.join(kInputsDir, 'non-existent.cpp') - try: - tu = TranslationUnit.from_source(path) - except TranslationUnitLoadError: - tu = None - assert tu == None - -def test_fail_from_ast_file(): - path = os.path.join(kInputsDir, 'non-existent.ast') - try: - tu = TranslationUnit.from_ast_file(path) - except TranslationUnitLoadError: - tu = None - assert tu == None + # Just in case there is an open file descriptor somewhere. + del tu2 + + os.unlink(path) + + def test_index_parse(self): + path = os.path.join(kInputsDir, 'hello.cpp') + index = Index.create() + tu = index.parse(path) + self.assertIsInstance(tu, TranslationUnit) + + def test_get_file(self): + """Ensure tu.get_file() works appropriately.""" + + tu = get_tu('int foo();') + + f = tu.get_file('t.c') + self.assertIsInstance(f, File) + self.assertEqual(f.name, 't.c') + + with self.assertRaises(Exception): + f = tu.get_file('foobar.cpp') + + def test_get_source_location(self): + """Ensure tu.get_source_location() works.""" + + tu = get_tu('int foo();') + + location = tu.get_location('t.c', 2) + self.assertIsInstance(location, SourceLocation) + self.assertEqual(location.offset, 2) + self.assertEqual(location.file.name, 't.c') + + location = tu.get_location('t.c', (1, 3)) + self.assertIsInstance(location, SourceLocation) + self.assertEqual(location.line, 1) + self.assertEqual(location.column, 3) + self.assertEqual(location.file.name, 't.c') + + def test_get_source_range(self): + """Ensure tu.get_source_range() works.""" + + tu = get_tu('int foo();') + + r = tu.get_extent('t.c', (1,4)) + self.assertIsInstance(r, SourceRange) + self.assertEqual(r.start.offset, 1) + self.assertEqual(r.end.offset, 4) + self.assertEqual(r.start.file.name, 't.c') + self.assertEqual(r.end.file.name, 't.c') + + r = tu.get_extent('t.c', ((1,2), (1,3))) + self.assertIsInstance(r, SourceRange) + self.assertEqual(r.start.line, 1) + self.assertEqual(r.start.column, 2) + self.assertEqual(r.end.line, 1) + self.assertEqual(r.end.column, 3) + self.assertEqual(r.start.file.name, 't.c') + self.assertEqual(r.end.file.name, 't.c') + + start = tu.get_location('t.c', 0) + end = tu.get_location('t.c', 5) + + r = tu.get_extent('t.c', (start, end)) + self.assertIsInstance(r, SourceRange) + self.assertEqual(r.start.offset, 0) + self.assertEqual(r.end.offset, 5) + self.assertEqual(r.start.file.name, 't.c') + self.assertEqual(r.end.file.name, 't.c') + + def test_get_tokens_gc(self): + """Ensures get_tokens() works properly with garbage collection.""" + + tu = get_tu('int foo();') + r = tu.get_extent('t.c', (0, 10)) + tokens = list(tu.get_tokens(extent=r)) + + self.assertEqual(tokens[0].spelling, 'int') + gc.collect() + self.assertEqual(tokens[0].spelling, 'int') + + del tokens[1] + gc.collect() + self.assertEqual(tokens[0].spelling, 'int') + + # May trigger segfault if we don't do our job properly. + del tokens + gc.collect() + gc.collect() # Just in case. + + def test_fail_from_source(self): + path = os.path.join(kInputsDir, 'non-existent.cpp') + try: + tu = TranslationUnit.from_source(path) + except TranslationUnitLoadError: + tu = None + self.assertEqual(tu, None) + + def test_fail_from_ast_file(self): + path = os.path.join(kInputsDir, 'non-existent.ast') + try: + tu = TranslationUnit.from_ast_file(path) + except TranslationUnitLoadError: + tu = None + self.assertEqual(tu, None) diff --git a/bindings/python/tests/cindex/test_type.py b/bindings/python/tests/cindex/test_type.py index 6ee0773828ecd9becfd8159b0a70d9873a33d135..4dec0583c7b06a5dec16491eabdad2f8c997c71f 100644 --- a/bindings/python/tests/cindex/test_type.py +++ b/bindings/python/tests/cindex/test_type.py @@ -1,12 +1,13 @@ import gc +import unittest from clang.cindex import CursorKind from clang.cindex import TranslationUnit from clang.cindex import TypeKind -from nose.tools import raises from .util import get_cursor from .util import get_tu + kInput = """\ typedef int I; @@ -24,400 +25,414 @@ struct teststruct { """ -def test_a_struct(): - tu = get_tu(kInput) - - teststruct = get_cursor(tu, 'teststruct') - assert teststruct is not None, "Could not find teststruct." - fields = list(teststruct.get_children()) - assert all(x.kind == CursorKind.FIELD_DECL for x in fields) - assert all(x.translation_unit is not None for x in fields) - - assert fields[0].spelling == 'a' - assert not fields[0].type.is_const_qualified() - assert fields[0].type.kind == TypeKind.INT - assert fields[0].type.get_canonical().kind == TypeKind.INT - assert fields[0].type.get_typedef_name() == '' - - assert fields[1].spelling == 'b' - assert not fields[1].type.is_const_qualified() - assert fields[1].type.kind == TypeKind.TYPEDEF - assert fields[1].type.get_canonical().kind == TypeKind.INT - assert fields[1].type.get_declaration().spelling == 'I' - assert fields[1].type.get_typedef_name() == 'I' - - assert fields[2].spelling == 'c' - assert not fields[2].type.is_const_qualified() - assert fields[2].type.kind == TypeKind.LONG - assert fields[2].type.get_canonical().kind == TypeKind.LONG - assert fields[2].type.get_typedef_name() == '' - - assert fields[3].spelling == 'd' - assert not fields[3].type.is_const_qualified() - assert fields[3].type.kind == TypeKind.ULONG - assert fields[3].type.get_canonical().kind == TypeKind.ULONG - assert fields[3].type.get_typedef_name() == '' - - assert fields[4].spelling == 'e' - assert not fields[4].type.is_const_qualified() - assert fields[4].type.kind == TypeKind.LONG - assert fields[4].type.get_canonical().kind == TypeKind.LONG - assert fields[4].type.get_typedef_name() == '' - - assert fields[5].spelling == 'f' - assert fields[5].type.is_const_qualified() - assert fields[5].type.kind == TypeKind.INT - assert fields[5].type.get_canonical().kind == TypeKind.INT - assert fields[5].type.get_typedef_name() == '' - - assert fields[6].spelling == 'g' - assert not fields[6].type.is_const_qualified() - assert fields[6].type.kind == TypeKind.POINTER - assert fields[6].type.get_pointee().kind == TypeKind.INT - assert fields[6].type.get_typedef_name() == '' - - assert fields[7].spelling == 'h' - assert not fields[7].type.is_const_qualified() - assert fields[7].type.kind == TypeKind.POINTER - assert fields[7].type.get_pointee().kind == TypeKind.POINTER - assert fields[7].type.get_pointee().get_pointee().kind == TypeKind.POINTER - assert fields[7].type.get_pointee().get_pointee().get_pointee().kind == TypeKind.INT - assert fields[7].type.get_typedef_name() == '' - -def test_references(): - """Ensure that a Type maintains a reference to a TranslationUnit.""" - - tu = get_tu('int x;') - children = list(tu.cursor.get_children()) - assert len(children) > 0 - - cursor = children[0] - t = cursor.type - - assert isinstance(t.translation_unit, TranslationUnit) - - # Delete main TranslationUnit reference and force a GC. - del tu - gc.collect() - assert isinstance(t.translation_unit, TranslationUnit) - - # If the TU was destroyed, this should cause a segfault. - decl = t.get_declaration() constarrayInput=""" struct teststruct { void *A[2]; }; """ -def testConstantArray(): - tu = get_tu(constarrayInput) - - teststruct = get_cursor(tu, 'teststruct') - assert teststruct is not None, "Didn't find teststruct??" - fields = list(teststruct.get_children()) - assert fields[0].spelling == 'A' - assert fields[0].type.kind == TypeKind.CONSTANTARRAY - assert fields[0].type.get_array_element_type() is not None - assert fields[0].type.get_array_element_type().kind == TypeKind.POINTER - assert fields[0].type.get_array_size() == 2 - -def test_equal(): - """Ensure equivalence operators work on Type.""" - source = 'int a; int b; void *v;' - tu = get_tu(source) - - a = get_cursor(tu, 'a') - b = get_cursor(tu, 'b') - v = get_cursor(tu, 'v') - - assert a is not None - assert b is not None - assert v is not None - - assert a.type == b.type - assert a.type != v.type - - assert a.type != None - assert a.type != 'foo' - -def test_type_spelling(): - """Ensure Type.spelling works.""" - tu = get_tu('int c[5]; void f(int i[]); int x; int v[x];') - c = get_cursor(tu, 'c') - i = get_cursor(tu, 'i') - x = get_cursor(tu, 'x') - v = get_cursor(tu, 'v') - assert c is not None - assert i is not None - assert x is not None - assert v is not None - assert c.type.spelling == "int [5]" - assert i.type.spelling == "int []" - assert x.type.spelling == "int" - assert v.type.spelling == "int [x]" - -def test_typekind_spelling(): - """Ensure TypeKind.spelling works.""" - tu = get_tu('int a;') - a = get_cursor(tu, 'a') - - assert a is not None - assert a.type.kind.spelling == 'Int' - -def test_function_argument_types(): - """Ensure that Type.argument_types() works as expected.""" - tu = get_tu('void f(int, int);') - f = get_cursor(tu, 'f') - assert f is not None - - args = f.type.argument_types() - assert args is not None - assert len(args) == 2 - - t0 = args[0] - assert t0 is not None - assert t0.kind == TypeKind.INT - - t1 = args[1] - assert t1 is not None - assert t1.kind == TypeKind.INT - - args2 = list(args) - assert len(args2) == 2 - assert t0 == args2[0] - assert t1 == args2[1] - -@raises(TypeError) -def test_argument_types_string_key(): - """Ensure that non-int keys raise a TypeError.""" - tu = get_tu('void f(int, int);') - f = get_cursor(tu, 'f') - assert f is not None - - args = f.type.argument_types() - assert len(args) == 2 - - args['foo'] - -@raises(IndexError) -def test_argument_types_negative_index(): - """Ensure that negative indexes on argument_types Raises an IndexError.""" - tu = get_tu('void f(int, int);') - f = get_cursor(tu, 'f') - args = f.type.argument_types() - - args[-1] - -@raises(IndexError) -def test_argument_types_overflow_index(): - """Ensure that indexes beyond the length of Type.argument_types() raise.""" - tu = get_tu('void f(int, int);') - f = get_cursor(tu, 'f') - args = f.type.argument_types() - - args[2] - -@raises(Exception) -def test_argument_types_invalid_type(): - """Ensure that obtaining argument_types on a Type without them raises.""" - tu = get_tu('int i;') - i = get_cursor(tu, 'i') - assert i is not None - - i.type.argument_types() - -def test_is_pod(): - """Ensure Type.is_pod() works.""" - tu = get_tu('int i; void f();') - i = get_cursor(tu, 'i') - f = get_cursor(tu, 'f') - - assert i is not None - assert f is not None - - assert i.type.is_pod() - assert not f.type.is_pod() - -def test_function_variadic(): - """Ensure Type.is_function_variadic works.""" - - source =""" -#include -void foo(int a, ...); -void bar(int a, int b); -""" - tu = get_tu(source) - foo = get_cursor(tu, 'foo') - bar = get_cursor(tu, 'bar') - - assert foo is not None - assert bar is not None - - assert isinstance(foo.type.is_function_variadic(), bool) - assert foo.type.is_function_variadic() - assert not bar.type.is_function_variadic() - -def test_element_type(): - """Ensure Type.element_type works.""" - tu = get_tu('int c[5]; void f(int i[]); int x; int v[x];') - c = get_cursor(tu, 'c') - i = get_cursor(tu, 'i') - v = get_cursor(tu, 'v') - assert c is not None - assert i is not None - assert v is not None - - assert c.type.kind == TypeKind.CONSTANTARRAY - assert c.type.element_type.kind == TypeKind.INT - assert i.type.kind == TypeKind.INCOMPLETEARRAY - assert i.type.element_type.kind == TypeKind.INT - assert v.type.kind == TypeKind.VARIABLEARRAY - assert v.type.element_type.kind == TypeKind.INT - -@raises(Exception) -def test_invalid_element_type(): - """Ensure Type.element_type raises if type doesn't have elements.""" - tu = get_tu('int i;') - i = get_cursor(tu, 'i') - assert i is not None - i.element_type - -def test_element_count(): - """Ensure Type.element_count works.""" - tu = get_tu('int i[5]; int j;') - i = get_cursor(tu, 'i') - j = get_cursor(tu, 'j') - - assert i is not None - assert j is not None - - assert i.type.element_count == 5 - - try: - j.type.element_count - assert False - except: - assert True - -def test_is_volatile_qualified(): - """Ensure Type.is_volatile_qualified works.""" - - tu = get_tu('volatile int i = 4; int j = 2;') - - i = get_cursor(tu, 'i') - j = get_cursor(tu, 'j') - - assert i is not None - assert j is not None - - assert isinstance(i.type.is_volatile_qualified(), bool) - assert i.type.is_volatile_qualified() - assert not j.type.is_volatile_qualified() - -def test_is_restrict_qualified(): - """Ensure Type.is_restrict_qualified works.""" - - tu = get_tu('struct s { void * restrict i; void * j; };') - - i = get_cursor(tu, 'i') - j = get_cursor(tu, 'j') - - assert i is not None - assert j is not None - - assert isinstance(i.type.is_restrict_qualified(), bool) - assert i.type.is_restrict_qualified() - assert not j.type.is_restrict_qualified() - -def test_record_layout(): - """Ensure Cursor.type.get_size, Cursor.type.get_align and - Cursor.type.get_offset works.""" - - source =""" -struct a { - long a1; - long a2:3; - long a3:4; - long long a4; -}; -""" - tries=[(['-target','i386-linux-gnu'],(4,16,0,32,35,64)), - (['-target','nvptx64-unknown-unknown'],(8,24,0,64,67,128)), - (['-target','i386-pc-win32'],(8,16,0,32,35,64)), - (['-target','msp430-none-none'],(2,14,0,32,35,48))] - for flags, values in tries: - align,total,a1,a2,a3,a4 = values - - tu = get_tu(source, flags=flags) - teststruct = get_cursor(tu, 'a') +class TestType(unittest.TestCase): + def test_a_struct(self): + tu = get_tu(kInput) + + teststruct = get_cursor(tu, 'teststruct') + self.assertIsNotNone(teststruct, "Could not find teststruct.") fields = list(teststruct.get_children()) - assert teststruct.type.get_align() == align - assert teststruct.type.get_size() == total - assert teststruct.type.get_offset(fields[0].spelling) == a1 - assert teststruct.type.get_offset(fields[1].spelling) == a2 - assert teststruct.type.get_offset(fields[2].spelling) == a3 - assert teststruct.type.get_offset(fields[3].spelling) == a4 - assert fields[0].is_bitfield() == False - assert fields[1].is_bitfield() == True - assert fields[1].get_bitfield_width() == 3 - assert fields[2].is_bitfield() == True - assert fields[2].get_bitfield_width() == 4 - assert fields[3].is_bitfield() == False - -def test_offset(): - """Ensure Cursor.get_record_field_offset works in anonymous records""" - source=""" -struct Test { - struct {int a;} typeanon; - struct { - int bariton; - union { - int foo; - }; - }; - int bar; -};""" - tries=[(['-target','i386-linux-gnu'],(4,16,0,32,64,96)), - (['-target','nvptx64-unknown-unknown'],(8,24,0,32,64,96)), - (['-target','i386-pc-win32'],(8,16,0,32,64,96)), - (['-target','msp430-none-none'],(2,14,0,32,64,96))] - for flags, values in tries: - align,total,f1,bariton,foo,bar = values + self.assertEqual(fields[0].kind, CursorKind.FIELD_DECL) + self.assertIsNotNone(fields[0].translation_unit) + self.assertEqual(fields[0].spelling, 'a') + self.assertFalse(fields[0].type.is_const_qualified()) + self.assertEqual(fields[0].type.kind, TypeKind.INT) + self.assertEqual(fields[0].type.get_canonical().kind, TypeKind.INT) + self.assertEqual(fields[0].type.get_typedef_name(), '') + + self.assertEqual(fields[1].kind, CursorKind.FIELD_DECL) + self.assertIsNotNone(fields[1].translation_unit) + self.assertEqual(fields[1].spelling, 'b') + self.assertFalse(fields[1].type.is_const_qualified()) + self.assertEqual(fields[1].type.kind, TypeKind.TYPEDEF) + self.assertEqual(fields[1].type.get_canonical().kind, TypeKind.INT) + self.assertEqual(fields[1].type.get_declaration().spelling, 'I') + self.assertEqual(fields[1].type.get_typedef_name(), 'I') + + self.assertEqual(fields[2].kind, CursorKind.FIELD_DECL) + self.assertIsNotNone(fields[2].translation_unit) + self.assertEqual(fields[2].spelling, 'c') + self.assertFalse(fields[2].type.is_const_qualified()) + self.assertEqual(fields[2].type.kind, TypeKind.LONG) + self.assertEqual(fields[2].type.get_canonical().kind, TypeKind.LONG) + self.assertEqual(fields[2].type.get_typedef_name(), '') + + self.assertEqual(fields[3].kind, CursorKind.FIELD_DECL) + self.assertIsNotNone(fields[3].translation_unit) + self.assertEqual(fields[3].spelling, 'd') + self.assertFalse(fields[3].type.is_const_qualified()) + self.assertEqual(fields[3].type.kind, TypeKind.ULONG) + self.assertEqual(fields[3].type.get_canonical().kind, TypeKind.ULONG) + self.assertEqual(fields[3].type.get_typedef_name(), '') + + self.assertEqual(fields[4].kind, CursorKind.FIELD_DECL) + self.assertIsNotNone(fields[4].translation_unit) + self.assertEqual(fields[4].spelling, 'e') + self.assertFalse(fields[4].type.is_const_qualified()) + self.assertEqual(fields[4].type.kind, TypeKind.LONG) + self.assertEqual(fields[4].type.get_canonical().kind, TypeKind.LONG) + self.assertEqual(fields[4].type.get_typedef_name(), '') + + self.assertEqual(fields[5].kind, CursorKind.FIELD_DECL) + self.assertIsNotNone(fields[5].translation_unit) + self.assertEqual(fields[5].spelling, 'f') + self.assertTrue(fields[5].type.is_const_qualified()) + self.assertEqual(fields[5].type.kind, TypeKind.INT) + self.assertEqual(fields[5].type.get_canonical().kind, TypeKind.INT) + self.assertEqual(fields[5].type.get_typedef_name(), '') + + self.assertEqual(fields[6].kind, CursorKind.FIELD_DECL) + self.assertIsNotNone(fields[6].translation_unit) + self.assertEqual(fields[6].spelling, 'g') + self.assertFalse(fields[6].type.is_const_qualified()) + self.assertEqual(fields[6].type.kind, TypeKind.POINTER) + self.assertEqual(fields[6].type.get_pointee().kind, TypeKind.INT) + self.assertEqual(fields[6].type.get_typedef_name(), '') + + self.assertEqual(fields[7].kind, CursorKind.FIELD_DECL) + self.assertIsNotNone(fields[7].translation_unit) + self.assertEqual(fields[7].spelling, 'h') + self.assertFalse(fields[7].type.is_const_qualified()) + self.assertEqual(fields[7].type.kind, TypeKind.POINTER) + self.assertEqual(fields[7].type.get_pointee().kind, TypeKind.POINTER) + self.assertEqual(fields[7].type.get_pointee().get_pointee().kind, TypeKind.POINTER) + self.assertEqual(fields[7].type.get_pointee().get_pointee().get_pointee().kind, TypeKind.INT) + self.assertEqual(fields[7].type.get_typedef_name(), '') + + def test_references(self): + """Ensure that a Type maintains a reference to a TranslationUnit.""" + + tu = get_tu('int x;') + children = list(tu.cursor.get_children()) + self.assertGreater(len(children), 0) + + cursor = children[0] + t = cursor.type + + self.assertIsInstance(t.translation_unit, TranslationUnit) + + # Delete main TranslationUnit reference and force a GC. + del tu + gc.collect() + self.assertIsInstance(t.translation_unit, TranslationUnit) + + # If the TU was destroyed, this should cause a segfault. + decl = t.get_declaration() + + def testConstantArray(self): + tu = get_tu(constarrayInput) + + teststruct = get_cursor(tu, 'teststruct') + self.assertIsNotNone(teststruct, "Didn't find teststruct??") + fields = list(teststruct.get_children()) + self.assertEqual(fields[0].spelling, 'A') + self.assertEqual(fields[0].type.kind, TypeKind.CONSTANTARRAY) + self.assertIsNotNone(fields[0].type.get_array_element_type()) + self.assertEqual(fields[0].type.get_array_element_type().kind, TypeKind.POINTER) + self.assertEqual(fields[0].type.get_array_size(), 2) + + def test_equal(self): + """Ensure equivalence operators work on Type.""" + source = 'int a; int b; void *v;' tu = get_tu(source) - teststruct = get_cursor(tu, 'Test') - children = list(teststruct.get_children()) - fields = list(teststruct.type.get_fields()) - assert children[0].kind == CursorKind.STRUCT_DECL - assert children[0].spelling != "typeanon" - assert children[1].spelling == "typeanon" - assert fields[0].kind == CursorKind.FIELD_DECL - assert fields[1].kind == CursorKind.FIELD_DECL - assert fields[1].is_anonymous() - assert teststruct.type.get_offset("typeanon") == f1 - assert teststruct.type.get_offset("bariton") == bariton - assert teststruct.type.get_offset("foo") == foo - assert teststruct.type.get_offset("bar") == bar - - -def test_decay(): - """Ensure decayed types are handled as the original type""" - - tu = get_tu("void foo(int a[]);") - foo = get_cursor(tu, 'foo') - a = foo.type.argument_types()[0] - - assert a.kind == TypeKind.INCOMPLETEARRAY - assert a.element_type.kind == TypeKind.INT - assert a.get_canonical().kind == TypeKind.INCOMPLETEARRAY - -def test_addrspace(): - """Ensure the address space can be queried""" - tu = get_tu('__attribute__((address_space(2))) int testInteger = 3;', 'c') - - testInteger = get_cursor(tu, 'testInteger') - - assert testInteger is not None, "Could not find testInteger." - assert testInteger.type.get_address_space() == 2 + + a = get_cursor(tu, 'a') + b = get_cursor(tu, 'b') + v = get_cursor(tu, 'v') + + self.assertIsNotNone(a) + self.assertIsNotNone(b) + self.assertIsNotNone(v) + + self.assertEqual(a.type, b.type) + self.assertNotEqual(a.type, v.type) + + self.assertNotEqual(a.type, None) + self.assertNotEqual(a.type, 'foo') + + def test_type_spelling(self): + """Ensure Type.spelling works.""" + tu = get_tu('int c[5]; void f(int i[]); int x; int v[x];') + c = get_cursor(tu, 'c') + i = get_cursor(tu, 'i') + x = get_cursor(tu, 'x') + v = get_cursor(tu, 'v') + self.assertIsNotNone(c) + self.assertIsNotNone(i) + self.assertIsNotNone(x) + self.assertIsNotNone(v) + self.assertEqual(c.type.spelling, "int [5]") + self.assertEqual(i.type.spelling, "int []") + self.assertEqual(x.type.spelling, "int") + self.assertEqual(v.type.spelling, "int [x]") + + def test_typekind_spelling(self): + """Ensure TypeKind.spelling works.""" + tu = get_tu('int a;') + a = get_cursor(tu, 'a') + + self.assertIsNotNone(a) + self.assertEqual(a.type.kind.spelling, 'Int') + + def test_function_argument_types(self): + """Ensure that Type.argument_types() works as expected.""" + tu = get_tu('void f(int, int);') + f = get_cursor(tu, 'f') + self.assertIsNotNone(f) + + args = f.type.argument_types() + self.assertIsNotNone(args) + self.assertEqual(len(args), 2) + + t0 = args[0] + self.assertIsNotNone(t0) + self.assertEqual(t0.kind, TypeKind.INT) + + t1 = args[1] + self.assertIsNotNone(t1) + self.assertEqual(t1.kind, TypeKind.INT) + + args2 = list(args) + self.assertEqual(len(args2), 2) + self.assertEqual(t0, args2[0]) + self.assertEqual(t1, args2[1]) + + def test_argument_types_string_key(self): + """Ensure that non-int keys raise a TypeError.""" + tu = get_tu('void f(int, int);') + f = get_cursor(tu, 'f') + self.assertIsNotNone(f) + + args = f.type.argument_types() + self.assertEqual(len(args), 2) + + with self.assertRaises(TypeError): + args['foo'] + + def test_argument_types_negative_index(self): + """Ensure that negative indexes on argument_types Raises an IndexError.""" + tu = get_tu('void f(int, int);') + f = get_cursor(tu, 'f') + args = f.type.argument_types() + + with self.assertRaises(IndexError): + args[-1] + + def test_argument_types_overflow_index(self): + """Ensure that indexes beyond the length of Type.argument_types() raise.""" + tu = get_tu('void f(int, int);') + f = get_cursor(tu, 'f') + args = f.type.argument_types() + + with self.assertRaises(IndexError): + args[2] + + def test_argument_types_invalid_type(self): + """Ensure that obtaining argument_types on a Type without them raises.""" + tu = get_tu('int i;') + i = get_cursor(tu, 'i') + self.assertIsNotNone(i) + + with self.assertRaises(Exception): + i.type.argument_types() + + def test_is_pod(self): + """Ensure Type.is_pod() works.""" + tu = get_tu('int i; void f();') + i = get_cursor(tu, 'i') + f = get_cursor(tu, 'f') + + self.assertIsNotNone(i) + self.assertIsNotNone(f) + + self.assertTrue(i.type.is_pod()) + self.assertFalse(f.type.is_pod()) + + def test_function_variadic(self): + """Ensure Type.is_function_variadic works.""" + + source =""" +#include + + void foo(int a, ...); + void bar(int a, int b); + """ + + tu = get_tu(source) + foo = get_cursor(tu, 'foo') + bar = get_cursor(tu, 'bar') + + self.assertIsNotNone(foo) + self.assertIsNotNone(bar) + + self.assertIsInstance(foo.type.is_function_variadic(), bool) + self.assertTrue(foo.type.is_function_variadic()) + self.assertFalse(bar.type.is_function_variadic()) + + def test_element_type(self): + """Ensure Type.element_type works.""" + tu = get_tu('int c[5]; void f(int i[]); int x; int v[x];') + c = get_cursor(tu, 'c') + i = get_cursor(tu, 'i') + v = get_cursor(tu, 'v') + self.assertIsNotNone(c) + self.assertIsNotNone(i) + self.assertIsNotNone(v) + + self.assertEqual(c.type.kind, TypeKind.CONSTANTARRAY) + self.assertEqual(c.type.element_type.kind, TypeKind.INT) + self.assertEqual(i.type.kind, TypeKind.INCOMPLETEARRAY) + self.assertEqual(i.type.element_type.kind, TypeKind.INT) + self.assertEqual(v.type.kind, TypeKind.VARIABLEARRAY) + self.assertEqual(v.type.element_type.kind, TypeKind.INT) + + def test_invalid_element_type(self): + """Ensure Type.element_type raises if type doesn't have elements.""" + tu = get_tu('int i;') + i = get_cursor(tu, 'i') + self.assertIsNotNone(i) + with self.assertRaises(Exception): + i.element_type + + def test_element_count(self): + """Ensure Type.element_count works.""" + tu = get_tu('int i[5]; int j;') + i = get_cursor(tu, 'i') + j = get_cursor(tu, 'j') + + self.assertIsNotNone(i) + self.assertIsNotNone(j) + + self.assertEqual(i.type.element_count, 5) + + with self.assertRaises(Exception): + j.type.element_count + + def test_is_volatile_qualified(self): + """Ensure Type.is_volatile_qualified works.""" + + tu = get_tu('volatile int i = 4; int j = 2;') + + i = get_cursor(tu, 'i') + j = get_cursor(tu, 'j') + + self.assertIsNotNone(i) + self.assertIsNotNone(j) + + self.assertIsInstance(i.type.is_volatile_qualified(), bool) + self.assertTrue(i.type.is_volatile_qualified()) + self.assertFalse(j.type.is_volatile_qualified()) + + def test_is_restrict_qualified(self): + """Ensure Type.is_restrict_qualified works.""" + + tu = get_tu('struct s { void * restrict i; void * j; };') + + i = get_cursor(tu, 'i') + j = get_cursor(tu, 'j') + + self.assertIsNotNone(i) + self.assertIsNotNone(j) + + self.assertIsInstance(i.type.is_restrict_qualified(), bool) + self.assertTrue(i.type.is_restrict_qualified()) + self.assertFalse(j.type.is_restrict_qualified()) + + def test_record_layout(self): + """Ensure Cursor.type.get_size, Cursor.type.get_align and + Cursor.type.get_offset works.""" + + source =""" + struct a { + long a1; + long a2:3; + long a3:4; + long long a4; + }; + """ + tries=[(['-target','i386-linux-gnu'],(4,16,0,32,35,64)), + (['-target','nvptx64-unknown-unknown'],(8,24,0,64,67,128)), + (['-target','i386-pc-win32'],(8,16,0,32,35,64)), + (['-target','msp430-none-none'],(2,14,0,32,35,48))] + for flags, values in tries: + align,total,a1,a2,a3,a4 = values + + tu = get_tu(source, flags=flags) + teststruct = get_cursor(tu, 'a') + fields = list(teststruct.get_children()) + + self.assertEqual(teststruct.type.get_align(), align) + self.assertEqual(teststruct.type.get_size(), total) + self.assertEqual(teststruct.type.get_offset(fields[0].spelling), a1) + self.assertEqual(teststruct.type.get_offset(fields[1].spelling), a2) + self.assertEqual(teststruct.type.get_offset(fields[2].spelling), a3) + self.assertEqual(teststruct.type.get_offset(fields[3].spelling), a4) + self.assertEqual(fields[0].is_bitfield(), False) + self.assertEqual(fields[1].is_bitfield(), True) + self.assertEqual(fields[1].get_bitfield_width(), 3) + self.assertEqual(fields[2].is_bitfield(), True) + self.assertEqual(fields[2].get_bitfield_width(), 4) + self.assertEqual(fields[3].is_bitfield(), False) + + def test_offset(self): + """Ensure Cursor.get_record_field_offset works in anonymous records""" + source=""" + struct Test { + struct {int a;} typeanon; + struct { + int bariton; + union { + int foo; + }; + }; + int bar; + };""" + tries=[(['-target','i386-linux-gnu'],(4,16,0,32,64,96)), + (['-target','nvptx64-unknown-unknown'],(8,24,0,32,64,96)), + (['-target','i386-pc-win32'],(8,16,0,32,64,96)), + (['-target','msp430-none-none'],(2,14,0,32,64,96))] + for flags, values in tries: + align,total,f1,bariton,foo,bar = values + tu = get_tu(source) + teststruct = get_cursor(tu, 'Test') + children = list(teststruct.get_children()) + fields = list(teststruct.type.get_fields()) + self.assertEqual(children[0].kind, CursorKind.STRUCT_DECL) + self.assertNotEqual(children[0].spelling, "typeanon") + self.assertEqual(children[1].spelling, "typeanon") + self.assertEqual(fields[0].kind, CursorKind.FIELD_DECL) + self.assertEqual(fields[1].kind, CursorKind.FIELD_DECL) + self.assertTrue(fields[1].is_anonymous()) + self.assertEqual(teststruct.type.get_offset("typeanon"), f1) + self.assertEqual(teststruct.type.get_offset("bariton"), bariton) + self.assertEqual(teststruct.type.get_offset("foo"), foo) + self.assertEqual(teststruct.type.get_offset("bar"), bar) + + def test_decay(self): + """Ensure decayed types are handled as the original type""" + + tu = get_tu("void foo(int a[]);") + foo = get_cursor(tu, 'foo') + a = foo.type.argument_types()[0] + + self.assertEqual(a.kind, TypeKind.INCOMPLETEARRAY) + self.assertEqual(a.element_type.kind, TypeKind.INT) + self.assertEqual(a.get_canonical().kind, TypeKind.INCOMPLETEARRAY) + + def test_addrspace(self): + """Ensure the address space can be queried""" + tu = get_tu('__attribute__((address_space(2))) int testInteger = 3;', 'c') + + testInteger = get_cursor(tu, 'testInteger') + + self.assertIsNotNone(testInteger, "Could not find testInteger.") + self.assertEqual(testInteger.type.get_address_space(), 2) diff --git a/cmake/caches/Apple-stage2.cmake b/cmake/caches/Apple-stage2.cmake index 8826fc12de993d330d7bbefb9dae2a0e260794f5..d58e4b6fafd5b1dee0814ba827556cc21f740f24 100644 --- a/cmake/caches/Apple-stage2.cmake +++ b/cmake/caches/Apple-stage2.cmake @@ -61,7 +61,7 @@ set(LLVM_DISTRIBUTION_COMPONENTS LTO clang-format clang-headers - libcxx-headers + cxx-headers ${LLVM_TOOLCHAIN_TOOLS} CACHE STRING "") diff --git a/cmake/caches/Fuchsia-stage2.cmake b/cmake/caches/Fuchsia-stage2.cmake index 7b2f2213d3ef760f82399b34e3ea9810afd42e79..2d36f09c999bc6b045c25ab828cf392b27a79d35 100644 --- a/cmake/caches/Fuchsia-stage2.cmake +++ b/cmake/caches/Fuchsia-stage2.cmake @@ -7,8 +7,9 @@ set(PACKAGE_VENDOR Fuchsia CACHE STRING "") set(LLVM_INCLUDE_EXAMPLES OFF CACHE BOOL "") set(LLVM_INCLUDE_DOCS OFF CACHE BOOL "") -set(LLVM_ENABLE_ZLIB ON CACHE BOOL "") set(LLVM_ENABLE_BACKTRACES OFF CACHE BOOL "") +set(LLVM_ENABLE_TERMINFO OFF CACHE BOOL "") +set(LLVM_ENABLE_ZLIB ON CACHE BOOL "") set(LLVM_EXTERNALIZE_DEBUGINFO ON CACHE BOOL "") set(CLANG_PLUGIN_SUPPORT OFF CACHE BOOL "") @@ -16,33 +17,20 @@ set(LLVM_ENABLE_LTO ON CACHE BOOL "") if(NOT APPLE) set(LLVM_ENABLE_LLD ON CACHE BOOL "") set(CLANG_DEFAULT_LINKER lld CACHE STRING "") + set(CLANG_DEFAULT_OBJCOPY llvm-objcopy CACHE STRING "") endif() -# This is a "Does your linker support it?" option that only applies -# to x86-64 ELF targets. All Fuchsia target linkers do support it. -# For x86-64 Linux, it's supported by LLD and by GNU linkers since -# binutils 2.27, so one can hope that all Linux hosts in use handle it. -# Ideally this would be settable as a per-target option. -set(ENABLE_X86_RELAX_RELOCATIONS ON CACHE BOOL "") - -if(APPLE) - set(LLDB_CODESIGN_IDENTITY "" CACHE STRING "") -endif() - +set(LLVM_ENABLE_ASSERTIONS ON CACHE BOOL "") set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "") set(CMAKE_C_FLAGS_RELWITHDEBINFO "-O3 -gline-tables-only -DNDEBUG" CACHE STRING "") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 -gline-tables-only -DNDEBUG" CACHE STRING "") -set(LLVM_BUILTIN_TARGETS "x86_64-fuchsia;aarch64-fuchsia" CACHE STRING "") +set(LLVM_BUILTIN_TARGETS "default;x86_64-fuchsia;aarch64-fuchsia" CACHE STRING "") foreach(target x86_64;aarch64) set(BUILTINS_${target}-fuchsia_CMAKE_SYSROOT ${FUCHSIA_${target}_SYSROOT} CACHE PATH "") set(BUILTINS_${target}-fuchsia_CMAKE_SYSTEM_NAME Fuchsia CACHE STRING "") endforeach() -if(NOT APPLE) - set(LLVM_BUILTIN_TARGETS "default;${LLVM_BUILTIN_TARGETS}" CACHE STRING "" FORCE) -endif() - set(LLVM_RUNTIME_TARGETS "default;x86_64-fuchsia;aarch64-fuchsia;x86_64-fuchsia-asan:x86_64-fuchsia;aarch64-fuchsia-asan:aarch64-fuchsia" CACHE STRING "") foreach(target x86_64;aarch64) set(RUNTIMES_${target}-fuchsia_CMAKE_BUILD_WITH_INSTALL_RPATH ON CACHE BOOL "") @@ -91,12 +79,13 @@ set(LLVM_TOOLCHAIN_TOOLS set(LLVM_DISTRIBUTION_COMPONENTS clang + libclang lld - lldb - liblldb LTO clang-format clang-headers + clang-include-fixer + clang-refactor clang-tidy clangd builtins diff --git a/cmake/caches/Fuchsia.cmake b/cmake/caches/Fuchsia.cmake index 0932c046f628a95e4612b61d173da037905665ba..0d8159294e27c6a86c5c3ab33a985f57ed14e06a 100644 --- a/cmake/caches/Fuchsia.cmake +++ b/cmake/caches/Fuchsia.cmake @@ -8,10 +8,12 @@ set(LLVM_INCLUDE_EXAMPLES OFF CACHE BOOL "") set(LLVM_INCLUDE_TESTS OFF CACHE BOOL "") set(LLVM_INCLUDE_DOCS OFF CACHE BOOL "") set(CLANG_INCLUDE_TESTS OFF CACHE BOOL "") -set(LLVM_ENABLE_ZLIB OFF CACHE BOOL "") set(LLVM_ENABLE_BACKTRACES OFF CACHE BOOL "") +set(LLVM_ENABLE_TERMINFO OFF CACHE BOOL "") +set(LLVM_ENABLE_ZLIB OFF CACHE BOOL "") set(CLANG_PLUGIN_SUPPORT OFF CACHE BOOL "") +set(LLVM_ENABLE_ASSERTIONS ON CACHE BOOL "") set(CMAKE_BUILD_TYPE Release CACHE STRING "") set(BOOTSTRAP_LLVM_ENABLE_LTO ON CACHE BOOL "") diff --git a/cmake/modules/AddClang.cmake b/cmake/modules/AddClang.cmake index e657059744a4ffa77115275f74ee298b6487d891..c09a8423f9f6d51afa2ecd237210bc66009f2793 100644 --- a/cmake/modules/AddClang.cmake +++ b/cmake/modules/AddClang.cmake @@ -104,11 +104,9 @@ macro(add_clang_library name) RUNTIME DESTINATION bin) if (${ARG_SHARED} AND NOT CMAKE_CONFIGURATION_TYPES) - add_custom_target(install-${name} - DEPENDS ${name} - COMMAND "${CMAKE_COMMAND}" - -DCMAKE_INSTALL_COMPONENT=${name} - -P "${CMAKE_BINARY_DIR}/cmake_install.cmake") + add_llvm_install_targets(install-${name} + DEPENDS ${name} + COMPONENT ${name}) endif() endif() set_property(GLOBAL APPEND PROPERTY CLANG_EXPORTS ${name}) @@ -147,11 +145,9 @@ macro(add_clang_tool name) COMPONENT ${name}) if(NOT CMAKE_CONFIGURATION_TYPES) - add_custom_target(install-${name} - DEPENDS ${name} - COMMAND "${CMAKE_COMMAND}" - -DCMAKE_INSTALL_COMPONENT=${name} - -P "${CMAKE_BINARY_DIR}/cmake_install.cmake") + add_llvm_install_targets(install-${name} + DEPENDS ${name} + COMPONENT ${name}) endif() set_property(GLOBAL APPEND PROPERTY CLANG_EXPORTS ${name}) endif() diff --git a/cmake/modules/ProtobufMutator.cmake b/cmake/modules/ProtobufMutator.cmake index be457b5d3a5b1ac811efa2603e606a832b66504b..5f23f33f4c73799c8c2cd4aa09c3ff7b2c48ee84 100644 --- a/cmake/modules/ProtobufMutator.cmake +++ b/cmake/modules/ProtobufMutator.cmake @@ -1,23 +1,18 @@ set(PBM_PREFIX protobuf_mutator) set(PBM_PATH ${CMAKE_CURRENT_BINARY_DIR}/${PBM_PREFIX}/src/${PBM_PREFIX}) -set(PBM_LIB_PATH ${PBM_PATH}/src/libprotobuf-mutator.a) -set(PBM_FUZZ_LIB_PATH ${PBM_PATH}/src/libfuzzer/libprotobuf-mutator-libfuzzer.a) +set(PBM_LIB_PATH ${PBM_PATH}-build/src/libprotobuf-mutator.a) +set(PBM_FUZZ_LIB_PATH ${PBM_PATH}-build/src/libfuzzer/libprotobuf-mutator-libfuzzer.a) ExternalProject_Add(${PBM_PREFIX} PREFIX ${PBM_PREFIX} GIT_REPOSITORY https://github.com/google/libprotobuf-mutator.git GIT_TAG master - CONFIGURE_COMMAND ${CMAKE_COMMAND} -G${CMAKE_GENERATOR} - -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} - -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} - -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} - BUILD_COMMAND ${CMAKE_MAKE_PROGRAM} + CMAKE_ARGS -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} + CMAKE_CACHE_ARGS -DCMAKE_C_COMPILER:FILEPATH=${CMAKE_C_COMPILER} + -DCMAKE_CXX_COMPILER:FILEPATH=${CMAKE_CXX_COMPILER} BUILD_BYPRODUCTS ${PBM_LIB_PATH} ${PBM_FUZZ_LIB_PATH} - BUILD_IN_SOURCE 1 + UPDATE_COMMAND "" INSTALL_COMMAND "" - LOG_DOWNLOAD 1 - LOG_CONFIGURE 1 - LOG_BUILD 1 ) set(ProtobufMutator_INCLUDE_DIRS ${PBM_PATH}) diff --git a/docs/ClangCommandLineReference.rst b/docs/ClangCommandLineReference.rst index 0cc9c71ebe63c2f7f0472d31981f34a3aaa976d3..0026f1fbd0b66b1c02b52c3bf8757dad4517d14a 100644 --- a/docs/ClangCommandLineReference.rst +++ b/docs/ClangCommandLineReference.rst @@ -61,10 +61,10 @@ Pass to the ptxas assembler Pass to the target offloading toolchain. .. program:: clang1 -.. option:: -Xopenmp-target= +.. option:: -Xopenmp-target= .. program:: clang -Pass to the specified target offloading toolchain. The triple that identifies the toolchain must be provided after the equals sign. +Pass to the target offloading toolchain identified by . .. option:: -Z @@ -116,10 +116,18 @@ Output path for the plist report .. option:: -bundle\_loader .. program:: clang +.. option:: -cfguard + +Emit tables required for Windows Control Flow Guard. + .. option:: -client\_name .. option:: -compatibility\_version +.. option:: --config + +Specifies configuration file + .. option:: --constant-cfstrings .. option:: -coverage, --coverage @@ -524,10 +532,10 @@ Serialize compiler diagnostics to a file .. option:: -shared, --shared -.. option:: -shared-libasan - .. option:: -shared-libgcc +.. option:: -shared-libsan, -shared-libasan + .. option:: -single\_module .. option:: -specs=, --specs= @@ -536,6 +544,8 @@ Serialize compiler diagnostics to a file .. option:: -static-libgcc +.. option:: -static-libsan + .. option:: -static-libstdc++ .. option:: -std-default= @@ -588,6 +598,8 @@ Verify the binary representation of debug output .. option:: --version +Print version information + .. option:: -w, --no-warnings Suppress all warnings @@ -698,10 +710,22 @@ Print source range spans in numeric form .. option:: -fdiagnostics-show-category= +.. option:: -fdiscard-value-names, -fno-discard-value-names + +Discard value names in LLVM IR + +.. option:: -fexperimental-isel, -fno-experimental-isel + +Enables the experimental global instruction selector + .. option:: -fexperimental-new-pass-manager, -fno-experimental-new-pass-manager Enables an experimental new pass manager in LLVM. +.. option:: -ffine-grained-bitfield-accesses, -fno-fine-grained-bitfield-accesses + +Use separate accesses for bitfields with legal widths and alignments. + .. option:: -finline-functions, -fno-inline-functions Inline suitable functions @@ -728,6 +752,10 @@ Level of field padding for AddressSanitizer Enable linker dead stripping of globals in AddressSanitizer +.. option:: -fsanitize-address-poison-class-member-array-new-cookie, -fno-sanitize-address-poison-class-member-array-new-cookie + +Enable poisoning array cookies when using class member operator new\[\] in AddressSanitizer + .. option:: -fsanitize-address-use-after-scope, -fno-sanitize-address-use-after-scope Enable use-after-scope detection in AddressSanitizer @@ -740,6 +768,10 @@ Path to blacklist file for sanitizers Enable control flow integrity (CFI) checks for cross-DSO calls. +.. option:: -fsanitize-cfi-icall-generalize-pointers + +Generalize pointers in CFI indirect call type signature checks + .. option:: -fsanitize-coverage=,..., -fno-sanitize-coverage=,... Specify the type of coverage instrumentation for Sanitizers @@ -756,7 +788,7 @@ Enable origins tracking in MemorySanitizer Enable origins tracking in MemorySanitizer -.. option:: -fsanitize-memory-use-after-dtor +.. option:: -fsanitize-memory-use-after-dtor, -fno-sanitize-memory-use-after-dtor Enable use-after-destroy detection in MemorySanitizer @@ -856,6 +888,10 @@ Add directory to include search path Restrict all prior -I flags to double-quoted inclusion and remove current directory from include path +.. option:: --cuda-path-ignore-env + +Ignore environment variables to detect CUDA installation + .. option:: --cuda-path= CUDA installation path @@ -1163,6 +1199,10 @@ Load the clang builtins module map file. .. option:: -fcaret-diagnostics, -fno-caret-diagnostics +.. option:: -fcf-protection=, -fcf-protection (equivalent to -fcf-protection=full) + +Instrument control-flow architecture protection. Options: return, branch, full, none. + .. option:: -fclasspath=, --CLASSPATH , --CLASSPATH=, --classpath , --classpath= .. option:: -fcolor-diagnostics, -fno-color-diagnostics @@ -1263,8 +1303,16 @@ Print a template comparison tree for differing templates Allow '$' in identifiers +.. option:: -fdouble-square-bracket-attributes, -fno-double-square-bracket-attributes + +Enable '\[\[\]\]' attributes in all C and C++ language modes + .. option:: -fdwarf-directory-asm, -fno-dwarf-directory-asm +.. option:: -fdwarf-exceptions + +Use DWARF style exceptions + .. option:: -felide-constructors, -fno-elide-constructors .. option:: -feliminate-unused-debug-symbols, -fno-eliminate-unused-debug-symbols @@ -1341,10 +1389,18 @@ Implicitly search the file system for module map files. .. option:: -finput-charset= +.. option:: -finstrument-function-entry-bare + +Instrument function entry only, after inlining, without arguments to the instrumentation call + .. option:: -finstrument-functions Generate calls to instrument function entry and exit +.. option:: -finstrument-functions-after-inlining + +Like -finstrument-functions, but insert the calls after inlining + .. option:: -fintegrated-as, -fno-integrated-as, -integrated-as Enable the integrated assembler @@ -1467,12 +1523,6 @@ Do not treat C++ operator name keywords as synonyms for operators .. option:: -fno-working-directory -.. option:: -fnoopenmp-relocatable-target - -Do not compile OpenMP target code as relocatable. - -.. option:: -fnoopenmp-use-tls - .. option:: -fobjc-abi-version= .. option:: -fobjc-arc, -fno-objc-arc @@ -1511,13 +1561,11 @@ Enable ARC-style weak references in Objective-C .. option:: -fopenmp, -fno-openmp -.. option:: -fopenmp-dump-offload-linker-script - -.. option:: -fopenmp-relocatable-target +Parse OpenMP pragmas and generate parallel code. -OpenMP target code is compiled as relocatable using the -c flag. For OpenMP targets the code is relocatable by default. +.. option:: -fopenmp-simd, -fno-openmp-simd -.. option:: -fopenmp-use-tls +Emit OpenMP code only for SIMD-based constructs. .. option:: -fopenmp-version= @@ -1557,6 +1605,10 @@ Override the default ABI to return all structs on the stack .. option:: -fpie, -fno-pie +.. option:: -fplt, -fno-plt + +Use the PLT to make function calls + .. option:: -fplugin= Load the named plugin (dynamic shared object) @@ -1654,6 +1706,10 @@ Turn on loop reroller Generate a YAML optimization record file +.. option:: -fseh-exceptions + +Use SEH style exceptions + .. option:: -fshort-enums, -fno-short-enums Allocate to an enum type only as many bytes as it needs for the declared range of possible values @@ -1696,7 +1752,7 @@ Enable the superword-level parallelism vectorization passes .. option:: -fsplit-dwarf-inlining, -fno-split-dwarf-inlining -Place debug types in their own section (ELF Only) +Provide minimal debug info in the object/executable to facilitate online symbolication/stack traces in the absence of .dwo/.dwp files when using Split DWARF .. option:: -fsplit-stack @@ -1712,6 +1768,10 @@ Force the usage of stack protectors for all functions Use a strong heuristic to apply stack protectors to functions +.. option:: -fstack-size-section, -fno-stack-size-section + +Emit section containing metadata on function stack sizes + .. option:: -fstandalone-debug, -fno-limit-debug-info, -fno-standalone-debug Emit full debug info for all types used by the program @@ -1838,6 +1898,10 @@ Treat signed integer overflow as two's complement Store string literals as writable data +.. option:: -fxray-always-emit-customevents, -fno-xray-always-emit-customevents + +Determine whether to always emit \_\_xray\_customevent(...) calls even if the function it appears in is not always instrumented. + .. option:: -fxray-always-instrument= Filename defining the whitelist for imbuing the 'always instrument' XRay attribute. @@ -1914,6 +1978,10 @@ OpenCL language standard to compile for. OpenCL only. This option is added for compatibility with OpenCL 1.0. +.. option:: -cl-uniform-work-group-size + +OpenCL only. Defines that the global work-size be a multiple of the work-group size specified to clEnqueueNDRangeKernel + .. option:: -cl-unsafe-math-optimizations OpenCL only. Allow unsafe floating-point optimizations. Also implies -cl-no-signed-zeros and -cl-mad-enable. @@ -1958,7 +2026,7 @@ Link stack frames through backchain on System Z .. option:: -mconsole -.. option:: -mcpu=, -mv4 (equivalent to -mcpu=hexagonv4), -mv5 (equivalent to -mcpu=hexagonv5), -mv55 (equivalent to -mcpu=hexagonv55), -mv60 (equivalent to -mcpu=hexagonv60), -mv62 (equivalent to -mcpu=hexagonv62) +.. option:: -mcpu=, -mv4 (equivalent to -mcpu=hexagonv4), -mv5 (equivalent to -mcpu=hexagonv5), -mv55 (equivalent to -mcpu=hexagonv55), -mv60 (equivalent to -mcpu=hexagonv60), -mv62 (equivalent to -mcpu=hexagonv62), -mv65 (equivalent to -mcpu=hexagonv65) .. option:: -mdefault-build-attributes, -mno-default-build-attributes @@ -2026,6 +2094,10 @@ Use Intel MCU ABI (integrated-as) Emit an object file which can be used with an incremental linker +.. option:: -mindirect-jump= + +Change indirect jump instructions to inhibit speculation + .. option:: -miphoneos-version-min=, -mios-version-min= .. option:: -mips16 @@ -2080,6 +2152,10 @@ Omit frame pointer setup for leaf functions Use copy relocations support for PIE builds +.. option:: -mprefer-vector-width= + +Specifies preferred vector width for auto-vectorization. Defaults to 'none' which allows target specific decisions. + .. option:: -mqdsp6-compat Enable hexagon-qdsp6 backward compatibility @@ -2116,6 +2192,10 @@ Set the stack alignment Set the stack probe size +.. option:: -mstack-arg-probe, -mno-stack-arg-probe + +Disable stack probes + .. option:: -mstackrealign, -mno-stackrealign Force realign the stack at entry to every function @@ -2162,6 +2242,10 @@ Generate code which only uses the general purpose registers (AArch64 only) AMDGPU ------ +.. option:: -mxnack, -mno-xnack + +Enable XNACK (AMDGPU only) + ARM --- .. option:: -ffixed-r9 @@ -2192,10 +2276,18 @@ Disallow use of CRC instructions (ARM only) Disallow generation of deprecated IT blocks for ARMv8. It is on by default for ARMv8 Thumb mode. +.. option:: -mtp= + +Read thread pointer from coprocessor register (ARM only) + .. option:: -munaligned-access, -mno-unaligned-access Allow memory accesses to be unaligned (AArch32/AArch64 only) +Hexagon +------- +.. option:: -mieee-rnd-near + Hexagon ------- .. option:: -mhvx, -mno-hvx @@ -2206,7 +2298,15 @@ Enable Hexagon Vector eXtensions Enable Hexagon Double Vector eXtensions -.. option:: -mieee-rnd-near +.. option:: -mhvx-length= + +Set Hexagon Vector Length + +.. program:: clang1 +.. option:: -mhvx= +.. program:: clang + +Enable Hexagon Vector eXtensions PowerPC ------- @@ -2246,8 +2346,14 @@ PowerPC WebAssembly ----------- +.. option:: -mnontrapping-fptoint, -mno-nontrapping-fptoint + +.. option:: -msign-ext, -mno-sign-ext + .. option:: -msimd128, -mno-simd128 +.. option:: -mexception-handling, -mno-exception-handling + X86 --- .. option:: -m3dnow, -mno-3dnow @@ -2262,6 +2368,8 @@ X86 .. option:: -mavx2, -mno-avx2 +.. option:: -mavx512bitalg, -mno-avx512bitalg + .. option:: -mavx512bw, -mno-avx512bw .. option:: -mavx512cd, -mno-avx512cd @@ -2278,8 +2386,12 @@ X86 .. option:: -mavx512vbmi, -mno-avx512vbmi +.. option:: -mavx512vbmi2, -mno-avx512vbmi2 + .. option:: -mavx512vl, -mno-avx512vl +.. option:: -mavx512vnni, -mno-avx512vnni + .. option:: -mavx512vpopcntdq, -mno-avx512vpopcntdq .. option:: -mbmi, -mno-bmi @@ -2304,6 +2416,10 @@ X86 .. option:: -mfxsr, -mno-fxsr +.. option:: -mgfni, -mno-gfni + +.. option:: -mibt, -mno-ibt + .. option:: -mlwp, -mno-lwp .. option:: -mlzcnt, -mno-lzcnt @@ -2326,16 +2442,26 @@ X86 .. option:: -mprfchw, -mno-prfchw +.. option:: -mrdpid, -mno-rdpid + .. option:: -mrdrnd, -mno-rdrnd .. option:: -mrdseed, -mno-rdseed +.. option:: -mretpoline, -mno-retpoline + +.. option:: -mretpoline-external-thunk, -mno-retpoline-external-thunk + .. option:: -mrtm, -mno-rtm +.. option:: -msahf, -mno-sahf + .. option:: -msgx, -mno-sgx .. option:: -msha, -mno-sha +.. option:: -mshstk, -mno-shstk + .. option:: -msse, -mno-sse .. option:: -msse2, -mno-sse2 @@ -2354,6 +2480,10 @@ X86 .. option:: -mtbm, -mno-tbm +.. option:: -mvaes, -mno-vaes + +.. option:: -mvpclmulqdq, -mno-vpclmulqdq + .. option:: -mx87, -m80387, -mno-x87 .. option:: -mxop, -mno-xop @@ -2445,6 +2575,10 @@ Debug information flags .. option:: -gdwarf-aranges +.. option:: -gembed-source + +.. option:: -gno-embed-source + .. option:: -ggnu-pubnames .. option:: -grecord-gcc-switches, -gno-record-gcc-switches diff --git a/docs/ClangFormat.rst b/docs/ClangFormat.rst index b4030eac6f1fd3a41f91c40c343bb58a07925642..f53c02ae90d7631574a07a662e9ede07a4c1aa91 100644 --- a/docs/ClangFormat.rst +++ b/docs/ClangFormat.rst @@ -11,7 +11,7 @@ Standalone Tool =============== :program:`clang-format` is located in `clang/tools/clang-format` and can be used -to format C/C++/Obj-C code. +to format C/C++/Java/JavaScript/Objective-C/Protobuf code. .. code-block:: console diff --git a/docs/ClangFormatStyleOptions.rst b/docs/ClangFormatStyleOptions.rst index 0c03c776566dcf4cff97cc16f9cfed157bc3cd18..816b39f06f3e1de4ccc158f0cf0f2721dcb64d7a 100644 --- a/docs/ClangFormatStyleOptions.rst +++ b/docs/ClangFormatStyleOptions.rst @@ -266,13 +266,9 @@ the configuration (without a prefix: ``Auto``). .. code-block:: c++ - true: - int a; // My comment a - int b = 2; // comment b - - false: - int a; // My comment a - int b = 2; // comment about b + true: false: + int a; // My comment a vs. int a; // My comment a + int b = 2; // comment b int b = 2; // comment about b **AllowAllParametersOfDeclarationOnNextLine** (``bool``) If the function declaration doesn't fit on a line, @@ -633,7 +629,9 @@ the configuration (without a prefix: ``Auto``). int bar(); } - * ``bool AfterObjCDeclaration`` Wrap ObjC definitions (``@autoreleasepool``, interfaces, ..). + * ``bool AfterObjCDeclaration`` Wrap ObjC definitions (interfaces, implementations...). + @autoreleasepool and @synchronized blocks are wrapped + according to `AfterControlStatement` flag. * ``bool AfterStruct`` Wrap struct definitions. @@ -1177,6 +1175,46 @@ the configuration (without a prefix: ``Auto``). For example: BOOST_FOREACH. +**IncludeBlocks** (``IncludeBlocksStyle``) + Dependent on the value, multiple ``#include`` blocks can be sorted + as one and divided based on category. + + Possible values: + + * ``IBS_Preserve`` (in configuration: ``Preserve``) + Sort each ``#include`` block separately. + + .. code-block:: c++ + + #include "b.h" into #include "b.h" + + #include #include "a.h" + #include "a.h" #include + + * ``IBS_Merge`` (in configuration: ``Merge``) + Merge multiple ``#include`` blocks together and sort as one. + + .. code-block:: c++ + + #include "b.h" into #include "a.h" + #include "b.h" + #include #include + #include "a.h" + + * ``IBS_Regroup`` (in configuration: ``Regroup``) + Merge multiple ``#include`` blocks together and sort as one. + Then split into groups based on category priority. See + ``IncludeCategories``. + + .. code-block:: c++ + + #include "b.h" into #include "a.h" + #include "b.h" + #include + #include "a.h" #include + + + **IncludeCategories** (``std::vector``) Regular expressions denoting the different ``#include`` categories used for ordering ``#includes``. @@ -1472,6 +1510,52 @@ the configuration (without a prefix: ``Auto``). +**ObjCBinPackProtocolList** (``BinPackStyle``) + Controls bin-packing Objective-C protocol conformance list + items into as few lines as possible when they go over ``ColumnLimit``. + + If ``Auto`` (the default), delegates to the value in + ``BinPackParameters``. If that is ``true``, bin-packs Objective-C + protocol conformance list items into as few lines as possible + whenever they go over ``ColumnLimit``. + + If ``Always``, always bin-packs Objective-C protocol conformance + list items into as few lines as possible whenever they go over + ``ColumnLimit``. + + If ``Never``, lays out Objective-C protocol conformance list items + onto individual lines whenever they go over ``ColumnLimit``. + + + .. code-block:: c++ + + Always (or Auto, if BinPackParameters=true): + @interface ccccccccccccc () < + ccccccccccccc, ccccccccccccc, + ccccccccccccc, ccccccccccccc> { + } + + Never (or Auto, if BinPackParameters=false): + @interface ddddddddddddd () < + ddddddddddddd, + ddddddddddddd, + ddddddddddddd, + ddddddddddddd> { + } + + Possible values: + + * ``BPS_Auto`` (in configuration: ``Auto``) + Automatically determine parameter bin-packing behavior. + + * ``BPS_Always`` (in configuration: ``Always``) + Always bin-pack parameters. + + * ``BPS_Never`` (in configuration: ``Never``) + Never bin-pack parameters. + + + **ObjCBlockIndentWidth** (``unsigned``) The number of characters to use for indentation of ObjC blocks. @@ -1541,6 +1625,44 @@ the configuration (without a prefix: ``Auto``). +**RawStringFormats** (``std::vector``) + Defines hints for detecting supported languages code blocks in raw + strings. + + A raw string with a matching delimiter or a matching enclosing function + name will be reformatted assuming the specified language based on the + style for that language defined in the .clang-format file. If no style has + been defined in the .clang-format file for the specific language, a + predefined style given by 'BasedOnStyle' is used. If 'BasedOnStyle' is not + found, the formatting is based on llvm style. A matching delimiter takes + precedence over a matching enclosing function name for determining the + language of the raw string contents. + + If a canonical delimiter is specified, occurrences of other delimiters for + the same language will be updated to the canonical if possible. + + There should be at most one specification per language and each delimiter + and enclosing function should not occur in multiple specifications. + + To configure this in the .clang-format file, use: + + .. code-block:: yaml + + RawStringFormats: + - Language: TextProto + Delimiters: + - 'pb' + - 'proto' + EnclosingFunctions: + - 'PARSE_TEXT_PROTO' + BasedOnStyle: google + - Language: Cpp + Delimiters: + - 'cc' + - 'cpp' + BasedOnStyle: llvm + CanonicalDelimiter: 'cc' + **ReflowComments** (``bool``) If ``true``, clang-format will attempt to re-flow comments. @@ -1568,6 +1690,14 @@ the configuration (without a prefix: ``Auto``). **SortUsingDeclarations** (``bool``) If ``true``, clang-format will sort using declarations. + The order of using declarations is defined as follows: + Split the strings by "::" and discard any initial empty strings. The last + element of each list is a non-namespace name; all others are namespace + names. Sort the lists of names lexicographically, where the sort order of + individual names is that all non-namespace names come before all namespace + names, and within those groups, names are in case-insensitive + lexicographic order. + .. code-block:: c++ false: true: @@ -1580,7 +1710,7 @@ the configuration (without a prefix: ``Auto``). .. code-block:: c++ true: false: - (int)i; vs. (int) i; + (int) i; vs. (int)i; **SpaceAfterTemplateKeyword** (``bool``) If ``true``, a space will be inserted after the 'template' keyword. @@ -1599,6 +1729,23 @@ the configuration (without a prefix: ``Auto``). int a = 5; vs. int a=5; a += 42 a+=42; +**SpaceBeforeCtorInitializerColon** (``bool``) + If ``false``, spaces will be removed before constructor initializer + colon. + + .. code-block:: c++ + + true: false: + Foo::Foo() : a(a) {} Foo::Foo(): a(a) {} + +**SpaceBeforeInheritanceColon** (``bool``) + If ``false``, spaces will be removed before inheritance colon. + + .. code-block:: c++ + + true: false: + class Foo : Bar {} vs. class Foo: Bar {} + **SpaceBeforeParens** (``SpaceBeforeParensOptions``) Defines in which cases to put a space before opening parentheses. @@ -1643,6 +1790,15 @@ the configuration (without a prefix: ``Auto``). +**SpaceBeforeRangeBasedForLoopColon** (``bool``) + If ``false``, spaces will be removed before range-based for loop + colon. + + .. code-block:: c++ + + true: false: + for (auto v : values) {} vs. for(auto v: values) {} + **SpaceInEmptyParentheses** (``bool``) If ``true``, spaces may be inserted into ``()``. diff --git a/docs/ControlFlowIntegrity.rst b/docs/ControlFlowIntegrity.rst index 04fb43a70f1990c6c2c98424a9d335cdf0a935b1..12b4610f8a282adbcf8d3772d3d60df48a33100f 100644 --- a/docs/ControlFlowIntegrity.rst +++ b/docs/ControlFlowIntegrity.rst @@ -215,6 +215,23 @@ shared library boundaries are handled as if the callee was not compiled with This scheme is currently only supported on the x86 and x86_64 architectures. +``-fsanitize-cfi-icall-generalize-pointers`` +-------------------------------------------- + +Mismatched pointer types are a common cause of cfi-icall check failures. +Translation units compiled with the ``-fsanitize-cfi-icall-generalize-pointers`` +flag relax pointer type checking for call sites in that translation unit, +applied across all functions compiled with ``-fsanitize=cfi-icall``. + +Specifically, pointers in return and argument types are treated as equivalent as +long as the qualifiers for the type they point to match. For example, ``char*`` +``char**`, and ``int*`` are considered equivalent types. However, ``char*`` and +``const char*`` are considered separate types. + +``-fsanitize-cfi-icall-generalize-pointers`` is not compatible with +``-fsanitize-cfi-cross-dso``. + + ``-fsanitize=cfi-icall`` and ``-fsanitize=function`` ---------------------------------------------------- diff --git a/docs/DiagnosticsReference.rst b/docs/DiagnosticsReference.rst index d8c486fc3b3c8e79435ca35cd38f86205fb5ba97..e2b0bd7dd5507b08f0f7dbc9114c8af11f8f7f22 100644 --- a/docs/DiagnosticsReference.rst +++ b/docs/DiagnosticsReference.rst @@ -244,6 +244,21 @@ This diagnostic is an error by default, but the flag ``-Wno-address-of-temporary ------------------ This diagnostic flag exists for GCC compatibility, and has no effect in Clang. +-Waligned-allocation-unavailable +-------------------------------- +This diagnostic is an error by default, but the flag ``-Wno-aligned-allocation-unavailable`` can be used to disable the error. + +**Diagnostic text:** + ++--------------------------------------------------+--------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:error:`error:` |nbsp| :diagtext:`aligned` |nbsp| |+------------------------+| |nbsp| :diagtext:`function of type '`:placeholder:`B`:diagtext:`' is only available on` |nbsp| :placeholder:`C` |nbsp| :placeholder:`D` |nbsp| :diagtext:`or newer`| +| ||:diagtext:`allocation` || | +| |+------------------------+| | +| ||:diagtext:`deallocation`|| | +| |+------------------------+| | ++--------------------------------------------------+--------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + + -Wall ----- Some of the diagnostics controlled by this flag are enabled by default. @@ -745,6 +760,11 @@ This diagnostic is enabled by default. +--------------------------------------------------------------------------------------------------------------------------------------------------------------+ +-Wbinary-literal +---------------- +Controls `-Wc++14-binary-literal`_, `-Wc++98-c++11-compat-binary-literal`_, `-Wgnu-binary-literal`_. + + -Wbind-to-temporary-copy ------------------------ Also controls `-Wc++98-compat-bind-to-temporary-copy`_. @@ -972,7 +992,7 @@ Synonym for `-Wc++11-narrowing`_. -------------- Some of the diagnostics controlled by this flag are enabled by default. -Also controls `-Wc++11-compat-deprecated-writable-strings`_, `-Wc++11-compat-reserved-user-defined-literal`_, `-Wc++11-narrowing`_, `-Wc++98-c++11-c++14-compat`_, `-Wc++98-c++11-compat`_. +Also controls `-Wc++11-compat-deprecated-writable-strings`_, `-Wc++11-compat-reserved-user-defined-literal`_, `-Wc++11-narrowing`_, `-Wc++98-c++11-c++14-c++17-compat`_, `-Wc++98-c++11-c++14-compat`_, `-Wc++98-c++11-compat`_. **Diagnostic text:** @@ -1038,7 +1058,9 @@ This diagnostic is enabled by default. -Wc++11-compat-pedantic ----------------------- -Controls `-Wc++98-c++11-c++14-compat-pedantic`_, `-Wc++98-c++11-compat-pedantic`_. +Some of the diagnostics controlled by this flag are enabled by default. + +Controls `-Wc++11-compat`_, `-Wc++98-c++11-c++14-c++17-compat-pedantic`_, `-Wc++98-c++11-c++14-compat-pedantic`_, `-Wc++98-c++11-compat-pedantic`_. -Wc++11-compat-reserved-user-defined-literal @@ -1288,12 +1310,12 @@ Some of the diagnostics controlled by this flag are enabled by default. -Wc++14-compat -------------- -Synonym for `-Wc++98-c++11-c++14-compat`_. +Controls `-Wc++98-c++11-c++14-c++17-compat`_, `-Wc++98-c++11-c++14-compat`_. -Wc++14-compat-pedantic ----------------------- -Synonym for `-Wc++98-c++11-c++14-compat-pedantic`_. +Controls `-Wc++14-compat`_, `-Wc++98-c++11-c++14-c++17-compat-pedantic`_, `-Wc++98-c++11-c++14-compat-pedantic`_. -Wc++14-extensions @@ -1349,16 +1371,16 @@ Also controls `-Wc++14-binary-literal`_. +-------------------------------------------------------------------------------+ --Wc++1y-extensions ------------------- -Synonym for `-Wc++14-extensions`_. +-Wc++17-compat +-------------- +Some of the diagnostics controlled by this flag are enabled by default. +Controls `-Wc++17-compat-mangling`_, `-Wc++98-c++11-c++14-c++17-compat`_, `-Wdeprecated-increment-bool`_, `-Wdeprecated-register`_. --Wc++1z-compat --------------- -This diagnostic is enabled by default. -Also controls `-Wdeprecated-increment-bool`_, `-Wdeprecated-register`_. +-Wc++17-compat-mangling +----------------------- +This diagnostic is enabled by default. **Diagnostic text:** @@ -1367,42 +1389,49 @@ Also controls `-Wdeprecated-increment-bool`_, `-Wdeprecated-register`_. +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ --Wc++1z-extensions +-Wc++17-compat-pedantic +----------------------- +Some of the diagnostics controlled by this flag are enabled by default. + +Controls `-Wc++17-compat`_, `-Wc++98-c++11-c++14-c++17-compat-pedantic`_. + + +-Wc++17-extensions ------------------ Some of the diagnostics controlled by this flag are enabled by default. **Diagnostic text:** +------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`constexpr if is a C++1z extension`| +|:warning:`warning:` |nbsp| :diagtext:`constexpr if is a C++17 extension`| +------------------------------------------------------------------------+ +---------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`'constexpr' on lambda expressions is a C++1z extension`| +|:warning:`warning:` |nbsp| :diagtext:`'constexpr' on lambda expressions is a C++17 extension`| +---------------------------------------------------------------------------------------------+ +---------------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`use of the` |nbsp| :placeholder:`A` |nbsp| :diagtext:`attribute is a C++1z extension`| +|:warning:`warning:` |nbsp| :diagtext:`use of the` |nbsp| :placeholder:`A` |nbsp| :diagtext:`attribute is a C++17 extension`| +---------------------------------------------------------------------------------------------------------------------------+ +---------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`decomposition declarations are a C++1z extension`| +|:warning:`warning:` |nbsp| :diagtext:`decomposition declarations are a C++17 extension`| +---------------------------------------------------------------------------------------+ +--------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`pack fold expression is a C++1z extension`| +|:warning:`warning:` |nbsp| :diagtext:`pack fold expression is a C++17 extension`| +--------------------------------------------------------------------------------+ +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`'begin' and 'end' returning different types (`:placeholder:`A` |nbsp| :diagtext:`and` |nbsp| :placeholder:`B`:diagtext:`) is a C++1z extension`| +|:warning:`warning:` |nbsp| :diagtext:`'begin' and 'end' returning different types (`:placeholder:`A` |nbsp| :diagtext:`and` |nbsp| :placeholder:`B`:diagtext:`) is a C++17 extension`| +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +----------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`hexadecimal floating literals are a C++1z feature`| +|:warning:`warning:` |nbsp| :diagtext:`hexadecimal floating literals are a C++17 feature`| +----------------------------------------------------------------------------------------+ +----------------------------------------+--------------------+-------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`'`|+------------------+|:diagtext:`' initialization statements are a C++1z extension`| +|:warning:`warning:` |nbsp| :diagtext:`'`|+------------------+|:diagtext:`' initialization statements are a C++17 extension`| | ||:diagtext:`if` || | | |+------------------+| | | ||:diagtext:`switch`|| | @@ -1410,68 +1439,145 @@ Some of the diagnostics controlled by this flag are enabled by default. +----------------------------------------+--------------------+-------------------------------------------------------------+ +-----------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`inline variables are a C++1z extension`| +|:warning:`warning:` |nbsp| :diagtext:`inline variables are a C++17 extension`| +-----------------------------------------------------------------------------+ +---------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`use of multiple declarators in a single using declaration is a C++1z extension`| +|:warning:`warning:` |nbsp| :diagtext:`use of multiple declarators in a single using declaration is a C++17 extension`| +---------------------------------------------------------------------------------------------------------------------+ +-------------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`nested namespace definition is a C++1z extension; define each namespace separately`| +|:warning:`warning:` |nbsp| :diagtext:`nested namespace definition is a C++17 extension; define each namespace separately`| +-------------------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------+---------------------------+-----------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`attributes on` |nbsp| |+-------------------------+| |nbsp| :diagtext:`declaration are a C++17 extension`| +| ||:diagtext:`a namespace` || | +| |+-------------------------+| | +| ||:diagtext:`an enumerator`|| | +| |+-------------------------+| | ++------------------------------------------------------------+---------------------------+-----------------------------------------------------+ + +---------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`capture of '\*this' by copy is a C++1z extension`| +|:warning:`warning:` |nbsp| :diagtext:`capture of '\*this' by copy is a C++17 extension`| +---------------------------------------------------------------------------------------+ +------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`static\_assert with no message is a C++1z extension`| +|:warning:`warning:` |nbsp| :diagtext:`static\_assert with no message is a C++17 extension`| +------------------------------------------------------------------------------------------+ +--------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`template template parameter using 'typename' is a C++1z extension`| +|:warning:`warning:` |nbsp| :diagtext:`template template parameter using 'typename' is a C++17 extension`| +--------------------------------------------------------------------------------------------------------+ +--------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`default scope specifier for attributes is a C++1z extension`| +|:warning:`warning:` |nbsp| :diagtext:`default scope specifier for attributes is a C++17 extension`| +--------------------------------------------------------------------------------------------------+ +-----------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`pack expansion of using declaration is a C++1z extension`| +|:warning:`warning:` |nbsp| :diagtext:`pack expansion of using declaration is a C++17 extension`| +-----------------------------------------------------------------------------------------------+ +-Wc++1y-extensions +------------------ +Synonym for `-Wc++14-extensions`_. + + +-Wc++1z-compat +-------------- +Synonym for `-Wc++17-compat`_. + + +-Wc++1z-compat-mangling +----------------------- +Synonym for `-Wc++17-compat-mangling`_. + + +-Wc++1z-extensions +------------------ +Synonym for `-Wc++17-extensions`_. + + +-Wc++2a-compat +-------------- +**Diagnostic text:** + ++-------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`'`:placeholder:`A`:diagtext:`' is a keyword in C++2a`| ++-------------------------------------------------------------------------------------------+ + + +-Wc++2a-compat-pedantic +----------------------- +Synonym for `-Wc++2a-compat`_. + + +-Wc++2a-extensions +------------------ +Some of the diagnostics controlled by this flag are enabled by default. + +**Diagnostic text:** + ++----------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`default member initializer for bit-field is a C++2a extension`| ++----------------------------------------------------------------------------------------------------+ + ++--------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`explicit capture of 'this' with a capture default of '=' is a C++2a extension`| ++--------------------------------------------------------------------------------------------------------------------+ + ++--------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`invoking a pointer to a 'const &' member function on an rvalue is a C++2a extension`| ++--------------------------------------------------------------------------------------------------------------------------+ + + +-Wc++98-c++11-c++14-c++17-compat +-------------------------------- +**Diagnostic text:** + ++-------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`default member initializer for bit-field is incompatible with C++ standards before C++2a`| ++-------------------------------------------------------------------------------------------------------------------------------+ + ++-----------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`explicit capture of 'this' with a capture default of '=' is incompatible with C++ standards before C++2a`| ++-----------------------------------------------------------------------------------------------------------------------------------------------+ + + +-Wc++98-c++11-c++14-c++17-compat-pedantic +----------------------------------------- +Also controls `-Wc++98-c++11-c++14-c++17-compat`_. + +**Diagnostic text:** + ++-----------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`invoking a pointer to a 'const &' member function on an rvalue is incompatible with C++ standards before C++2a`| ++-----------------------------------------------------------------------------------------------------------------------------------------------------+ + + -Wc++98-c++11-c++14-compat -------------------------- **Diagnostic text:** -+------------------------------------------------------------+---------------------------+--------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`attributes on` |nbsp| |+-------------------------+| |nbsp| :diagtext:`declaration are incompatible with C++ standards before C++1z`| -| ||:diagtext:`a namespace` || | -| |+-------------------------+| | -| ||:diagtext:`an enumerator`|| | -| |+-------------------------+| | -+------------------------------------------------------------+---------------------------+--------------------------------------------------------------------------------+ - +---------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`constexpr if is incompatible with C++ standards before C++1z`| +|:warning:`warning:` |nbsp| :diagtext:`constexpr if is incompatible with C++ standards before C++17`| +---------------------------------------------------------------------------------------------------+ +----------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`constexpr on lambda expressions is incompatible with C++ standards before C++1z`| +|:warning:`warning:` |nbsp| :diagtext:`constexpr on lambda expressions is incompatible with C++ standards before C++17`| +----------------------------------------------------------------------------------------------------------------------+ +------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`decomposition declarations are incompatible with C++ standards before C++1z`| +|:warning:`warning:` |nbsp| :diagtext:`decomposition declarations are incompatible with C++ standards before C++17`| +------------------------------------------------------------------------------------------------------------------+ +-----------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`pack fold expression is incompatible with C++ standards before C++1z`| +|:warning:`warning:` |nbsp| :diagtext:`pack fold expression is incompatible with C++ standards before C++17`| +-----------------------------------------------------------------------------------------------------------+ +---------------------------+--------------------+----------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| |+------------------+| |nbsp| :diagtext:`initialization statements are incompatible with C++ standards before C++1z`| +|:warning:`warning:` |nbsp| |+------------------+| |nbsp| :diagtext:`initialization statements are incompatible with C++ standards before C++17`| | ||:diagtext:`if` || | | |+------------------+| | | ||:diagtext:`switch`|| | @@ -1479,47 +1585,47 @@ Some of the diagnostics controlled by this flag are enabled by default. +---------------------------+--------------------+----------------------------------------------------------------------------------------------+ +--------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`inline variables are incompatible with C++ standards before C++1z`| +|:warning:`warning:` |nbsp| :diagtext:`inline variables are incompatible with C++ standards before C++17`| +--------------------------------------------------------------------------------------------------------+ +------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`nested namespace definition is incompatible with C++ standards before C++1z`| +|:warning:`warning:` |nbsp| :diagtext:`nested namespace definition is incompatible with C++ standards before C++17`| +------------------------------------------------------------------------------------------------------------------+ +-------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`by value capture of '\*this' is incompatible with C++ standards before C++1z`| +|:warning:`warning:` |nbsp| :diagtext:`by value capture of '\*this' is incompatible with C++ standards before C++17`| +-------------------------------------------------------------------------------------------------------------------+ +---------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`static\_assert with no message is incompatible with C++ standards before C++1z`| +|:warning:`warning:` |nbsp| :diagtext:`static\_assert with no message is incompatible with C++ standards before C++17`| +---------------------------------------------------------------------------------------------------------------------+ +-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`non-type template parameters declared with` |nbsp| :placeholder:`A` |nbsp| :diagtext:`are incompatible with C++ standards before C++1z`| +|:warning:`warning:` |nbsp| :diagtext:`non-type template parameters declared with` |nbsp| :placeholder:`A` |nbsp| :diagtext:`are incompatible with C++ standards before C++17`| +-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +-----------------------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`template template parameter using 'typename' is incompatible with C++ standards before C++1z`| +|:warning:`warning:` |nbsp| :diagtext:`template template parameter using 'typename' is incompatible with C++ standards before C++17`| +-----------------------------------------------------------------------------------------------------------------------------------+ +--------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`unicode literals are incompatible with C++ standards before C++1z`| +|:warning:`warning:` |nbsp| :diagtext:`unicode literals are incompatible with C++ standards before C++17`| +--------------------------------------------------------------------------------------------------------+ +-----------------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`default scope specifier for attributes is incompatible with C++ standards before C++1z`| +|:warning:`warning:` |nbsp| :diagtext:`default scope specifier for attributes is incompatible with C++ standards before C++17`| +-----------------------------------------------------------------------------------------------------------------------------+ +------------------------------------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`use of multiple declarators in a single using declaration is incompatible with C++ standards before C++1z`| +|:warning:`warning:` |nbsp| :diagtext:`use of multiple declarators in a single using declaration is incompatible with C++ standards before C++17`| +------------------------------------------------------------------------------------------------------------------------------------------------+ +-----------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`pack expansion using declaration is incompatible with C++ standards before C++1z`| +|:warning:`warning:` |nbsp| :diagtext:`pack expansion using declaration is incompatible with C++ standards before C++17`| +-----------------------------------------------------------------------------------------------------------------------+ +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`'begin' and 'end' returning different types (`:placeholder:`A` |nbsp| :diagtext:`and` |nbsp| :placeholder:`B`:diagtext:`) is incompatible with C++ standards before C++1z`| +|:warning:`warning:` |nbsp| :diagtext:`'begin' and 'end' returning different types (`:placeholder:`A` |nbsp| :diagtext:`and` |nbsp| :placeholder:`B`:diagtext:`) is incompatible with C++ standards before C++17`| +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ @@ -1529,8 +1635,16 @@ Also controls `-Wc++98-c++11-c++14-compat`_. **Diagnostic text:** ++------------------------------------------------------------+---------------------------+--------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`attributes on` |nbsp| |+-------------------------+| |nbsp| :diagtext:`declaration are incompatible with C++ standards before C++17`| +| ||:diagtext:`a namespace` || | +| |+-------------------------+| | +| ||:diagtext:`an enumerator`|| | +| |+-------------------------+| | ++------------------------------------------------------------+---------------------------+--------------------------------------------------------------------------------+ + +---------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`hexadecimal floating literals are incompatible with C++ standards before C++1z`| +|:warning:`warning:` |nbsp| :diagtext:`hexadecimal floating literals are incompatible with C++ standards before C++17`| +---------------------------------------------------------------------------------------------------------------------+ @@ -1587,10 +1701,8 @@ Also controls `-Wc++98-c++11-c++14-compat`_. +----------------------------------------------------------------------------------------------------------+ --Wc++98-c++11-compat-pedantic ------------------------------ -Also controls `-Wc++98-c++11-compat`_. - +-Wc++98-c++11-compat-binary-literal +----------------------------------- **Diagnostic text:** +---------------------------------------------------------------------------------------------------------------+ @@ -1598,9 +1710,14 @@ Also controls `-Wc++98-c++11-compat`_. +---------------------------------------------------------------------------------------------------------------+ +-Wc++98-c++11-compat-pedantic +----------------------------- +Controls `-Wc++98-c++11-compat`_, `-Wc++98-c++11-compat-binary-literal`_. + + -Wc++98-compat -------------- -Also controls `-Wc++98-c++11-c++14-compat`_, `-Wc++98-c++11-compat`_, `-Wc++98-compat-local-type-template-args`_, `-Wc++98-compat-unnamed-type-template-args`_. +Also controls `-Wc++98-c++11-c++14-c++17-compat`_, `-Wc++98-c++11-c++14-compat`_, `-Wc++98-c++11-compat`_, `-Wc++98-compat-local-type-template-args`_, `-Wc++98-compat-unnamed-type-template-args`_. **Diagnostic text:** @@ -1941,7 +2058,7 @@ Also controls `-Wc++98-c++11-c++14-compat`_, `-Wc++98-c++11-compat`_, `-Wc++98-c -Wc++98-compat-pedantic ----------------------- -Also controls `-Wc++98-c++11-c++14-compat-pedantic`_, `-Wc++98-c++11-compat-pedantic`_, `-Wc++98-compat`_, `-Wc++98-compat-bind-to-temporary-copy`_. +Also controls `-Wc++98-c++11-c++14-c++17-compat-pedantic`_, `-Wc++98-c++11-c++14-compat-pedantic`_, `-Wc++98-c++11-compat-pedantic`_, `-Wc++98-compat`_, `-Wc++98-compat-bind-to-temporary-copy`_. **Diagnostic text:** @@ -2435,6 +2552,11 @@ Synonym for `-Wnull-conversion`_. -Wcoroutine ----------- +Synonym for `-Wcoroutine-missing-unhandled-exception`_. + + +-Wcoroutine-missing-unhandled-exception +--------------------------------------- This diagnostic is enabled by default. **Diagnostic text:** @@ -2453,6 +2575,11 @@ This diagnostic is enabled by default. +--------------------------------------------------------------------------------------------------+ +-Wcpp +----- +Synonym for `-W#warnings`_. + + -Wcstring-format-directive -------------------------- **Diagnostic text:** @@ -2716,6 +2843,10 @@ This diagnostic is enabled by default. **Diagnostic text:** ++--------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`specifying 'uuid' as an ATL attribute is deprecated; use \_\_declspec instead`| ++--------------------------------------------------------------------------------------------------------------------+ + +-----------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`use of C-style parameters in Objective-C method declarations is deprecated`| +-----------------------------------------------------------------------------------------------------------------+ @@ -2751,7 +2882,7 @@ This diagnostic is enabled by default. **Diagnostic text:** +----------------------------------------------------------------------+----------------------+ -|:warning:`warning:` |nbsp| :diagtext:`Implementing deprecated` |nbsp| |+--------------------+| +|:warning:`warning:` |nbsp| :diagtext:`implementing deprecated` |nbsp| |+--------------------+| | ||:diagtext:`method` || | |+--------------------+| | ||:diagtext:`class` || @@ -2760,6 +2891,10 @@ This diagnostic is enabled by default. | |+--------------------+| +----------------------------------------------------------------------+----------------------+ ++----------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`implementing unavailable method`| ++----------------------------------------------------------------------+ + -Wdeprecated-increment-bool --------------------------- @@ -2768,7 +2903,7 @@ This diagnostic is enabled by default. **Diagnostic text:** +---------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`incrementing expression of type bool is deprecated and incompatible with C++1z`| +|:warning:`warning:` |nbsp| :diagtext:`incrementing expression of type bool is deprecated and incompatible with C++17`| +---------------------------------------------------------------------------------------------------------------------+ @@ -2818,7 +2953,7 @@ This diagnostic is enabled by default. **Diagnostic text:** +-------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`'register' storage class specifier is deprecated and incompatible with C++1z`| +|:warning:`warning:` |nbsp| :diagtext:`'register' storage class specifier is deprecated and incompatible with C++17`| +-------------------------------------------------------------------------------------------------------------------+ @@ -3227,7 +3362,7 @@ Also controls `-Wdeprecated-dynamic-exception-spec`_. **Diagnostic text:** +--------------------------------------------------------------------------------------------+ -|:error:`error:` |nbsp| :diagtext:`ISO C++1z does not allow dynamic exception specifications`| +|:error:`error:` |nbsp| :diagtext:`ISO C++17 does not allow dynamic exception specifications`| +--------------------------------------------------------------------------------------------+ @@ -3279,7 +3414,7 @@ This diagnostic is enabled by default. **Diagnostic text:** +-------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`ISO C++1z does not allow a decomposition group to be empty`| +|:warning:`warning:` |nbsp| :diagtext:`ISO C++17 does not allow a decomposition group to be empty`| +-------------------------------------------------------------------------------------------------+ @@ -3312,6 +3447,8 @@ Synonym for `-Wextra-tokens`_. -------------- This diagnostic is enabled by default. +Also controls `-Wenum-compare-switch`_. + **Diagnostic text:** +------------------------------------------------------------------------------------------------+ @@ -3319,6 +3456,17 @@ This diagnostic is enabled by default. +------------------------------------------------------------------------------------------------+ +-Wenum-compare-switch +--------------------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++--------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`comparison of two values with different enumeration types in switch statement`| ++--------------------------------------------------------------------------------------------------------------------+ + + -Wenum-conversion ----------------- This diagnostic is enabled by default. @@ -3363,6 +3511,10 @@ This diagnostic is enabled by default. |:warning:`warning:` |nbsp| :diagtext:`exception of type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`will be caught by earlier handler`| +-------------------------------------------------------------------------------------------------------------------------------------+ ++-----------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`has a non-throwing exception specification but can still throw`| ++-----------------------------------------------------------------------------------------------------------------------------+ + -Wexit-time-destructors ----------------------- @@ -3451,7 +3603,7 @@ This diagnostic is enabled by default. ------- Some of the diagnostics controlled by this flag are enabled by default. -Also controls `-Wignored-qualifiers`_, `-Winitializer-overrides`_, `-Wmissing-field-initializers`_, `-Wmissing-method-return-type`_, `-Wsemicolon-before-method-body`_, `-Wsign-compare`_, `-Wunused-parameter`_. +Also controls `-Wignored-qualifiers`_, `-Winitializer-overrides`_, `-Wmissing-field-initializers`_, `-Wmissing-method-return-type`_, `-Wnull-pointer-arithmetic`_, `-Wsemicolon-before-method-body`_, `-Wsign-compare`_, `-Wunused-parameter`_. **Diagnostic text:** @@ -4317,6 +4469,10 @@ This diagnostic is enabled by default. |:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`attribute ignored`| +--------------------------------------------------------------------------------+ ++--------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`attribute ignored for field of type` |nbsp| :placeholder:`B`| ++--------------------------------------------------------------------------------------------------------------------------+ + +---------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`attribute ignored on inline function`| +---------------------------------------------------------------------------------------------------+ @@ -4453,6 +4609,8 @@ This diagnostic is enabled by default. | |+----------------------------------------------------------------------------------------------------------------+| | ||:diagtext:`methods and properties` || | |+----------------------------------------------------------------------------------------------------------------+| +| ||:diagtext:`functions, methods, and properties` || +| |+----------------------------------------------------------------------------------------------------------------+| | ||:diagtext:`struct or union` || | |+----------------------------------------------------------------------------------------------------------------+| | ||:diagtext:`struct, union or class` || @@ -4645,9 +4803,13 @@ This diagnostic is enabled by default. |:warning:`warning:` |nbsp| :diagtext:`\_\_declspec attribute` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is not supported`| +-------------------------------------------------------------------------------------------------------------------------+ -+-------------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`Ignoring unsupported '`:placeholder:`A`:diagtext:`' in the target attribute string`| -+-------------------------------------------------------------------------------------------------------------------------+ ++-------------------------------------------------------+-------------------------+----------------------------------+---------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`ignoring` |nbsp| |+-----------------------+|+--------------------------------+| |nbsp| :diagtext:`'`:placeholder:`C`:diagtext:`' in the target attribute string`| +| ||:diagtext:`unsupported`||| || | +| |+-----------------------+|+--------------------------------+| | +| ||:diagtext:`duplicate` ||| |nbsp| :diagtext:`architecture`|| | +| |+-----------------------+|+--------------------------------+| | ++-------------------------------------------------------+-------------------------+----------------------------------+---------------------------------------------------------------------------------+ -Wignored-optimization-argument @@ -4970,9 +5132,13 @@ Some of the diagnostics controlled by this flag are enabled by default. **Diagnostic text:** -+------------------------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`implicit declaration of function` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is invalid in C99`| -+------------------------------------------------------------------------------------------------------------------------------------+ ++----------------------------------------------------------------------------------------------------------------------------------------+--------------------+ +|:warning:`warning:` |nbsp| :diagtext:`implicit declaration of function` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is invalid in` |nbsp| |+------------------+| +| ||:diagtext:`C99` || +| |+------------------+| +| ||:diagtext:`OpenCL`|| +| |+------------------+| ++----------------------------------------------------------------------------------------------------------------------------------------+--------------------+ +---------------------------------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`implicitly declaring library function '`:placeholder:`A`:diagtext:`' with type` |nbsp| :placeholder:`B`| @@ -5250,6 +5416,10 @@ This diagnostic is enabled by default. |:warning:`warning:` |nbsp| :diagtext:`missing submodule '`:placeholder:`A`:diagtext:`'`| +---------------------------------------------------------------------------------------+ ++--------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`umbrella directory '`:placeholder:`A`:diagtext:`' not found`| ++--------------------------------------------------------------------------------------------------+ + +-------------------------------------------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`umbrella header for module '`:placeholder:`A`:diagtext:`' does not include header '`:placeholder:`B`:diagtext:`'`| +-------------------------------------------------------------------------------------------------------------------------------------------------------+ @@ -5299,7 +5469,7 @@ Also controls `-Wdeprecated-increment-bool`_. **Diagnostic text:** +------------------------------------------------------------------------------------------------+ -|:error:`error:` |nbsp| :diagtext:`ISO C++1z does not allow incrementing expression of type bool`| +|:error:`error:` |nbsp| :diagtext:`ISO C++17 does not allow incrementing expression of type bool`| +------------------------------------------------------------------------------------------------+ @@ -5472,6 +5642,10 @@ Also controls `-Wignored-optimization-argument`_. **Diagnostic text:** ++-----------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`the object size sanitizer has no effect at -O0, but is explicitly enabled:` |nbsp| :placeholder:`A`| ++-----------------------------------------------------------------------------------------------------------------------------------------+ + +-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`optimization level '`:placeholder:`A`:diagtext:`' is not supported; using '`:placeholder:`B`:placeholder:`C`:diagtext:`' instead`| +-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+ @@ -5522,6 +5696,17 @@ This diagnostic is enabled by default. +--------------------------------------------------------------------------------------------------------------+ +-Winvalid-ios-deployment-target +------------------------------- +This diagnostic is an error by default, but the flag ``-Wno-invalid-ios-deployment-target`` can be used to disable the error. + +**Diagnostic text:** + ++------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:error:`error:` |nbsp| :diagtext:`invalid iOS deployment version '`:placeholder:`A`:diagtext:`', iOS 10 is the maximum deployment target for 32-bit targets`| ++------------------------------------------------------------------------------------------------------------------------------------------------------------+ + + -Winvalid-noreturn ------------------ This diagnostic is enabled by default. @@ -6013,6 +6198,8 @@ This diagnostic is enabled by default. -Wmicrosoft-enum-forward-reference ---------------------------------- +This diagnostic is enabled by default. + **Diagnostic text:** +---------------------------------------------------------------------------------------------------+ @@ -6022,8 +6209,6 @@ This diagnostic is enabled by default. -Wmicrosoft-enum-value ---------------------- -This diagnostic is enabled by default. - **Diagnostic text:** +---------------------------------------------------------------------------------------------------------------------------+ @@ -6433,6 +6618,17 @@ This diagnostic flag exists for GCC compatibility, and has no effect in Clang. +--------------------------------------------------------------------------------------------+ +-Wmissing-noescape +------------------ +This diagnostic is enabled by default. + +**Diagnostic text:** + ++----------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`parameter of overriding method should be annotated with \_\_attribute\_\_((noescape))`| ++----------------------------------------------------------------------------------------------------------------------------+ + + -Wmissing-noreturn ------------------ **Diagnostic text:** @@ -6596,7 +6792,7 @@ This diagnostic is an error by default, but the flag ``-Wno-modules-import-neste ------ Some of the diagnostics controlled by this flag are enabled by default. -Controls `-Wcast-of-sel-type`_, `-Wchar-subscripts`_, `-Wcomment`_, `-Wdelete-non-virtual-dtor`_, `-Wextern-c-compat`_, `-Wfor-loop-analysis`_, `-Wformat`_, `-Wimplicit`_, `-Winfinite-recursion`_, `-Wmismatched-tags`_, `-Wmissing-braces`_, `-Wmove`_, `-Wmultichar`_, `-Wobjc-designated-initializers`_, `-Wobjc-missing-super-calls`_, `-Woverloaded-virtual`_, `-Wprivate-extern`_, `-Wreorder`_, `-Wreturn-type`_, `-Wself-assign`_, `-Wself-move`_, `-Wsizeof-array-argument`_, `-Wsizeof-array-decay`_, `-Wstring-plus-int`_, `-Wtrigraphs`_, `-Wuninitialized`_, `-Wunknown-pragmas`_, `-Wunused`_, `-Wuser-defined-warnings`_, `-Wvolatile-register-var`_. +Controls `-Wcast-of-sel-type`_, `-Wchar-subscripts`_, `-Wcomment`_, `-Wdelete-non-virtual-dtor`_, `-Wextern-c-compat`_, `-Wfor-loop-analysis`_, `-Wformat`_, `-Wimplicit`_, `-Winfinite-recursion`_, `-Wmismatched-tags`_, `-Wmissing-braces`_, `-Wmove`_, `-Wmultichar`_, `-Wobjc-designated-initializers`_, `-Wobjc-flexible-array`_, `-Wobjc-missing-super-calls`_, `-Woverloaded-virtual`_, `-Wprivate-extern`_, `-Wreorder`_, `-Wreturn-type`_, `-Wself-assign`_, `-Wself-move`_, `-Wsizeof-array-argument`_, `-Wsizeof-array-decay`_, `-Wstring-plus-int`_, `-Wtrigraphs`_, `-Wuninitialized`_, `-Wunknown-pragmas`_, `-Wunused`_, `-Wuser-defined-warnings`_, `-Wvolatile-register-var`_. -Wmove @@ -6692,6 +6888,11 @@ This diagnostic is enabled by default. +----------------------------------------------------------------+ +-Wnoexcept-type +--------------- +Synonym for `-Wc++17-compat-mangling`_. + + -Wnon-gcc --------- Some of the diagnostics controlled by this flag are enabled by default. @@ -6832,6 +7033,32 @@ This diagnostic is enabled by default. +---------------------------------------------------------------------------------------------------------------------+ +-Wnsconsumed-mismatch +--------------------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++---------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`overriding method has mismatched ns\_consumed attribute on its parameter`| ++---------------------------------------------------------------------------------------------------------------+ + + +-Wnsreturns-mismatch +-------------------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++-------------------------------------------------------------------------------------+---------------------------+------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`overriding method has mismatched ns\_returns\_`|+-------------------------+| |nbsp| :diagtext:`attributes`| +| ||:diagtext:`not\_retained`|| | +| |+-------------------------+| | +| ||:diagtext:`retained` || | +| |+-------------------------+| | ++-------------------------------------------------------------------------------------+---------------------------+------------------------------+ + + -Wnull-arithmetic ----------------- This diagnostic is enabled by default. @@ -6904,6 +7131,23 @@ This diagnostic is enabled by default. +---------------------------------------------------------------------------------------------------------+ +-Wnull-pointer-arithmetic +------------------------- +**Diagnostic text:** + ++--------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`arithmetic on a null pointer treated as a cast from integer to pointer is a GNU extension`| ++--------------------------------------------------------------------------------------------------------------------------------+ + ++-------------------------------------------------------------------------------------------------------------+----------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`performing pointer arithmetic on a null pointer has undefined behavior`|+--------------------------------------------+| +| || || +| |+--------------------------------------------+| +| || |nbsp| :diagtext:`if the offset is nonzero`|| +| |+--------------------------------------------+| ++-------------------------------------------------------------------------------------------------------------+----------------------------------------------+ + + -Wnullability ------------- This diagnostic is enabled by default. @@ -7077,6 +7321,21 @@ This diagnostic is enabled by default. +----------------------------------------------------------------------------------------------------------+ +-Wobjc-flexible-array +--------------------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`field` |nbsp| :placeholder:`A` |nbsp| :diagtext:`can overwrite instance variable` |nbsp| :placeholder:`B` |nbsp| :diagtext:`with variable sized type` |nbsp| :placeholder:`C` |nbsp| :diagtext:`in superclass` |nbsp| :placeholder:`D`| ++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`field` |nbsp| :placeholder:`A` |nbsp| :diagtext:`with variable sized type` |nbsp| :placeholder:`B` |nbsp| :diagtext:`is not visible to subclasses and can conflict with their instance variables`| ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + + -Wobjc-forward-class-redefinition --------------------------------- This diagnostic is enabled by default. @@ -7152,6 +7411,15 @@ This diagnostic is enabled by default. +-------------------------------------------------------------------------------------------+ +-Wobjc-messaging-id +------------------- +**Diagnostic text:** + ++---------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`messaging unqualified id`| ++---------------------------------------------------------------+ + + -Wobjc-method-access -------------------- This diagnostic is enabled by default. @@ -7515,10 +7783,26 @@ This diagnostic is enabled by default. **Diagnostic text:** ++------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`option '-ffine-grained-bitfield-accesses' cannot be enabled together with a sanitizer; flag ignored`| ++------------------------------------------------------------------------------------------------------------------------------------------+ + +----------------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`option '`:placeholder:`A`:diagtext:`' was ignored by the PS4 toolchain, using '-fPIC'`| +----------------------------------------------------------------------------------------------------------------------------+ ++-------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`ignoring '-mabicalls' option as it cannot be used with non position-independent code and the N64 ABI`| ++-------------------------------------------------------------------------------------------------------------------------------------------+ + ++-------------------------------------------------------------------------------------------------------------------+-------------------------------------------+----------------------+ +|:warning:`warning:` |nbsp| :diagtext:`ignoring '-mlong-calls' option as it is not currently supported with` |nbsp| |+-----------------------------------------+|:diagtext:`-mabicalls`| +| || || | +| |+-----------------------------------------+| | +| ||:diagtext:`the implicit usage of` |nbsp| || | +| |+-----------------------------------------+| | ++-------------------------------------------------------------------------------------------------------------------+-------------------------------------------+----------------------+ + -Wout-of-line-declaration ------------------------- @@ -7531,6 +7815,21 @@ This diagnostic is an error by default, but the flag ``-Wno-out-of-line-declarat +-------------------------------------------------------------------------------------------+ +-Wout-of-scope-function +----------------------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++-------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`use of out-of-scope declaration of` |nbsp| :placeholder:`A`|+-------------------------------------------------------------------------------------+| +| || || +| |+-------------------------------------------------------------------------------------+| +| || |nbsp| :diagtext:`whose type is not compatible with that of an implicit declaration`|| +| |+-------------------------------------------------------------------------------------+| ++-------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------+ + + -Wover-aligned -------------- **Diagnostic text:** @@ -7776,7 +8075,7 @@ This diagnostic is enabled by default. -Wpedantic ---------- -Also controls `-Wc++11-extra-semi`_, `-Wc++11-long-long`_, `-Wc++14-binary-literal`_, `-Wc11-extensions`_, `-Wcomplex-component-init`_, `-Wdeclaration-after-statement`_, `-Wdollar-in-identifier-extension`_, `-Wembedded-directive`_, `-Wempty-translation-unit`_, `-Wextended-offsetof`_, `-Wflexible-array-extensions`_, `-Wformat-pedantic`_, `-Wfour-char-constants`_, `-Wgnu-anonymous-struct`_, `-Wgnu-auto-type`_, `-Wgnu-binary-literal`_, `-Wgnu-case-range`_, `-Wgnu-complex-integer`_, `-Wgnu-compound-literal-initializer`_, `-Wgnu-conditional-omitted-operand`_, `-Wgnu-empty-initializer`_, `-Wgnu-empty-struct`_, `-Wgnu-flexible-array-initializer`_, `-Wgnu-flexible-array-union-member`_, `-Wgnu-folding-constant`_, `-Wgnu-imaginary-constant`_, `-Wgnu-include-next`_, `-Wgnu-label-as-value`_, `-Wgnu-redeclared-enum`_, `-Wgnu-statement-expression`_, `-Wgnu-union-cast`_, `-Wgnu-zero-line-directive`_, `-Wgnu-zero-variadic-macro-arguments`_, `-Wimport-preprocessor-directive-pedantic`_, `-Wkeyword-macro`_, `-Wlanguage-extension-token`_, `-Wlong-long`_, `-Wmicrosoft-charize`_, `-Wmicrosoft-comment-paste`_, `-Wmicrosoft-cpp-macro`_, `-Wmicrosoft-end-of-file`_, `-Wmicrosoft-enum-forward-reference`_, `-Wmicrosoft-fixed-enum`_, `-Wmicrosoft-flexible-array`_, `-Wmicrosoft-redeclare-static`_, `-Wnested-anon-types`_, `-Wnullability-extension`_, `-Woverlength-strings`_, `-Wretained-language-linkage`_, `-Wvariadic-macros`_, `-Wvla-extension`_, `-Wzero-length-array`_. +Also controls `-Wc++11-extra-semi`_, `-Wc++11-long-long`_, `-Wc++14-binary-literal`_, `-Wc11-extensions`_, `-Wcomplex-component-init`_, `-Wdeclaration-after-statement`_, `-Wdollar-in-identifier-extension`_, `-Wembedded-directive`_, `-Wempty-translation-unit`_, `-Wextended-offsetof`_, `-Wflexible-array-extensions`_, `-Wformat-pedantic`_, `-Wfour-char-constants`_, `-Wgnu-anonymous-struct`_, `-Wgnu-auto-type`_, `-Wgnu-binary-literal`_, `-Wgnu-case-range`_, `-Wgnu-complex-integer`_, `-Wgnu-compound-literal-initializer`_, `-Wgnu-conditional-omitted-operand`_, `-Wgnu-empty-initializer`_, `-Wgnu-empty-struct`_, `-Wgnu-flexible-array-initializer`_, `-Wgnu-flexible-array-union-member`_, `-Wgnu-folding-constant`_, `-Wgnu-imaginary-constant`_, `-Wgnu-include-next`_, `-Wgnu-label-as-value`_, `-Wgnu-redeclared-enum`_, `-Wgnu-statement-expression`_, `-Wgnu-union-cast`_, `-Wgnu-zero-line-directive`_, `-Wgnu-zero-variadic-macro-arguments`_, `-Wimport-preprocessor-directive-pedantic`_, `-Wkeyword-macro`_, `-Wlanguage-extension-token`_, `-Wlong-long`_, `-Wmicrosoft-charize`_, `-Wmicrosoft-comment-paste`_, `-Wmicrosoft-cpp-macro`_, `-Wmicrosoft-end-of-file`_, `-Wmicrosoft-enum-value`_, `-Wmicrosoft-fixed-enum`_, `-Wmicrosoft-flexible-array`_, `-Wmicrosoft-redeclare-static`_, `-Wnested-anon-types`_, `-Wnullability-extension`_, `-Woverlength-strings`_, `-Wretained-language-linkage`_, `-Wundefined-internal-type`_, `-Wvla-extension`_, `-Wzero-length-array`_. **Diagnostic text:** @@ -7842,6 +8141,10 @@ Also controls `-Wc++11-extra-semi`_, `-Wc++11-long-long`_, `-Wc++14-binary-liter |:warning:`warning:` |nbsp| :diagtext:`parameter` |nbsp| :placeholder:`A` |nbsp| :diagtext:`was not declared, defaulting to type 'int'`| +--------------------------------------------------------------------------------------------------------------------------------------+ ++--------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`invoking a pointer to a 'const &' member function on an rvalue is a C++2a extension`| ++--------------------------------------------------------------------------------------------------------------------------+ + +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`qualifier in explicit instantiation of` |nbsp| :placeholder:`A` |nbsp| :diagtext:`requires a template-id (a typedef is not permitted)`| +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ @@ -7995,7 +8298,7 @@ Also controls `-Wc++11-extra-semi`_, `-Wc++11-long-long`_, `-Wc++14-binary-liter +---------------------------------------------------------------------------------------------------------------------------+ +---------------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`use of the` |nbsp| :placeholder:`A` |nbsp| :diagtext:`attribute is a C++1z extension`| +|:warning:`warning:` |nbsp| :diagtext:`use of the` |nbsp| :placeholder:`A` |nbsp| :diagtext:`attribute is a C++17 extension`| +---------------------------------------------------------------------------------------------------------------------------+ +-----------------------------------------------------------------------------+--------------------+---------------------------------------------+ @@ -8080,6 +8383,14 @@ Also controls `-Wc++11-extra-semi`_, `-Wc++11-long-long`_, `-Wc++14-binary-liter |:warning:`warning:` |nbsp| :diagtext:`exception specification of '...' is a Microsoft extension`| +------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------+---------------------------+-----------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`attributes on` |nbsp| |+-------------------------+| |nbsp| :diagtext:`declaration are a C++17 extension`| +| ||:diagtext:`a namespace` || | +| |+-------------------------+| | +| ||:diagtext:`an enumerator`|| | +| |+-------------------------+| | ++------------------------------------------------------------+---------------------------+-----------------------------------------------------+ + +-----------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`extern templates are a C++11 extension`| +-----------------------------------------------------------------------------+ @@ -8105,7 +8416,7 @@ Also controls `-Wc++11-extra-semi`_, `-Wc++11-long-long`_, `-Wc++14-binary-liter +---------------------------------------------------------------------------------------+ +----------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`hexadecimal floating literals are a C++1z feature`| +|:warning:`warning:` |nbsp| :diagtext:`hexadecimal floating literals are a C++17 feature`| +----------------------------------------------------------------------------------------+ +---------------------------------------------------------------------+ @@ -8124,6 +8435,14 @@ Also controls `-Wc++11-extra-semi`_, `-Wc++11-long-long`_, `-Wc++14-binary-liter |:warning:`warning:` |nbsp| :diagtext:`\_\_VA\_ARGS\_\_ can only appear in the expansion of a C99 variadic macro`| +----------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`variadic macros are a C99 feature`| ++------------------------------------------------------------------------+ + ++--------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`named variadic macros are a GNU extension`| ++--------------------------------------------------------------------------------+ + +------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`empty macro arguments are a C99 feature`| +------------------------------------------------------------------------------+ @@ -8288,6 +8607,17 @@ This diagnostic is enabled by default. +----------------------------------------------------------------------------------------------------------------------------------+ +-Wpragma-clang-attribute +------------------------ +This diagnostic is enabled by default. + +**Diagnostic text:** + ++-------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`unused attribute` |nbsp| :placeholder:`A` |nbsp| :diagtext:`in '#pragma clang attribute push' region`| ++-------------------------------------------------------------------------------------------------------------------------------------------+ + + -Wpragma-once-outside-header ---------------------------- This diagnostic is enabled by default. @@ -8299,6 +8629,32 @@ This diagnostic is enabled by default. +----------------------------------------------------------------+ +-Wpragma-pack +------------- +Some of the diagnostics controlled by this flag are enabled by default. + +Also controls `-Wpragma-pack-suspicious-include`_. + +**Diagnostic text:** + ++---------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`the current #pragma pack aligment value is modified in the included file`| ++---------------------------------------------------------------------------------------------------------------+ + ++---------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`unterminated '#pragma pack (push, ...)' at end of file`| ++---------------------------------------------------------------------------------------------+ + + +-Wpragma-pack-suspicious-include +-------------------------------- +**Diagnostic text:** + ++-------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`non-default #pragma pack value changes the alignment of struct or union members in the included file`| ++-------------------------------------------------------------------------------------------------------------------------------------------+ + + -Wpragma-system-header-outside-header ------------------------------------- This diagnostic is enabled by default. @@ -8314,7 +8670,7 @@ This diagnostic is enabled by default. --------- Some of the diagnostics controlled by this flag are enabled by default. -Also controls `-Wignored-pragmas`_, `-Wunknown-pragmas`_. +Also controls `-Wignored-pragmas`_, `-Wpragma-clang-attribute`_, `-Wpragma-pack`_, `-Wunknown-pragmas`_. **Diagnostic text:** @@ -8370,6 +8726,23 @@ This diagnostic is enabled by default. |:warning:`warning:` |nbsp| :diagtext:`top-level module '`:placeholder:`A`:diagtext:`' in private module map, expected a submodule of '`:placeholder:`B`:diagtext:`'`| +--------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ++----------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`module '`:placeholder:`A`:diagtext:`' already re-exported as '`:placeholder:`B`:diagtext:`'`| ++----------------------------------------------------------------------------------------------------------------------------------+ + + +-Wprofile-instr-missing +----------------------- +**Diagnostic text:** + ++-----------------------------------------------------------------------------------------------------------------------------+---------------+---------------------------------------------+-------------------+---------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`profile data may be incomplete: of` |nbsp| :placeholder:`A` |nbsp| :diagtext:`function`|+-------------+|:diagtext:`,` |nbsp| :placeholder:`B` |nbsp| |+-----------------+| |nbsp| :diagtext:`no data`| +| || || ||:diagtext:`:has` || | +| |+-------------+| |+-----------------+| | +| ||:diagtext:`s`|| ||:diagtext:`:have`|| | +| |+-------------+| |+-----------------+| | ++-----------------------------------------------------------------------------------------------------------------------------+---------------+---------------------------------------------+-------------------+---------------------------+ + -Wprofile-instr-out-of-date --------------------------- @@ -8377,13 +8750,13 @@ This diagnostic is enabled by default. **Diagnostic text:** -+------------------------------------------------------------------------------------------------------------------------------+---------------+---------------------------------------------+-------------------+---------------------------------------------------------------+-------------------+--------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`profile data may be out of date: of` |nbsp| :placeholder:`A` |nbsp| :diagtext:`function`|+-------------+|:diagtext:`,` |nbsp| :placeholder:`B` |nbsp| |+-----------------+| |nbsp| :diagtext:`no data and` |nbsp| :placeholder:`C` |nbsp| |+-----------------+| |nbsp| :diagtext:`mismatched data that will be ignored`| -| || || ||:diagtext:`:has` || ||:diagtext:`:has` || | -| |+-------------+| |+-----------------+| |+-----------------+| | -| ||:diagtext:`s`|| ||:diagtext:`:have`|| ||:diagtext:`:have`|| | -| |+-------------+| |+-----------------+| |+-----------------+| | -+------------------------------------------------------------------------------------------------------------------------------+---------------+---------------------------------------------+-------------------+---------------------------------------------------------------+-------------------+--------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------------------------+---------------+---------------------------------------------+-------------------+--------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`profile data may be out of date: of` |nbsp| :placeholder:`A` |nbsp| :diagtext:`function`|+-------------+|:diagtext:`,` |nbsp| :placeholder:`B` |nbsp| |+-----------------+| |nbsp| :diagtext:`mismatched data that will be ignored`| +| || || ||:diagtext:`:has` || | +| |+-------------+| |+-----------------+| | +| ||:diagtext:`s`|| ||:diagtext:`:have`|| | +| |+-------------+| |+-----------------+| | ++------------------------------------------------------------------------------------------------------------------------------+---------------+---------------------------------------------+-------------------+--------------------------------------------------------+ -Wprofile-instr-unprofiled @@ -8448,9 +8821,29 @@ This diagnostic is enabled by default. **Diagnostic text:** -+-----------------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`property of type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`was selected for synthesis`| -+-----------------------------------------------------------------------------------------------------------------------------+ ++-------------------------------------------------------+----------------------------------------------------------------+----------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`property` |nbsp| |+--------------------------------------------------------------+| |nbsp| :diagtext:`was selected for synthesis`| +| ||+-------------------------------------------+ || | +| |||:diagtext:`of type` |nbsp| :placeholder:`B`| || | +| ||+-------------------------------------------+ || | +| |+--------------------------------------------------------------+| | +| ||+---------------------------------------------------------+ || | +| |||:diagtext:`with attribute '`:placeholder:`B`:diagtext:`'`| || | +| ||+---------------------------------------------------------+ || | +| |+--------------------------------------------------------------+| | +| ||+------------------------------------------------------------+|| | +| |||:diagtext:`without attribute '`:placeholder:`B`:diagtext:`'`||| | +| ||+------------------------------------------------------------+|| | +| |+--------------------------------------------------------------+| | +| ||+-----------------------------------------------+ || | +| |||:diagtext:`with getter` |nbsp| :placeholder:`B`| || | +| ||+-----------------------------------------------+ || | +| |+--------------------------------------------------------------+| | +| ||+-----------------------------------------------+ || | +| |||:diagtext:`with setter` |nbsp| :placeholder:`B`| || | +| ||+-----------------------------------------------+ || | +| |+--------------------------------------------------------------+| | ++-------------------------------------------------------+----------------------------------------------------------------+----------------------------------------------+ -Wqualified-void-return-type @@ -8542,6 +8935,15 @@ This diagnostic flag exists for GCC compatibility, and has no effect in Clang. +-------------------------------------------------------------------------+ +-Wredundant-parens +------------------ +**Diagnostic text:** + ++-----------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`redundant parentheses surrounding declarator`| ++-----------------------------------------------------------------------------------+ + + -Wregister ---------- This diagnostic is enabled by default. @@ -8551,7 +8953,7 @@ Also controls `-Wdeprecated-register`_. **Diagnostic text:** +----------------------------------------------------------------------------------------------+ -|:error:`error:` |nbsp| :diagtext:`ISO C++1z does not allow 'register' storage class specifier`| +|:error:`error:` |nbsp| :diagtext:`ISO C++17 does not allow 'register' storage class specifier`| +----------------------------------------------------------------------------------------------+ @@ -8695,9 +9097,9 @@ Also controls `-Wreturn-type-c-linkage`_. | |+--------------------+| | +---------------------------------------------------+----------------------+-----------------------------------------------------------------+ -+--------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`control reaches end of non-void coroutine`| -+--------------------------------------------------------------------------------+ ++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`control reaches end of coroutine; which is undefined behavior because the promise type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`does not declare 'return\_void()'`| ++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +-------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`control reaches end of non-void function`| @@ -8707,9 +9109,9 @@ Also controls `-Wreturn-type-c-linkage`_. |:warning:`warning:` |nbsp| :diagtext:`control reaches end of non-void lambda`| +-----------------------------------------------------------------------------+ -+----------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`control may reach end of non-void coroutine`| -+----------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`control may reach end of coroutine; which is undefined behavior because the promise type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`does not declare 'return\_void()'`| ++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +---------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`control may reach end of non-void function`| @@ -8789,6 +9191,10 @@ This diagnostic is enabled by default. **Diagnostic text:** ++--------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`section attribute is specified on redeclared variable`| ++--------------------------------------------------------------------------------------------+ + +----------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`section does not match previous declaration`| +----------------------------------------------------------------------------------+ @@ -9370,6 +9776,8 @@ This diagnostic flag exists for GCC compatibility, and has no effect in Clang. |:warning:`warning:` |nbsp| :diagtext:`this` |nbsp| |+------------------------------------------------------------+| |nbsp| :diagtext:`a prototype`| | ||:diagtext:`function declaration is not` || | | |+------------------------------------------------------------+| | +| ||:diagtext:`block declaration is not` || | +| |+------------------------------------------------------------+| | | ||:diagtext:`old-style function definition is not preceded by`|| | | |+------------------------------------------------------------+| | +---------------------------------------------------+--------------------------------------------------------------+-------------------------------+ @@ -9383,6 +9791,8 @@ This diagnostic flag exists for GCC compatibility, and has no effect in Clang. |:warning:`warning:` |nbsp| :diagtext:`this` |nbsp| |+------------------------------------------------------------+| |nbsp| :diagtext:`a prototype`| | ||:diagtext:`function declaration is not` || | | |+------------------------------------------------------------+| | +| ||:diagtext:`block declaration is not` || | +| |+------------------------------------------------------------+| | | ||:diagtext:`old-style function definition is not preceded by`|| | | |+------------------------------------------------------------+| | +---------------------------------------------------+--------------------------------------------------------------+-------------------------------+ @@ -9576,7 +9986,7 @@ This diagnostic flag exists for GCC compatibility, and has no effect in Clang. ---------------------- Some of the diagnostics controlled by this flag are enabled by default. -Also controls `-Wtautological-constant-out-of-range-compare`_, `-Wtautological-overlap-compare`_, `-Wtautological-pointer-compare`_, `-Wtautological-undefined-compare`_. +Also controls `-Wtautological-constant-compare`_, `-Wtautological-overlap-compare`_, `-Wtautological-pointer-compare`_, `-Wtautological-undefined-compare`_. **Diagnostic text:** @@ -9598,21 +10008,22 @@ Also controls `-Wtautological-constant-out-of-range-compare`_, `-Wtautological-o | |+-----------------+| +-------------------------------------------------------------------------------------+-------------------+ -+-------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`comparison of unsigned`|+------------------------+| |nbsp| :diagtext:`expression` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is always` |nbsp| :placeholder:`B`| -| || || | -| |+------------------------+| | -| || |nbsp| :diagtext:`enum`|| | -| |+------------------------+| | -+-------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------------------------------------------+ -+--------------------------------------------------------------------------------------------------------+--------------------------+----------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`comparison of` |nbsp| :placeholder:`A` |nbsp| :diagtext:`unsigned`|+------------------------+| |nbsp| :diagtext:`expression is always` |nbsp| :placeholder:`B`| -| || || | -| |+------------------------+| | -| || |nbsp| :diagtext:`enum`|| | -| |+------------------------+| | -+--------------------------------------------------------------------------------------------------------+--------------------------+----------------------------------------------------------------+ +-Wtautological-constant-compare +------------------------------- +This diagnostic is enabled by default. + +Also controls `-Wtautological-constant-out-of-range-compare`_, `-Wtautological-unsigned-enum-zero-compare`_, `-Wtautological-unsigned-zero-compare`_. + +**Diagnostic text:** + ++---------------------------------------------------------+------------------+--------------------------------+------------------+-------------------------------------+-------------------+ +|:warning:`warning:` |nbsp| :diagtext:`comparison` |nbsp| |+----------------+| |nbsp| :placeholder:`C` |nbsp| |+----------------+| |nbsp| :diagtext:`is always` |nbsp| |+-----------------+| +| ||:placeholder:`D`|| ||:placeholder:`B`|| ||:diagtext:`false`|| +| |+----------------+| |+----------------+| |+-----------------+| +| ||:placeholder:`B`|| ||:placeholder:`D`|| ||:diagtext:`true` || +| |+----------------+| |+----------------+| |+-----------------+| ++---------------------------------------------------------+------------------+--------------------------------+------------------+-------------------------------------+-------------------+ -Wtautological-constant-out-of-range-compare @@ -9695,6 +10106,36 @@ This diagnostic is enabled by default. +------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------+ +-Wtautological-unsigned-enum-zero-compare +----------------------------------------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++------------------------------------------------------------+--------------------------------------+--------------------------------+--------------------------------------+-------------------------------------+-------------------+ +|:warning:`warning:` |nbsp| :diagtext:`comparison of` |nbsp| |+------------------------------------+| |nbsp| :placeholder:`C` |nbsp| |+------------------------------------+| |nbsp| :diagtext:`is always` |nbsp| |+-----------------+| +| ||:placeholder:`D` || ||:diagtext:`unsigned enum expression`|| ||:diagtext:`false`|| +| |+------------------------------------+| |+------------------------------------+| |+-----------------+| +| ||:diagtext:`unsigned enum expression`|| ||:placeholder:`D` || ||:diagtext:`true` || +| |+------------------------------------+| |+------------------------------------+| |+-----------------+| ++------------------------------------------------------------+--------------------------------------+--------------------------------+--------------------------------------+-------------------------------------+-------------------+ + + +-Wtautological-unsigned-zero-compare +------------------------------------ +This diagnostic is enabled by default. + +**Diagnostic text:** + ++------------------------------------------------------------+---------------------------------+--------------------------------+---------------------------------+-------------------------------------+-------------------+ +|:warning:`warning:` |nbsp| :diagtext:`comparison of` |nbsp| |+-------------------------------+| |nbsp| :placeholder:`C` |nbsp| |+-------------------------------+| |nbsp| :diagtext:`is always` |nbsp| |+-----------------+| +| ||:placeholder:`D` || ||:diagtext:`unsigned expression`|| ||:diagtext:`false`|| +| |+-------------------------------+| |+-------------------------------+| |+-----------------+| +| ||:diagtext:`unsigned expression`|| ||:placeholder:`D` || ||:diagtext:`true` || +| |+-------------------------------+| |+-------------------------------+| |+-----------------+| ++------------------------------------------------------------+---------------------------------+--------------------------------+---------------------------------+-------------------------------------+-------------------+ + + -Wtentative-definition-incomplete-type -------------------------------------- This diagnostic is enabled by default. @@ -10110,6 +10551,19 @@ This diagnostic is enabled by default. +---------------------------+----------------------+-----------------------------------------------------------------------------------+ +-Wundefined-internal-type +------------------------- +**Diagnostic text:** + ++---------------------------------------------------------------------------------------------------------+----------------------+----------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`ISO C++ requires a definition in this translation unit for` |nbsp| |+--------------------+| |nbsp| :placeholder:`B` |nbsp| :diagtext:`because its type does not have linkage`| +| ||:diagtext:`function`|| | +| |+--------------------+| | +| ||:diagtext:`variable`|| | +| |+--------------------+| | ++---------------------------------------------------------------------------------------------------------+----------------------+----------------------------------------------------------------------------------+ + + -Wundefined-reinterpret-cast ---------------------------- **Diagnostic text:** @@ -10149,19 +10603,22 @@ Also controls `-Wpotentially-evaluated-expression`_. -Wunguarded-availability ------------------------ +Some of the diagnostics controlled by this flag are enabled by default. + +Also controls `-Wunguarded-availability-new`_. + **Diagnostic text:** -+----------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is only available conditionally`| -+----------------------------------------------------------------------------------------------+ ++---------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is only available on` |nbsp| :placeholder:`B` |nbsp| :placeholder:`C` |nbsp| :diagtext:`or newer`| ++---------------------------------------------------------------------------------------------------------------------------------------------------------------+ -+------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`may be partial because the receiver type is unknown`| -+------------------------------------------------------------------------------------------------------------------+ -+--------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is partial:` |nbsp| :placeholder:`B`| -+--------------------------------------------------------------------------------------------------+ +-Wunguarded-availability-new +---------------------------- +This diagnostic is enabled by default. + +**Diagnostic text:** +---------------------------------------------------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is only available on` |nbsp| :placeholder:`B` |nbsp| :placeholder:`C` |nbsp| :diagtext:`or newer`| @@ -10314,10 +10771,6 @@ Some of the diagnostics controlled by this flag are enabled by default. |:warning:`warning:` |nbsp| :diagtext:`unexpected token in pragma diagnostic`| +----------------------------------------------------------------------------+ -+----------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`unknown warning group '`:placeholder:`A`:diagtext:`', ignored`| -+----------------------------------------------------------------------------------------------------+ - +-------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`unknown pragma ignored`| +-------------------------------------------------------------+ @@ -10376,6 +10829,10 @@ This diagnostic is enabled by default. **Diagnostic text:** ++----------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`unknown warning group '`:placeholder:`A`:diagtext:`', ignored`| ++----------------------------------------------------------------------------------------------------+ + +------------------------------------------------------+---------------------+---------------------------------------------------------+--------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`unknown` |nbsp| |+-------------------+| |nbsp| :diagtext:`option '`:placeholder:`B`:diagtext:`'`|+------------------------------------------------------------+| | ||:diagtext:`warning`|| || || @@ -10488,6 +10945,36 @@ This diagnostic is enabled by default. +-----------------------------------------------------------------------------------------------------+ +-Wunsupported-abs +----------------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++-----------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`ignoring '-mabs=2008' option because the '`:placeholder:`A`:diagtext:`' architecture does not support it`| ++-----------------------------------------------------------------------------------------------------------------------------------------------+ + ++-------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`ignoring '-mabs=legacy' option because the '`:placeholder:`A`:diagtext:`' architecture does not support it`| ++-------------------------------------------------------------------------------------------------------------------------------------------------+ + + +-Wunsupported-availability-guard +-------------------------------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++---------------------------+------------------------------------+--------------------------------------------------------------+------------------------------------+---------------------+ +|:warning:`warning:` |nbsp| |+----------------------------------+| |nbsp| :diagtext:`does not guard availability here; use if (`|+----------------------------------+|:diagtext:`) instead`| +| ||:diagtext:`@available` || ||:diagtext:`@available` || | +| |+----------------------------------+| |+----------------------------------+| | +| ||:diagtext:`\_\_builtin\_available`|| ||:diagtext:`\_\_builtin\_available`|| | +| |+----------------------------------+| |+----------------------------------+| | ++---------------------------+------------------------------------+--------------------------------------------------------------+------------------------------------+---------------------+ + + -Wunsupported-cb ---------------- This diagnostic is enabled by default. @@ -10527,6 +11014,21 @@ This diagnostic is enabled by default. +-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +-Wunsupported-gpopt +------------------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++--------------------------------------------------------------------------------------------------+-------------------------------------------+----------------------+ +|:warning:`warning:` |nbsp| :diagtext:`ignoring '-mgpopt' option as it cannot be used with` |nbsp| |+-----------------------------------------+|:diagtext:`-mabicalls`| +| || || | +| |+-----------------------------------------+| | +| ||:diagtext:`the implicit usage of` |nbsp| || | +| |+-----------------------------------------+| | ++--------------------------------------------------------------------------------------------------+-------------------------------------------+----------------------+ + + -Wunsupported-nan ----------------- This diagnostic is enabled by default. @@ -10585,14 +11087,14 @@ This diagnostic is enabled by default. **Diagnostic text:** ++-------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`argument '`:placeholder:`A`:diagtext:`' requires profile-guided optimization information`| ++-------------------------------------------------------------------------------------------------------------------------------+ + +---------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`joined argument expects additional value: '`:placeholder:`A`:diagtext:`'`| +---------------------------------------------------------------------------------------------------------------+ -+-----------------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`argument '-fdiagnostics-show-hotness' requires profile-guided optimization information`| -+-----------------------------------------------------------------------------------------------------------------------------+ - +----------------------------------------------------------------------------------------------------+----------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :placeholder:`A`:diagtext:`: '`:placeholder:`B`:diagtext:`' input unused`|+--------------------------------------------------------------------+| | ||+------------------------------------------------------------------+|| @@ -10621,6 +11123,10 @@ This diagnostic is enabled by default. |:warning:`warning:` |nbsp| :diagtext:`argument unused during compilation: '`:placeholder:`A`:diagtext:`'`| +---------------------------------------------------------------------------------------------------------+ ++----------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`the flag '`:placeholder:`A`:diagtext:`' has been deprecated and will be ignored`| ++----------------------------------------------------------------------------------------------------------------------+ + -Wunused-comparison ------------------- @@ -10781,6 +11287,21 @@ This diagnostic is enabled by default. +-------------------------------------------------------------------------------------------------------------------------------------------+ +-Wunused-template +----------------- +Also controls `-Wunneeded-internal-declaration`_. + +**Diagnostic text:** + ++-----------------------------------------------------+----------------------+----------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`unused` |nbsp| |+--------------------+| |nbsp| :diagtext:`template` |nbsp| :placeholder:`B`| +| ||:diagtext:`function`|| | +| |+--------------------+| | +| ||:diagtext:`variable`|| | +| |+--------------------+| | ++-----------------------------------------------------+----------------------+----------------------------------------------------+ + + -Wunused-value -------------- This diagnostic is enabled by default. @@ -10888,12 +11409,18 @@ This diagnostic is enabled by default. -Wvariadic-macros ----------------- +Some of the diagnostics controlled by this flag are enabled by default. + **Diagnostic text:** +--------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`named variadic macros are a GNU extension`| +--------------------------------------------------------------------------------+ ++-----------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`\_\_VA\_OPT\_\_ can only appear in the expansion of a variadic macro`| ++-----------------------------------------------------------------------------------------------------------+ + +------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`variadic macros are a C99 feature`| +------------------------------------------------------------------------+ @@ -10952,6 +11479,10 @@ This diagnostic is enabled by default. |:warning:`warning:` |nbsp| :diagtext:`parentheses were disambiguated as a function declaration`| +-----------------------------------------------------------------------------------------------+ ++-----------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`parentheses were disambiguated as redundant parentheses around declaration of variable named` |nbsp| :placeholder:`A`| ++-----------------------------------------------------------------------------------------------------------------------------------------------------------+ + -Wvisibility ------------ @@ -11037,6 +11568,15 @@ Also controls `-Wdeprecated-writable-strings`_. Synonym for `-Wwritable-strings`_. +-Wzero-as-null-pointer-constant +------------------------------- +**Diagnostic text:** + ++--------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`zero as null pointer constant`| ++--------------------------------------------------------------------+ + + -Wzero-length-array ------------------- **Diagnostic text:** diff --git a/docs/HardwareAssistedAddressSanitizerDesign.rst b/docs/HardwareAssistedAddressSanitizerDesign.rst new file mode 100644 index 0000000000000000000000000000000000000000..71a9df10173ffd39b081e5c8dc8c3351a3fe586f --- /dev/null +++ b/docs/HardwareAssistedAddressSanitizerDesign.rst @@ -0,0 +1,160 @@ +======================================================= +Hardware-assisted AddressSanitizer Design Documentation +======================================================= + +This page is a design document for +**hardware-assisted AddressSanitizer** (or **HWASAN**) +a tool similar to :doc:`AddressSanitizer`, +but based on partial hardware assistance. + +The document is a draft, suggestions are welcome. + + +Introduction +============ + +:doc:`AddressSanitizer` +tags every 8 bytes of the application memory with a 1 byte tag (using *shadow memory*), +uses *redzones* to find buffer-overflows and +*quarantine* to find use-after-free. +The redzones, the quarantine, and, to a less extent, the shadow, are the +sources of AddressSanitizer's memory overhead. +See the `AddressSanitizer paper`_ for details. + +AArch64 has the `Address Tagging`_ (or top-byte-ignore, TBI), a hardware feature that allows +software to use 8 most significant bits of a 64-bit pointer as +a tag. HWASAN uses `Address Tagging`_ +to implement a memory safety tool, similar to :doc:`AddressSanitizer`, +but with smaller memory overhead and slightly different (mostly better) +accuracy guarantees. + +Algorithm +========= +* Every heap/stack/global memory object is forcibly aligned by `N` bytes + (`N` is e.g. 16 or 64). We call `N` the **granularity** of tagging. +* For every such object a random `K`-bit tag `T` is chosen (`K` is e.g. 4 or 8) +* The pointer to the object is tagged with `T`. +* The memory for the object is also tagged with `T` + (using a `N=>1` shadow memory) +* Every load and store is instrumented to read the memory tag and compare it + with the pointer tag, exception is raised on tag mismatch. + +Instrumentation +=============== + +Memory Accesses +--------------- +All memory accesses are prefixed with an inline instruction sequence that +verifies the tags. Currently, the following sequence is used: + + +.. code-block:: asm + + // int foo(int *a) { return *a; } + // clang -O2 --target=aarch64-linux -fsanitize=hwaddress -c load.c + foo: + 0: 08 dc 44 d3 ubfx x8, x0, #4, #52 // shadow address + 4: 08 01 40 39 ldrb w8, [x8] // load shadow + 8: 09 fc 78 d3 lsr x9, x0, #56 // address tag + c: 3f 01 08 6b cmp w9, w8 // compare tags + 10: 61 00 00 54 b.ne #12 // jump on mismatch + 14: 00 00 40 b9 ldr w0, [x0] // original load + 18: c0 03 5f d6 ret + 1c: 40 20 40 d4 hlt #0x102 // halt + + +Alternatively, memory accesses are prefixed with a function call. + +Heap +---- + +Tagging the heap memory/pointers is done by `malloc`. +This can be based on any malloc that forces all objects to be N-aligned. +`free` tags the memory with a different tag. + +Stack +----- + +Stack frames are instrumented by aligning all non-promotable allocas +by `N` and tagging stack memory in function prologue and epilogue. + +Tags for different allocas in one function are **not** generated +independently; doing that in a function with `M` allocas would require +maintaining `M` live stack pointers, significantly increasing register +pressure. Instead we generate a single base tag value in the prologue, +and build the tag for alloca number `M` as `ReTag(BaseTag, M)`, where +ReTag can be as simple as exclusive-or with constant `M`. + +Stack instrumentation is expected to be a major source of overhead, +but could be optional. + +Globals +------- + +TODO: details. + +Error reporting +--------------- + +Errors are generated by the `HLT` instruction and are handled by a signal handler. + +Attribute +--------- + +HWASAN uses its own LLVM IR Attribute `sanitize_hwaddress` and a matching +C function attribute. An alternative would be to re-use ASAN's attribute +`sanitize_address`. The reasons to use a separate attribute are: + + * Users may need to disable ASAN but not HWASAN, or vise versa, + because the tools have different trade-offs and compatibility issues. + * LLVM (ideally) does not use flags to decide which pass is being used, + ASAN or HWASAN are being applied, based on the function attributes. + +This does mean that users of HWASAN may need to add the new attribute +to the code that already uses the old attribute. + + +Comparison with AddressSanitizer +================================ + +HWASAN: + * Is less portable than :doc:`AddressSanitizer` + as it relies on hardware `Address Tagging`_ (AArch64). + Address Tagging can be emulated with compiler instrumentation, + but it will require the instrumentation to remove the tags before + any load or store, which is infeasible in any realistic environment + that contains non-instrumented code. + * May have compatibility problems if the target code uses higher + pointer bits for other purposes. + * May require changes in the OS kernels (e.g. Linux seems to dislike + tagged pointers passed from address space: + https://www.kernel.org/doc/Documentation/arm64/tagged-pointers.txt). + * **Does not require redzones to detect buffer overflows**, + but the buffer overflow detection is probabilistic, with roughly + `(2**K-1)/(2**K)` probability of catching a bug. + * **Does not require quarantine to detect heap-use-after-free, + or stack-use-after-return**. + The detection is similarly probabilistic. + +The memory overhead of HWASAN is expected to be much smaller +than that of AddressSanitizer: +`1/N` extra memory for the shadow +and some overhead due to `N`-aligning all objects. + + +Related Work +============ +* `SPARC ADI`_ implements a similar tool mostly in hardware. +* `Effective and Efficient Memory Protection Using Dynamic Tainting`_ discusses + similar approaches ("lock & key"). +* `Watchdog`_ discussed a heavier, but still somewhat similar + "lock & key" approach. +* *TODO: add more "related work" links. Suggestions are welcome.* + + +.. _Watchdog: http://www.cis.upenn.edu/acg/papers/isca12_watchdog.pdf +.. _Effective and Efficient Memory Protection Using Dynamic Tainting: https://www.cc.gatech.edu/~orso/papers/clause.doudalis.orso.prvulovic.pdf +.. _SPARC ADI: https://lazytyped.blogspot.com/2017/09/getting-started-with-adi.html +.. _AddressSanitizer paper: https://www.usenix.org/system/files/conference/atc12/atc12-final39.pdf +.. _Address Tagging: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.den0024a/ch12s05s01.html + diff --git a/docs/InternalsManual.rst b/docs/InternalsManual.rst index 058c63f0afd638e8b844fa48672095807ff9c218..b23d31468d0e7eef5248ed6b7002676a7265c56c 100644 --- a/docs/InternalsManual.rst +++ b/docs/InternalsManual.rst @@ -1823,7 +1823,7 @@ Note that setting this member to 1 will opt out of common attribute semantic handling, requiring extra implementation efforts to ensure the attribute appertains to the appropriate subject, etc. -If the attribute should not be propagated from from a template declaration to an +If the attribute should not be propagated from a template declaration to an instantiation of the template, set the ``Clone`` member to 0. By default, all attributes will be cloned to template instantiations. diff --git a/docs/JSONCompilationDatabase.rst b/docs/JSONCompilationDatabase.rst index 8631e8365cead5018c446fad7a8a4e7f710d4988..1f3441b033d40dabbc12614c4ce015ebbedf0940 100644 --- a/docs/JSONCompilationDatabase.rst +++ b/docs/JSONCompilationDatabase.rst @@ -91,3 +91,9 @@ The convention is to name the file compile\_commands.json and put it at the top of the build directory. Clang tools are pointed to the top of the build directory to detect the file and use the compilation database to parse C++ code in the source tree. + +Alternatives +============ +For simple projects, Clang tools also recognize a compile_flags.txt file. +This should contain one flag per line. The same flags will be used to compile +any file. diff --git a/docs/LanguageExtensions.rst b/docs/LanguageExtensions.rst index 652145f66fc99f9c30ec7c1db8db4ae361fbd3ca..bb9b4c11be5f6808236c74ca162aaa3ad62be534 100644 --- a/docs/LanguageExtensions.rst +++ b/docs/LanguageExtensions.rst @@ -139,6 +139,35 @@ and following ``__`` (double underscore) to avoid interference from a macro with the same name. For instance, ``gnu::__const__`` can be used instead of ``gnu::const``. +``__has_c_attribute`` +--------------------- + +This function-like macro takes a single argument that is the name of an +attribute exposed with the double square-bracket syntax in C mode. The argument +can either be a single identifier or a scoped identifier. If the attribute is +supported, a nonzero value is returned. If the attribute is not supported by the +current compilation target, this macro evaluates to 0. It can be used like this: + +.. code-block:: c + + #ifndef __has_c_attribute // Optional of course. + #define __has_c_attribute(x) 0 // Compatibility with non-clang compilers. + #endif + + ... + #if __has_c_attribute(fallthrough) + #define FALLTHROUGH [[fallthrough]] + #else + #define FALLTHROUGH + #endif + ... + +The attribute identifier (but not scope) can also be specified with a preceding +and following ``__`` (double underscore) to avoid interference from a macro with +the same name. For instance, ``gnu::__const__`` can be used instead of +``gnu::const``. + + ``__has_attribute`` ------------------- @@ -436,6 +465,49 @@ const_cast no no no no See also :ref:`langext-__builtin_shufflevector`, :ref:`langext-__builtin_convertvector`. +Half-Precision Floating Point +============================= + +Clang supports two half-precision (16-bit) floating point types: ``__fp16`` and +``_Float16``. ``__fp16`` is defined in the ARM C Language Extensions (`ACLE +`_) +and ``_Float16`` in ISO/IEC TS 18661-3:2015. + +``__fp16`` is a storage and interchange format only. This means that values of +``__fp16`` promote to (at least) float when used in arithmetic operations. +There are two ``__fp16`` formats. Clang supports the IEEE 754-2008 format and +not the ARM alternative format. + +ISO/IEC TS 18661-3:2015 defines C support for additional floating point types. +``_FloatN`` is defined as a binary floating type, where the N suffix denotes +the number of bits and is 16, 32, 64, or greater and equal to 128 and a +multiple of 32. Clang supports ``_Float16``. The difference from ``__fp16`` is +that arithmetic on ``_Float16`` is performed in half-precision, thus it is not +a storage-only format. ``_Float16`` is available as a source language type in +both C and C++ mode. + +It is recommended that portable code use the ``_Float16`` type because +``__fp16`` is an ARM C-Language Extension (ACLE), whereas ``_Float16`` is +defined by the C standards committee, so using ``_Float16`` will not prevent +code from being ported to architectures other than Arm. Also, ``_Float16`` +arithmetic and operations will directly map on half-precision instructions when +they are available (e.g. Armv8.2-A), avoiding conversions to/from +single-precision, and thus will result in more performant code. If +half-precision instructions are unavailable, values will be promoted to +single-precision, similar to the semantics of ``__fp16`` except that the +results will be stored in single-precision. + +In an arithmetic operation where one operand is of ``__fp16`` type and the +other is of ``_Float16`` type, the ``_Float16`` type is first converted to +``__fp16`` type and then the operation is completed as if both operands were of +``__fp16`` type. + +To define a ``_Float16`` literal, suffix ``f16`` can be appended to the compile-time +constant declaration. There is no default argument promotion for ``_Float16``; this +applies to the standard floating types only. As a consequence, for example, an +explicit cast is required for printing a ``_Float16`` value (there is no string +format specifier for ``_Float16``). + Messages on ``deprecated`` and ``unavailable`` Attributes ========================================================= @@ -1024,6 +1096,11 @@ The following type trait primitives are supported by Clang: * ``__is_constructible`` (MSVC 2013, clang) * ``__is_nothrow_constructible`` (MSVC 2013, clang) * ``__is_assignable`` (MSVC 2015, clang) +* ``__reference_binds_to_temporary(T, U)`` (Clang): Determines whether a + reference of type ``T`` bound to an expression of type ``U`` would bind to a + materialized temporary object. If ``T`` is not a reference type the result + is false. Note this trait will also return false when the initialization of + ``T`` from ``U`` is ill-formed. Blocks ====== @@ -1114,12 +1191,14 @@ Automatic reference counting Clang provides support for :doc:`automated reference counting ` in Objective-C, which eliminates the need -for manual ``retain``/``release``/``autorelease`` message sends. There are two +for manual ``retain``/``release``/``autorelease`` message sends. There are three feature macros associated with automatic reference counting: ``__has_feature(objc_arc)`` indicates the availability of automated reference counting in general, while ``__has_feature(objc_arc_weak)`` indicates that automated reference counting also includes support for ``__weak`` pointers to -Objective-C objects. +Objective-C objects. ``__has_feature(objc_arc_fields)`` indicates that C structs +are allowed to have fields that are pointers to Objective-C objects managed by +automatic reference counting. .. _objc-fixed-enum: @@ -2648,3 +2727,11 @@ The ``#pragma clang section`` directive obeys the following rules: * The decision about which section-kind applies to each global is taken in the back-end. Once the section-kind is known, appropriate section name, as specified by the user using ``#pragma clang section`` directive, is applied to that global. + +Specifying Linker Options on ELF Targets +======================================== + +The ``#pragma comment(lib, ...)`` directive is supported on all ELF targets. +The second parameter is the library name (without the traditional Unix prefix of +``lib``). This allows you to provide an implicit link of dependent libraries. + diff --git a/docs/LibASTMatchersReference.html b/docs/LibASTMatchersReference.html index b8d4ed557b1a9b65fdfb5f67a0ed81846a8b1938..0a9fcceb0b56984e252eb5c8a19e7792772707a0 100644 --- a/docs/LibASTMatchersReference.html +++ b/docs/LibASTMatchersReference.html @@ -346,6 +346,15 @@ Example matches Foo (Additions) +Matcher<Decl>objcCategoryImplDeclMatcher<ObjCCategoryImplDecl>... +
Matches Objective-C category definitions.
+
+Example matches Foo (Additions)
+  @implementation Foo (Additions)
+  @end
+
+ + Matcher<Decl>objcImplementationDeclMatcher<ObjCImplementationDecl>...
Matches Objective-C implementation declarations.
 
@@ -691,7 +700,7 @@ Example matches x.y() and y()
 Given
   switch(a) { case 42: break; default: break; }
 caseStmt()
-  matches 'case 42: break;'.
+  matches 'case 42:'.
 
@@ -732,7 +741,7 @@ Example match: {1}, (1, 2) Matcher<Stmt>compoundStmtMatcher<CompoundStmt>...
Matches compound statements.
 
-Example matches '{}' and '{{}}'in 'for (;;) {{}}'
+Example matches '{}' and '{{}}' in 'for (;;) {{}}'
   for (;;) {{}}
 
@@ -1019,7 +1028,7 @@ declStmt() Given switch(a) { case 42: break; default: break; } defaultStmt() - matches 'default: break;'. + matches 'default:'. @@ -1188,9 +1197,9 @@ Example: Given materializeTemporaryExpr() matches 'f()' in these statements T u(f()); g(f()); + f().func(); but does not match f(); - f().func(); @@ -1216,6 +1225,24 @@ nullStmt() +Matcher<Stmt>objcCatchStmtMatcher<ObjCAtCatchStmt>... +
Matches Objective-C @catch statements.
+
+Example matches @catch
+  @try {}
+  @catch (...) {}
+
+ + +Matcher<Stmt>objcFinallyStmtMatcher<ObjCAtFinallyStmt>... +
Matches Objective-C @finally statements.
+
+Example matches @finally
+  @try {}
+  @finally {}
+
+ + Matcher<Stmt>objcMessageExprMatcher<ObjCMessageExpr>...
Matches ObjectiveC Message invocation expressions.
 
@@ -1227,6 +1254,22 @@ NSString's "alloc". This matcher should match both message sends.
 
+Matcher<Stmt>objcThrowStmtMatcher<ObjCAtThrowStmt>... +
Matches Objective-C statements.
+
+Example matches @throw obj;
+
+ + +Matcher<Stmt>objcTryStmtMatcher<ObjCAtTryStmt>... +
Matches Objective-C @try statements.
+
+Example matches @try
+  @try {}
+  @catch (...) {}
+
+ + Matcher<Stmt>opaqueValueExprMatcher<OpaqueValueExpr>...
Matches opaque value expressions. They are used as helpers
 to reference another expressions and can be met
@@ -1326,7 +1369,7 @@ substNonTypeTemplateParmExpr()
 Given
   switch(a) { case 42: break; default: break; }
 switchCase()
-  matches 'case 42: break;' and 'default: break;'.
+  matches 'case 42:' and 'default:'.
 
@@ -1883,7 +1926,11 @@ Example matches a || b (matcher = binaryOperator(hasOperatorName("||"))) -Matcher<CXXBoolLiteralExpr>equalsValueT Value +Matcher<CXXBoolLiteralExpr>equalsbool Value +

+
+
+Matcher<CXXBoolLiteralExpr>equalsconst ValueT  Value
 
Matches literals that are equal to the given value of type ValueT.
 
 Given
@@ -1909,10 +1956,6 @@ Usable as: Matcher<CXXBoolLiteralExpr>equalsbool Value
-

-
-
 Matcher<CXXBoolLiteralExpr>equalsdouble Value
 

 
@@ -2232,6 +2275,16 @@ Given
 
+Matcher<CXXNewExpr>isArray +
Matches array new expressions.
+
+Given:
+  MyClass *p1 = new MyClass[10];
+cxxNewExpr(isArray())
+  matches the expression 'new MyClass[10]'.
+
+ + Matcher<CXXOperatorCallExpr>hasOverloadedOperatorNameStringRef Name
Matches overloaded operator names.
 
@@ -2253,6 +2306,15 @@ Usable as: Matcher<CXXRecordDecl>hasDefinition
+
Matches a class declaration that is defined.
+
+Example matches x (matcher = cxxRecordDecl(hasDefinition()))
+class x {};
+class y;
+
+ + Matcher<CXXRecordDecl>isDerivedFromstd::string BaseName
Overloaded method as shortcut for isDerivedFrom(hasName(...)).
 
@@ -2314,6 +2376,8 @@ Given template <typename T> class X {}; class A {}; X<A> x; or template <typename T> class X {}; class A {}; template class X<A>; +or + template <typename T> class X {}; class A {}; extern template class X<A>; cxxRecordDecl(hasName("::X"), isTemplateInstantiation()) matches the template instantiation of X<A>. @@ -2346,7 +2410,11 @@ Example: matches the implicit cast around 0
-Matcher<CharacterLiteral>equalsValueT Value +Matcher<CharacterLiteral>equalsbool Value +

+
+
+Matcher<CharacterLiteral>equalsconst ValueT  Value
 
Matches literals that are equal to the given value of type ValueT.
 
 Given
@@ -2372,10 +2440,6 @@ Usable as: Matcher<CharacterLiteral>equalsbool Value
-

-
-
 Matcher<CharacterLiteral>equalsdouble Value
 

 
@@ -2582,6 +2646,15 @@ designatorCountIs(2)
 
+Matcher<EnumDecl>isScoped +
Matches C++11 scoped enum declaration.
+
+Example matches Y (matcher = enumDecl(isScoped()))
+enum X {};
+enum class Y {};
+
+ + Matcher<FieldDecl>hasBitWidthunsigned Width
Matches non-static data members that are bit-fields of the specified
 bit width.
@@ -2610,7 +2683,7 @@ fieldDecl(isBitField())
 
-Matcher<FloatingLiteral>equalsValueT Value +Matcher<FloatingLiteral>equalsconst ValueT Value
Matches literals that are equal to the given value of type ValueT.
 
 Given
@@ -2678,6 +2751,15 @@ Usable as: Matcher<FunctionDecl>hasTrailingReturn
+
Matches a function declared with a trailing return type.
+
+Example matches Y (matcher = functionDecl(hasTrailingReturn()))
+int X() {}
+auto Y() -> int {}
+
+ + Matcher<FunctionDecl>isConstexpr
Matches constexpr variable and function declarations.
 
@@ -2702,8 +2784,8 @@ functionDecl(isDefaulted())
 
-Matcher<FunctionDecl>isDefinition -
Matches if a declaration has a body attached.
+Matcher<FunctionDecl>isDefinition
+
Matches if a declaration has a body attached.
 
 Example matches A, va, fa
   class A {};
@@ -2712,8 +2794,15 @@ Example matches A, va, fa
   extern int vb;  Doesn't match, as it doesn't define the variable.
   void fa() {}
   void fb();  Doesn't match, as it has no body.
+  @interface X
+  - (void)ma; Doesn't match, interface is declaration.
+  @end
+  @implementation X
+  - (void)ma {}
+  @end
 
-Usable as: Matcher<TagDecl>, Matcher<VarDecl>, Matcher<FunctionDecl>
+Usable as: Matcher<TagDecl>, Matcher<VarDecl>, Matcher<FunctionDecl>,
+  Matcher<ObjCMethodDecl>
 
@@ -2741,6 +2830,7 @@ functionDecl(isExplicitTemplateSpecialization()) Usable as: Matcher<FunctionDecl>, Matcher<VarDecl>, Matcher<CXXRecordDecl>
+ Matcher<FunctionDecl>isExternC
Matches extern "C" function or variable declarations.
 
@@ -2757,6 +2847,7 @@ varDecl(isExternC())
   matches the declaration of x and y, but not the declaration of z.
 
+ Matcher<FunctionDecl>isInline
Matches function and namespace declarations that are marked with
 the inline keyword.
@@ -2772,6 +2863,20 @@ namespaceDecl(isInline()) will match n::m.
 
+Matcher<FunctionDecl>isNoReturn +
Matches FunctionDecls that have a noreturn attribute.
+
+Given
+  void nope();
+  [[noreturn]] void a();
+  __attribute__((noreturn)) void b();
+  struct c { [[noreturn]] c(); };
+functionDecl(isNoReturn())
+  matches all of those except
+  void nope();
+
+ + Matcher<FunctionDecl>isNoThrow
Matches functions that have a non-throwing exception specification.
 
@@ -2810,6 +2915,8 @@ Given
   template <typename T> class X {}; class A {}; X<A> x;
 or
   template <typename T> class X {}; class A {}; template class X<A>;
+or
+  template <typename T> class X {}; class A {}; extern template class X<A>;
 cxxRecordDecl(hasName("::X"), isTemplateInstantiation())
   matches the template instantiation of X<A>.
 
@@ -2846,11 +2953,11 @@ Given
   void j(int i);
   void k(int x, int y, int z, ...);
 functionDecl(parameterCountIs(2))
-  matches void g(int i, int j) {}
+  matches g and h
 functionProtoType(parameterCountIs(2))
-  matches void h(int i, int j)
+  matches g and h
 functionProtoType(parameterCountIs(3))
-  matches void k(int x, int y, int z, ...);
+  matches k
 
@@ -2896,15 +3003,19 @@ Given void j(int i); void k(int x, int y, int z, ...); functionDecl(parameterCountIs(2)) - matches void g(int i, int j) {} + matches g and h functionProtoType(parameterCountIs(2)) - matches void h(int i, int j) + matches g and h functionProtoType(parameterCountIs(3)) - matches void k(int x, int y, int z, ...); + matches k
-Matcher<IntegerLiteral>equalsValueT Value +Matcher<IntegerLiteral>equalsbool Value +

+
+
+Matcher<IntegerLiteral>equalsconst ValueT  Value
 
Matches literals that are equal to the given value of type ValueT.
 
 Given
@@ -2930,10 +3041,6 @@ Usable as: Matcher<IntegerLiteral>equalsbool Value
-

-
-
 Matcher<IntegerLiteral>equalsdouble Value
 

 
@@ -2979,7 +3086,7 @@ void f() {}
 
-Matcher<NamedDecl>hasNamestd::string Name +Matcher<NamedDecl>hasNameconst std::string Name
Matches NamedDecl nodes that have the specified name.
 
 Supports specifying enclosing namespaces or classes by prefixing the name
@@ -3110,6 +3217,37 @@ a substring matched by the given RegExp.
 
+Matcher<ObjCMethodDecl>isDefinition +
Matches if a declaration has a body attached.
+
+Example matches A, va, fa
+  class A {};
+  class B;  Doesn't match, as it has no body.
+  int va;
+  extern int vb;  Doesn't match, as it doesn't define the variable.
+  void fa() {}
+  void fb();  Doesn't match, as it has no body.
+  @interface X
+  - (void)ma; Doesn't match, interface is declaration.
+  @end
+  @implementation X
+  - (void)ma {}
+  @end
+
+Usable as: Matcher<TagDecl>, Matcher<VarDecl>, Matcher<FunctionDecl>,
+  Matcher<ObjCMethodDecl>
+
+ + +Matcher<ParmVarDecl>hasDefaultArgument +
Matches a declaration that has default arguments.
+
+Example matches y (matcher = parmVarDecl(hasDefaultArgument()))
+void x(int val) {}
+void y(int val = 0) {}
+
+ + Matcher<QualType>asStringstd::string Name
Matches if the matched type is represented by the given string.
 
@@ -3389,8 +3527,15 @@ Example matches A, va, fa
   extern int vb;  Doesn't match, as it doesn't define the variable.
   void fa() {}
   void fb();  Doesn't match, as it has no body.
+  @interface X
+  - (void)ma; Doesn't match, interface is declaration.
+  @end
+  @implementation X
+  - (void)ma {}
+  @end
 
-Usable as: Matcher<TagDecl>, Matcher<VarDecl>, Matcher<FunctionDecl>
+Usable as: Matcher<TagDecl>, Matcher<VarDecl>, Matcher<FunctionDecl>,
+  Matcher<ObjCMethodDecl>
 
@@ -3402,7 +3547,7 @@ an arbitrary precision integer. 'Value' must be euqal to the canonical representation of that integral value in base 10. Given - template<int T> struct A {}; + template<int T> struct C {}; C<42> c; classTemplateSpecializationDecl( hasAnyTemplateArgument(equalsIntegralValue("42"))) @@ -3414,7 +3559,7 @@ classTemplateSpecializationDecl(
Matches a TemplateArgument that is an integral value.
 
 Given
-  template<int T> struct A {};
+  template<int T> struct C {};
   C<42> c;
 classTemplateSpecializationDecl(
   hasAnyTemplateArgument(isIntegral()))
@@ -3652,8 +3797,15 @@ Example matches A, va, fa
   extern int vb;  Doesn't match, as it doesn't define the variable.
   void fa() {}
   void fb();  Doesn't match, as it has no body.
+  @interface X
+  - (void)ma; Doesn't match, interface is declaration.
+  @end
+  @implementation X
+  - (void)ma {}
+  @end
 
-Usable as: Matcher<TagDecl>, Matcher<VarDecl>, Matcher<FunctionDecl>
+Usable as: Matcher<TagDecl>, Matcher<VarDecl>, Matcher<FunctionDecl>,
+  Matcher<ObjCMethodDecl>
 
@@ -3683,6 +3835,7 @@ functionDecl(isExplicitTemplateSpecialization()) Usable as: Matcher<FunctionDecl>, Matcher<VarDecl>, Matcher<CXXRecordDecl> + Matcher<VarDecl>isExternC
Matches extern "C" function or variable declarations.
 
@@ -3699,6 +3852,7 @@ varDecl(isExternC())
   matches the declaration of x and y, but not the declaration of z.
 
+ Matcher<VarDecl>isStaticStorageClass
Matches variablefunction declarations that have "static" storage
 class specifier ("static" keyword) written in the source.
@@ -3723,6 +3877,8 @@ Given
   template <typename T> class X {}; class A {}; X<A> x;
 or
   template <typename T> class X {}; class A {}; template class X<A>;
+or
+  template <typename T> class X {}; class A {}; extern template class X<A>;
 cxxRecordDecl(hasName("::X"), isTemplateInstantiation())
   matches the template instantiation of X<A>.
 
@@ -3832,10 +3988,11 @@ Usable as: Any Matcher
 
Matches AST nodes that have descendant AST nodes that match the
 provided matcher.
 
-Example matches X, A, B, C
+Example matches X, A, A::X, B, B::C, B::C::X
   (matcher = cxxRecordDecl(forEachDescendant(cxxRecordDecl(hasName("X")))))
-  class X {};  Matches X, because X::X is a class of name X inside X.
-  class A { class X {}; };
+  class X {};
+  class A { class X {}; };  Matches A, because A::X is a class of name
+                            X inside A.
   class B { class C { class X {}; }; };
 
 DescendantT must be an AST base type.
@@ -3858,10 +4015,11 @@ Usable as: Any Matcher
 
Matches AST nodes that have child AST nodes that match the
 provided matcher.
 
-Example matches X, Y
+Example matches X, Y, Y::X, Z::Y, Z::Y::X
   (matcher = cxxRecordDecl(forEach(cxxRecordDecl(hasName("X")))
-  class X {};  Matches X, because X::X is a class of name X inside X.
-  class Y { class X {}; };
+  class X {};
+  class Y { class X {}; };  Matches Y, because Y::X is a class of name X
+                            inside Y.
   class Z { class Y { class X {}; }; };  Does not match Z.
 
 ChildT must be an AST base type.
@@ -3964,7 +4122,7 @@ Example 2 (conditional binary operator): matches opaqueValueExpr(condition)
 
-Matcher<AddrLabelExpr>hasDeclarationMatcher<Decl> InnerMatcher +Matcher<AddrLabelExpr>hasDeclarationconst Matcher<Decl> InnerMatcher
Matches a node if the declaration associated with that node
 matches the given matcher.
 
@@ -3975,8 +4133,17 @@ The associated declaration is:
 - for CXXConstructExpr, the declaration of the constructor
 - for CXXNewExpr, the declaration of the operator new
 
-Also usable as Matcher<T> for any T supporting the getDecl() member
-function. e.g. various subtypes of clang::Type and various expressions.
+For type nodes, hasDeclaration will generally match the declaration of the
+sugared type. Given
+  class X {};
+  typedef X Y;
+  Y y;
+in varDecl(hasType(hasDeclaration(decl()))) the decl will match the
+typedefDecl. A common use case is to match the underlying, desugared type.
+This can be achieved by using the hasUnqualifiedDesugaredType matcher:
+  varDecl(hasType(hasUnqualifiedDesugaredType(
+      recordType(hasDeclaration(decl())))))
+In this matcher, the decl will match the CXXRecordDecl of class X.
 
 Usable as: Matcher<AddrLabelExpr>, Matcher<CallExpr>,
   Matcher<CXXConstructExpr>, Matcher<CXXNewExpr>, Matcher<DeclRefExpr>,
@@ -4099,7 +4266,7 @@ Usable as: Matcher<BinaryOperator>hasEitherOperandMatcher<Expr>  InnerMatcher
+Matcher<BinaryOperator>hasEitherOperandconst Matcher<Expr>  InnerMatcher
 
Matches if either the left hand side or the right hand side of a
 binary operator matches.
 
@@ -4196,7 +4363,7 @@ Example matches y in x(y)
-Matcher<CXXConstructExpr>hasDeclarationMatcher<Decl> InnerMatcher +Matcher<CXXConstructExpr>hasDeclarationconst Matcher<Decl> InnerMatcher
Matches a node if the declaration associated with that node
 matches the given matcher.
 
@@ -4207,8 +4374,17 @@ The associated declaration is:
 - for CXXConstructExpr, the declaration of the constructor
 - for CXXNewExpr, the declaration of the operator new
 
-Also usable as Matcher<T> for any T supporting the getDecl() member
-function. e.g. various subtypes of clang::Type and various expressions.
+For type nodes, hasDeclaration will generally match the declaration of the
+sugared type. Given
+  class X {};
+  typedef X Y;
+  Y y;
+in varDecl(hasType(hasDeclaration(decl()))) the decl will match the
+typedefDecl. A common use case is to match the underlying, desugared type.
+This can be achieved by using the hasUnqualifiedDesugaredType matcher:
+  varDecl(hasType(hasUnqualifiedDesugaredType(
+      recordType(hasDeclaration(decl())))))
+In this matcher, the decl will match the CXXRecordDecl of class X.
 
 Usable as: Matcher<AddrLabelExpr>, Matcher<CallExpr>,
   Matcher<CXXConstructExpr>, Matcher<CXXNewExpr>, Matcher<DeclRefExpr>,
@@ -4320,7 +4496,7 @@ matches 'a' in
 Example matches y.x()
   (matcher = cxxMemberCallExpr(on(hasType(cxxRecordDecl(hasName("Y"))))))
   class Y { public: void x(); };
-  void z() { Y y; y.x(); }",
+  void z() { Y y; y.x(); }
 
 FIXME: Overload to allow directly matching types?
 
@@ -4380,7 +4556,17 @@ Example matches A() in the last line
-Matcher<CXXNewExpr>hasDeclarationMatcher<Decl> InnerMatcher +Matcher<CXXNewExpr>hasArraySizeMatcher<Expr> InnerMatcher +
Matches array new expressions with a given array size.
+
+Given:
+  MyClass *p1 = new MyClass[10];
+cxxNewExpr(hasArraySize(intgerLiteral(equals(10))))
+  matches the expression 'new MyClass[10]'.
+
+ + +Matcher<CXXNewExpr>hasDeclarationconst Matcher<Decl> InnerMatcher
Matches a node if the declaration associated with that node
 matches the given matcher.
 
@@ -4391,8 +4577,17 @@ The associated declaration is:
 - for CXXConstructExpr, the declaration of the constructor
 - for CXXNewExpr, the declaration of the operator new
 
-Also usable as Matcher<T> for any T supporting the getDecl() member
-function. e.g. various subtypes of clang::Type and various expressions.
+For type nodes, hasDeclaration will generally match the declaration of the
+sugared type. Given
+  class X {};
+  typedef X Y;
+  Y y;
+in varDecl(hasType(hasDeclaration(decl()))) the decl will match the
+typedefDecl. A common use case is to match the underlying, desugared type.
+This can be achieved by using the hasUnqualifiedDesugaredType matcher:
+  varDecl(hasType(hasUnqualifiedDesugaredType(
+      recordType(hasDeclaration(decl())))))
+In this matcher, the decl will match the CXXRecordDecl of class X.
 
 Usable as: Matcher<AddrLabelExpr>, Matcher<CallExpr>,
   Matcher<CXXConstructExpr>, Matcher<CXXNewExpr>, Matcher<DeclRefExpr>,
@@ -4515,7 +4710,7 @@ Example matches y in x(y)
 
-Matcher<CallExpr>hasDeclarationMatcher<Decl> InnerMatcher +Matcher<CallExpr>hasDeclarationconst Matcher<Decl> InnerMatcher
Matches a node if the declaration associated with that node
 matches the given matcher.
 
@@ -4526,8 +4721,17 @@ The associated declaration is:
 - for CXXConstructExpr, the declaration of the constructor
 - for CXXNewExpr, the declaration of the operator new
 
-Also usable as Matcher<T> for any T supporting the getDecl() member
-function. e.g. various subtypes of clang::Type and various expressions.
+For type nodes, hasDeclaration will generally match the declaration of the
+sugared type. Given
+  class X {};
+  typedef X Y;
+  Y y;
+in varDecl(hasType(hasDeclaration(decl()))) the decl will match the
+typedefDecl. A common use case is to match the underlying, desugared type.
+This can be achieved by using the hasUnqualifiedDesugaredType matcher:
+  varDecl(hasType(hasUnqualifiedDesugaredType(
+      recordType(hasDeclaration(decl())))))
+In this matcher, the decl will match the CXXRecordDecl of class X.
 
 Usable as: Matcher<AddrLabelExpr>, Matcher<CallExpr>,
   Matcher<CXXConstructExpr>, Matcher<CXXNewExpr>, Matcher<DeclRefExpr>,
@@ -4551,7 +4755,18 @@ caseStmt(hasCaseConstant(integerLiteral()))
 
 
 Matcher<CastExpr>hasSourceExpressionMatcher<Expr> InnerMatcher
-

+
Matches if the cast's source expression
+or opaque value's source expression matches the given matcher.
+
+Example 1: matches "a string"
+(matcher = castExpr(hasSourceExpression(cxxConstructExpr())))
+class URL { URL(string); };
+URL url = "a string";
+
+Example 2: matches 'b' (matcher =
+opaqueValueExpr(hasSourceExpression(implicitCastExpr(declRefExpr())))
+int a = b ?: 1;
+
Matcher<ClassTemplateSpecializationDecl>hasAnyTemplateArgumentMatcher<TemplateArgument> InnerMatcher @@ -4597,7 +4812,7 @@ Given A<bool, int> b; A<int, bool> c; - template<typename T> f() {}; + template<typename T> void f() {} void func() { f<int>(); }; classTemplateSpecializationDecl(hasTemplateArgument( 1, refersToType(asString("int")))) @@ -4656,7 +4871,7 @@ with compoundStmt()
-Matcher<DeclRefExpr>hasDeclarationMatcher<Decl> InnerMatcher +Matcher<DeclRefExpr>hasDeclarationconst Matcher<Decl> InnerMatcher
Matches a node if the declaration associated with that node
 matches the given matcher.
 
@@ -4667,8 +4882,17 @@ The associated declaration is:
 - for CXXConstructExpr, the declaration of the constructor
 - for CXXNewExpr, the declaration of the operator new
 
-Also usable as Matcher<T> for any T supporting the getDecl() member
-function. e.g. various subtypes of clang::Type and various expressions.
+For type nodes, hasDeclaration will generally match the declaration of the
+sugared type. Given
+  class X {};
+  typedef X Y;
+  Y y;
+in varDecl(hasType(hasDeclaration(decl()))) the decl will match the
+typedefDecl. A common use case is to match the underlying, desugared type.
+This can be achieved by using the hasUnqualifiedDesugaredType matcher:
+  varDecl(hasType(hasUnqualifiedDesugaredType(
+      recordType(hasDeclaration(decl())))))
+In this matcher, the decl will match the CXXRecordDecl of class X.
 
 Usable as: Matcher<AddrLabelExpr>, Matcher<CallExpr>,
   Matcher<CXXConstructExpr>, Matcher<CXXNewExpr>, Matcher<DeclRefExpr>,
@@ -4820,7 +5044,7 @@ declaration of d.
 
-Matcher<EnumType>hasDeclarationMatcher<Decl> InnerMatcher +Matcher<EnumType>hasDeclarationconst Matcher<Decl> InnerMatcher
Matches a node if the declaration associated with that node
 matches the given matcher.
 
@@ -4831,8 +5055,17 @@ The associated declaration is:
 - for CXXConstructExpr, the declaration of the constructor
 - for CXXNewExpr, the declaration of the operator new
 
-Also usable as Matcher<T> for any T supporting the getDecl() member
-function. e.g. various subtypes of clang::Type and various expressions.
+For type nodes, hasDeclaration will generally match the declaration of the
+sugared type. Given
+  class X {};
+  typedef X Y;
+  Y y;
+in varDecl(hasType(hasDeclaration(decl()))) the decl will match the
+typedefDecl. A common use case is to match the underlying, desugared type.
+This can be achieved by using the hasUnqualifiedDesugaredType matcher:
+  varDecl(hasType(hasUnqualifiedDesugaredType(
+      recordType(hasDeclaration(decl())))))
+In this matcher, the decl will match the CXXRecordDecl of class X.
 
 Usable as: Matcher<AddrLabelExpr>, Matcher<CallExpr>,
   Matcher<CXXConstructExpr>, Matcher<CXXNewExpr>, Matcher<DeclRefExpr>,
@@ -5096,7 +5329,7 @@ Given
   A<bool, int> b;
   A<int, bool> c;
 
-  template<typename T> f() {};
+  template<typename T> void f() {}
   void func() { f<int>(); };
 classTemplateSpecializationDecl(hasTemplateArgument(
     1, refersToType(asString("int"))))
@@ -5168,7 +5401,7 @@ FIXME: Unit test this matcher
 
-Matcher<InjectedClassNameType>hasDeclarationMatcher<Decl> InnerMatcher +Matcher<InjectedClassNameType>hasDeclarationconst Matcher<Decl> InnerMatcher
Matches a node if the declaration associated with that node
 matches the given matcher.
 
@@ -5179,8 +5412,17 @@ The associated declaration is:
 - for CXXConstructExpr, the declaration of the constructor
 - for CXXNewExpr, the declaration of the operator new
 
-Also usable as Matcher<T> for any T supporting the getDecl() member
-function. e.g. various subtypes of clang::Type and various expressions.
+For type nodes, hasDeclaration will generally match the declaration of the
+sugared type. Given
+  class X {};
+  typedef X Y;
+  Y y;
+in varDecl(hasType(hasDeclaration(decl()))) the decl will match the
+typedefDecl. A common use case is to match the underlying, desugared type.
+This can be achieved by using the hasUnqualifiedDesugaredType matcher:
+  varDecl(hasType(hasUnqualifiedDesugaredType(
+      recordType(hasDeclaration(decl())))))
+In this matcher, the decl will match the CXXRecordDecl of class X.
 
 Usable as: Matcher<AddrLabelExpr>, Matcher<CallExpr>,
   Matcher<CXXConstructExpr>, Matcher<CXXNewExpr>, Matcher<DeclRefExpr>,
@@ -5192,7 +5434,7 @@ Usable as: Matcher<LabelStmt>hasDeclarationMatcher<Decl>  InnerMatcher
+Matcher<LabelStmt>hasDeclarationconst Matcher<Decl>  InnerMatcher
 
Matches a node if the declaration associated with that node
 matches the given matcher.
 
@@ -5203,8 +5445,17 @@ The associated declaration is:
 - for CXXConstructExpr, the declaration of the constructor
 - for CXXNewExpr, the declaration of the operator new
 
-Also usable as Matcher<T> for any T supporting the getDecl() member
-function. e.g. various subtypes of clang::Type and various expressions.
+For type nodes, hasDeclaration will generally match the declaration of the
+sugared type. Given
+  class X {};
+  typedef X Y;
+  Y y;
+in varDecl(hasType(hasDeclaration(decl()))) the decl will match the
+typedefDecl. A common use case is to match the underlying, desugared type.
+This can be achieved by using the hasUnqualifiedDesugaredType matcher:
+  varDecl(hasType(hasUnqualifiedDesugaredType(
+      recordType(hasDeclaration(decl())))))
+In this matcher, the decl will match the CXXRecordDecl of class X.
 
 Usable as: Matcher<AddrLabelExpr>, Matcher<CallExpr>,
   Matcher<CXXConstructExpr>, Matcher<CXXNewExpr>, Matcher<DeclRefExpr>,
@@ -5216,7 +5467,7 @@ Usable as: Matcher<MemberExpr>hasDeclarationMatcher<Decl>  InnerMatcher
+Matcher<MemberExpr>hasDeclarationconst Matcher<Decl>  InnerMatcher
 
Matches a node if the declaration associated with that node
 matches the given matcher.
 
@@ -5227,8 +5478,17 @@ The associated declaration is:
 - for CXXConstructExpr, the declaration of the constructor
 - for CXXNewExpr, the declaration of the operator new
 
-Also usable as Matcher<T> for any T supporting the getDecl() member
-function. e.g. various subtypes of clang::Type and various expressions.
+For type nodes, hasDeclaration will generally match the declaration of the
+sugared type. Given
+  class X {};
+  typedef X Y;
+  Y y;
+in varDecl(hasType(hasDeclaration(decl()))) the decl will match the
+typedefDecl. A common use case is to match the underlying, desugared type.
+This can be achieved by using the hasUnqualifiedDesugaredType matcher:
+  varDecl(hasType(hasUnqualifiedDesugaredType(
+      recordType(hasDeclaration(decl())))))
+In this matcher, the decl will match the CXXRecordDecl of class X.
 
 Usable as: Matcher<AddrLabelExpr>, Matcher<CallExpr>,
   Matcher<CXXConstructExpr>, Matcher<CXXNewExpr>, Matcher<DeclRefExpr>,
@@ -5397,7 +5657,18 @@ matches the [webView ...] message invocation.
 
 
 Matcher<OpaqueValueExpr>hasSourceExpressionMatcher<Expr> InnerMatcher
-

+
Matches if the cast's source expression
+or opaque value's source expression matches the given matcher.
+
+Example 1: matches "a string"
+(matcher = castExpr(hasSourceExpression(cxxConstructExpr())))
+class URL { URL(string); };
+URL url = "a string";
+
+Example 2: matches 'b' (matcher =
+opaqueValueExpr(hasSourceExpression(implicitCastExpr(declRefExpr())))
+int a = b ?: 1;
+
Matcher<OverloadExpr>hasAnyDeclarationMatcher<Decl> InnerMatcher @@ -5476,7 +5747,7 @@ declaration of b but varDecl(hasType(qualType(hasCanonicalType(referenceType()))
-Matcher<QualType>hasDeclarationMatcher<Decl> InnerMatcher +Matcher<QualType>hasDeclarationconst Matcher<Decl> InnerMatcher
Matches a node if the declaration associated with that node
 matches the given matcher.
 
@@ -5487,8 +5758,17 @@ The associated declaration is:
 - for CXXConstructExpr, the declaration of the constructor
 - for CXXNewExpr, the declaration of the operator new
 
-Also usable as Matcher<T> for any T supporting the getDecl() member
-function. e.g. various subtypes of clang::Type and various expressions.
+For type nodes, hasDeclaration will generally match the declaration of the
+sugared type. Given
+  class X {};
+  typedef X Y;
+  Y y;
+in varDecl(hasType(hasDeclaration(decl()))) the decl will match the
+typedefDecl. A common use case is to match the underlying, desugared type.
+This can be achieved by using the hasUnqualifiedDesugaredType matcher:
+  varDecl(hasType(hasUnqualifiedDesugaredType(
+      recordType(hasDeclaration(decl())))))
+In this matcher, the decl will match the CXXRecordDecl of class X.
 
 Usable as: Matcher<AddrLabelExpr>, Matcher<CallExpr>,
   Matcher<CXXConstructExpr>, Matcher<CXXNewExpr>, Matcher<DeclRefExpr>,
@@ -5548,7 +5828,7 @@ Example matches X &x and const X &y
 
-Matcher<RecordType>hasDeclarationMatcher<Decl> InnerMatcher +Matcher<RecordType>hasDeclarationconst Matcher<Decl> InnerMatcher
Matches a node if the declaration associated with that node
 matches the given matcher.
 
@@ -5559,8 +5839,17 @@ The associated declaration is:
 - for CXXConstructExpr, the declaration of the constructor
 - for CXXNewExpr, the declaration of the operator new
 
-Also usable as Matcher<T> for any T supporting the getDecl() member
-function. e.g. various subtypes of clang::Type and various expressions.
+For type nodes, hasDeclaration will generally match the declaration of the
+sugared type. Given
+  class X {};
+  typedef X Y;
+  Y y;
+in varDecl(hasType(hasDeclaration(decl()))) the decl will match the
+typedefDecl. A common use case is to match the underlying, desugared type.
+This can be achieved by using the hasUnqualifiedDesugaredType matcher:
+  varDecl(hasType(hasUnqualifiedDesugaredType(
+      recordType(hasDeclaration(decl())))))
+In this matcher, the decl will match the CXXRecordDecl of class X.
 
 Usable as: Matcher<AddrLabelExpr>, Matcher<CallExpr>,
   Matcher<CXXConstructExpr>, Matcher<CXXNewExpr>, Matcher<DeclRefExpr>,
@@ -5629,7 +5918,7 @@ with compoundStmt()
 
-Matcher<Stmt>alignOfExprMatcher<UnaryExprOrTypeTraitExpr> InnerMatcher +Matcher<Stmt>alignOfExprconst Matcher<UnaryExprOrTypeTraitExpr> InnerMatcher
Same as unaryExprOrTypeTraitExpr, but only matching
 alignof.
 
@@ -5649,7 +5938,7 @@ returnStmt(forFunction(hasName("operator=")))
-Matcher<Stmt>sizeOfExprMatcher<UnaryExprOrTypeTraitExpr> InnerMatcher +Matcher<Stmt>sizeOfExprconst Matcher<UnaryExprOrTypeTraitExpr> InnerMatcher
Same as unaryExprOrTypeTraitExpr, but only matching
 sizeof.
 
@@ -5691,7 +5980,7 @@ Example matches true (matcher = hasCondition(cxxBoolLiteral(equals(true))))
-Matcher<TagType>hasDeclarationMatcher<Decl> InnerMatcher +Matcher<TagType>hasDeclarationconst Matcher<Decl> InnerMatcher
Matches a node if the declaration associated with that node
 matches the given matcher.
 
@@ -5702,8 +5991,17 @@ The associated declaration is:
 - for CXXConstructExpr, the declaration of the constructor
 - for CXXNewExpr, the declaration of the operator new
 
-Also usable as Matcher<T> for any T supporting the getDecl() member
-function. e.g. various subtypes of clang::Type and various expressions.
+For type nodes, hasDeclaration will generally match the declaration of the
+sugared type. Given
+  class X {};
+  typedef X Y;
+  Y y;
+in varDecl(hasType(hasDeclaration(decl()))) the decl will match the
+typedefDecl. A common use case is to match the underlying, desugared type.
+This can be achieved by using the hasUnqualifiedDesugaredType matcher:
+  varDecl(hasType(hasUnqualifiedDesugaredType(
+      recordType(hasDeclaration(decl())))))
+In this matcher, the decl will match the CXXRecordDecl of class X.
 
 Usable as: Matcher<AddrLabelExpr>, Matcher<CallExpr>,
   Matcher<CXXConstructExpr>, Matcher<CXXNewExpr>, Matcher<DeclRefExpr>,
@@ -5719,8 +6017,8 @@ Usable as: Matcher<
Matches a sugar TemplateArgument that refers to a certain expression.
 
 Given
-  template<typename T> struct A {};
-  struct B { B* next; };
+  struct B { int next; };
+  template<int(B::*next_ptr)> struct A {};
   A<&B::next> a;
 templateSpecializationType(hasAnyTemplateArgument(
   isExpr(hasDescendant(declRefExpr(to(fieldDecl(hasName("next"))))))))
@@ -5734,11 +6032,11 @@ templateSpecializationType(hasAnyTemplateArgument(
 declaration.
 
 Given
-  template<typename T> struct A {};
-  struct B { B* next; };
+  struct B { int next; };
+  template<int(B::*next_ptr)> struct A {};
   A<&B::next> a;
 classTemplateSpecializationDecl(hasAnyTemplateArgument(
-    refersToDeclaration(fieldDecl(hasName("next"))))
+    refersToDeclaration(fieldDecl(hasName("next")))))
   matches the specialization A<&B::next> with fieldDecl(...) matching
     B::next
 
@@ -5748,7 +6046,7 @@ classTemplateSpecializationDecl(hasAnyTemplateArgument(
Matches a TemplateArgument that referes to an integral type.
 
 Given
-  template<int T> struct A {};
+  template<int T> struct C {};
   C<42> c;
 classTemplateSpecializationDecl(
   hasAnyTemplateArgument(refersToIntegralType(asString("int"))))
@@ -5804,7 +6102,7 @@ functionDecl(hasAnyTemplateArgument(refersToType(asString("int"))))
 
-Matcher<
TemplateSpecializationType>hasDeclarationMatcher<Decl> InnerMatcher +Matcher<TemplateSpecializationType>hasDeclarationconst Matcher<Decl> InnerMatcher
Matches a node if the declaration associated with that node
 matches the given matcher.
 
@@ -5815,8 +6113,17 @@ The associated declaration is:
 - for CXXConstructExpr, the declaration of the constructor
 - for CXXNewExpr, the declaration of the operator new
 
-Also usable as Matcher<T> for any T supporting the getDecl() member
-function. e.g. various subtypes of clang::Type and various expressions.
+For type nodes, hasDeclaration will generally match the declaration of the
+sugared type. Given
+  class X {};
+  typedef X Y;
+  Y y;
+in varDecl(hasType(hasDeclaration(decl()))) the decl will match the
+typedefDecl. A common use case is to match the underlying, desugared type.
+This can be achieved by using the hasUnqualifiedDesugaredType matcher:
+  varDecl(hasType(hasUnqualifiedDesugaredType(
+      recordType(hasDeclaration(decl())))))
+In this matcher, the decl will match the CXXRecordDecl of class X.
 
 Usable as: Matcher<AddrLabelExpr>, Matcher<CallExpr>,
   Matcher<CXXConstructExpr>, Matcher<CXXNewExpr>, Matcher<DeclRefExpr>,
@@ -5837,7 +6144,7 @@ Given
   A<bool, int> b;
   A<int, bool> c;
 
-  template<typename T> f() {};
+  template<typename T> void f() {}
   void func() { f<int>(); };
 classTemplateSpecializationDecl(hasTemplateArgument(
     1, refersToType(asString("int"))))
@@ -5848,7 +6155,7 @@ functionDecl(hasTemplateArgument(0, refersToType(asString("int"))))
 
-Matcher<TemplateTypeParmType>hasDeclarationMatcher<Decl> InnerMatcher +Matcher<TemplateTypeParmType>hasDeclarationconst Matcher<Decl> InnerMatcher
Matches a node if the declaration associated with that node
 matches the given matcher.
 
@@ -5859,8 +6166,17 @@ The associated declaration is:
 - for CXXConstructExpr, the declaration of the constructor
 - for CXXNewExpr, the declaration of the operator new
 
-Also usable as Matcher<T> for any T supporting the getDecl() member
-function. e.g. various subtypes of clang::Type and various expressions.
+For type nodes, hasDeclaration will generally match the declaration of the
+sugared type. Given
+  class X {};
+  typedef X Y;
+  Y y;
+in varDecl(hasType(hasDeclaration(decl()))) the decl will match the
+typedefDecl. A common use case is to match the underlying, desugared type.
+This can be achieved by using the hasUnqualifiedDesugaredType matcher:
+  varDecl(hasType(hasUnqualifiedDesugaredType(
+      recordType(hasDeclaration(decl())))))
+In this matcher, the decl will match the CXXRecordDecl of class X.
 
 Usable as: Matcher<AddrLabelExpr>, Matcher<CallExpr>,
   Matcher<CXXConstructExpr>, Matcher<CXXNewExpr>, Matcher<DeclRefExpr>,
@@ -5872,7 +6188,7 @@ Usable as: Matcher<findAllMatcher<T>  Matcher
+Matcher<T>findAllconst Matcher<T>  Matcher
 
Matches if the node or any descendant matches.
 
 Generates results for each match.
@@ -5901,7 +6217,7 @@ Example matches x (matcher = expr(hasType(cxxRecordDecl(hasName("X")))))
 
-Matcher<TypedefType>hasDeclarationMatcher<Decl> InnerMatcher +Matcher<TypedefType>hasDeclarationconst Matcher<Decl> InnerMatcher
Matches a node if the declaration associated with that node
 matches the given matcher.
 
@@ -5912,8 +6228,17 @@ The associated declaration is:
 - for CXXConstructExpr, the declaration of the constructor
 - for CXXNewExpr, the declaration of the operator new
 
-Also usable as Matcher<T> for any T supporting the getDecl() member
-function. e.g. various subtypes of clang::Type and various expressions.
+For type nodes, hasDeclaration will generally match the declaration of the
+sugared type. Given
+  class X {};
+  typedef X Y;
+  Y y;
+in varDecl(hasType(hasDeclaration(decl()))) the decl will match the
+typedefDecl. A common use case is to match the underlying, desugared type.
+This can be achieved by using the hasUnqualifiedDesugaredType matcher:
+  varDecl(hasType(hasUnqualifiedDesugaredType(
+      recordType(hasDeclaration(decl())))))
+In this matcher, the decl will match the CXXRecordDecl of class X.
 
 Usable as: Matcher<AddrLabelExpr>, Matcher<CallExpr>,
   Matcher<CXXConstructExpr>, Matcher<CXXNewExpr>, Matcher<DeclRefExpr>,
@@ -5932,7 +6257,7 @@ type of the matched node.
 For example, in:
   class A {};
   using B = A;
-The matcher type(hasUniqualifeidDesugaredType(recordType())) matches
+The matcher type(hasUnqualifeidDesugaredType(recordType())) matches
 both B and A.
 
@@ -5956,7 +6281,7 @@ Example matches true (matcher = hasUnaryOperand(
-Matcher<UnresolvedUsingType>hasDeclarationMatcher<Decl> InnerMatcher +Matcher<UnresolvedUsingType>hasDeclarationconst Matcher<Decl> InnerMatcher
Matches a node if the declaration associated with that node
 matches the given matcher.
 
@@ -5967,8 +6292,17 @@ The associated declaration is:
 - for CXXConstructExpr, the declaration of the constructor
 - for CXXNewExpr, the declaration of the operator new
 
-Also usable as Matcher<T> for any T supporting the getDecl() member
-function. e.g. various subtypes of clang::Type and various expressions.
+For type nodes, hasDeclaration will generally match the declaration of the
+sugared type. Given
+  class X {};
+  typedef X Y;
+  Y y;
+in varDecl(hasType(hasDeclaration(decl()))) the decl will match the
+typedefDecl. A common use case is to match the underlying, desugared type.
+This can be achieved by using the hasUnqualifiedDesugaredType matcher:
+  varDecl(hasType(hasUnqualifiedDesugaredType(
+      recordType(hasDeclaration(decl())))))
+In this matcher, the decl will match the CXXRecordDecl of class X.
 
 Usable as: Matcher<AddrLabelExpr>, Matcher<CallExpr>,
   Matcher<CXXConstructExpr>, Matcher<CXXNewExpr>, Matcher<DeclRefExpr>,
diff --git a/docs/Modules.rst b/docs/Modules.rst
index 757be619139094de8efa5bac53a1e4c211d05e9d..493c54d3913a9460905cb63de31c771f6c87c61a 100644
--- a/docs/Modules.rst
+++ b/docs/Modules.rst
@@ -430,6 +430,21 @@ cplusplus
 cplusplus11
   C++11 support is available.
 
+cplusplus14
+  C++14 support is available.
+
+cplusplus17
+  C++17 support is available.
+
+c99
+  C99 support is available.
+
+c11
+  C11 support is available.
+
+c17
+  C17 support is available.
+
 freestanding
   A freestanding environment is available.
 
@@ -859,10 +874,12 @@ express this with a single module map file in the library:
 
   module Foo {
     header "Foo.h"
-    
-    explicit module Private {
-      header "Foo_Private.h"
-    }
+    ...
+  }
+
+  module Foo_Private {
+    header "Foo_Private.h"
+    ...
   }
 
 
@@ -873,7 +890,7 @@ build machinery.
 
 Private module map files, which are named ``module.private.modulemap``
 (or, for backward compatibility, ``module_private.map``), allow one to
-augment the primary module map file with an additional submodule. For
+augment the primary module map file with an additional modules. For
 example, we would split the module map file above into two module map
 files:
 
@@ -883,9 +900,9 @@ files:
   module Foo {
     header "Foo.h"
   }
-  
+
   /* module.private.modulemap */
-  explicit module Foo.Private {
+  module Foo_Private {
     header "Foo_Private.h"
   }
 
@@ -899,13 +916,12 @@ boundaries.
 
 When writing a private module as part of a *framework*, it's recommended that:
 
-* Headers for this module are present in the ``PrivateHeaders``
-  framework subdirectory.
-* The private module is defined as a *submodule* of the public framework (if
-  there's one), similar to how ``Foo.Private`` is defined in the example above.
-* The ``explicit`` keyword should be used to guarantee that its content will
-  only be available when the submodule itself is explicitly named (through a
-  ``@import`` for example).
+* Headers for this module are present in the ``PrivateHeaders`` framework
+  subdirectory.
+* The private module is defined as a *top level module* with the name of the
+  public framework prefixed, like ``Foo_Private`` above. Clang has extra logic
+  to work with this naming, using ``FooPrivate`` or ``Foo.Private`` (submodule)
+  trigger warnings and might not work as expected.
 
 Modularizing a Platform
 =======================
diff --git a/docs/OpenMPSupport.rst b/docs/OpenMPSupport.rst
new file mode 100644
index 0000000000000000000000000000000000000000..f34049473f825049941a858dee6cc35317824545
--- /dev/null
+++ b/docs/OpenMPSupport.rst
@@ -0,0 +1,68 @@
+.. raw:: html
+
+  
+
+.. role:: none
+.. role:: partial
+.. role:: good
+
+==================
+OpenMP Support
+==================
+
+Clang fully supports OpenMP 3.1 + some elements of OpenMP 4.5. Clang supports offloading to X86_64, AArch64 and PPC64[LE] devices.
+Support for Cuda devices is not ready yet.
+The status of major OpenMP 4.5 features support in Clang.
+
+Standalone directives
+=====================
+
+* #pragma omp [for] simd: :good:`Complete`.
+
+* #pragma omp declare simd: :partial:`Partial`.  We support parsing/semantic
+  analysis + generation of special attributes for X86 target, but still
+  missing the LLVM pass for vectorization.
+
+* #pragma omp taskloop [simd]: :good:`Complete`.
+
+* #pragma omp target [enter|exit] data: :good:`Complete`.
+
+* #pragma omp target update: :good:`Complete`.
+
+* #pragma omp target: :good:`Complete`.
+
+* #pragma omp declare target: :partial:`Partial`.  No full codegen support.
+
+* #pragma omp teams: :good:`Complete`.
+
+* #pragma omp distribute [simd]: :good:`Complete`.
+
+* #pragma omp distribute parallel for [simd]: :good:`Complete`.
+
+Combined directives
+===================
+
+* #pragma omp parallel for simd: :good:`Complete`.
+
+* #pragma omp target parallel: :good:`Complete`.
+
+* #pragma omp target parallel for [simd]: :good:`Complete`.
+
+* #pragma omp target simd: :good:`Complete`.
+
+* #pragma omp target teams: :good:`Complete`.
+
+* #pragma omp teams distribute [simd]: :good:`Complete`.
+
+* #pragma omp target teams distribute [simd]: :good:`Complete`.
+
+* #pragma omp teams distribute parallel for [simd]: :good:`Complete`.
+
+* #pragma omp target teams distribute parallel for [simd]: :good:`Complete`.
+
+Clang does not support any constructs/updates from upcoming OpenMP 5.0 except for `reduction`-based clauses in the `task` and `target`-based directives.
+In addition, the LLVM OpenMP runtime `libomp` supports the OpenMP Tools Interface (OMPT) on x86, x86_64, AArch64, and PPC64 on Linux, Windows, and mac OS.
diff --git a/docs/ReleaseNotes.rst b/docs/ReleaseNotes.rst
index 293144a832700f25b0e043b62fc1c4c0e9e3d84d..b29cd0627d05c85bd3563bbf8ffba5aea7b514e3 100644
--- a/docs/ReleaseNotes.rst
+++ b/docs/ReleaseNotes.rst
@@ -1,5 +1,5 @@
 =======================================
-Clang 6.0.0 (In-Progress) Release Notes
+Clang 7.0.0 (In-Progress) Release Notes
 =======================================
 
 .. contents::
@@ -10,7 +10,7 @@ Written by the `LLVM Team `_
 
 .. warning::
 
-   These are in-progress notes for the upcoming Clang 6 release.
+   These are in-progress notes for the upcoming Clang 7 release.
    Release notes for previous releases can be found on
    `the Download Page `_.
 
@@ -18,7 +18,7 @@ Introduction
 ============
 
 This document contains the release notes for the Clang C/C++/Objective-C
-frontend, part of the LLVM Compiler Infrastructure, release 6.0.0. Here we
+frontend, part of the LLVM Compiler Infrastructure, release 7.0.0. Here we
 describe the status of Clang in some detail, including major
 improvements from the previous release and new feature work. For the
 general LLVM release notes, see `the LLVM
@@ -35,7 +35,7 @@ main Clang web page, this document applies to the *next* release, not
 the current one. To see the release notes for a specific release, please
 see the `releases page `_.
 
-What's New in Clang 6.0.0?
+What's New in Clang 7.0.0?
 ==========================
 
 Some of the major new features and improvements to Clang are listed
@@ -51,57 +51,17 @@ Major New Features
 Improvements to Clang's diagnostics
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-- ``-Wpragma-pack`` is a new warning that warns in the following cases:
-
-  - When a translation unit is missing terminating ``#pragma pack (pop)``
-    directives.
-
-  - When leaving an included file that changes the current alignment value,
-    i.e. when the alignment before ``#include`` is different to the alignment
-    after ``#include``.
-
-  - ``-Wpragma-pack-suspicious-include`` (disabled by default) warns on an
-    ``#include`` when the included file contains structures or unions affected by
-    a non-default alignment that has been specified using a ``#pragma pack``
-    directive prior to the ``#include``.
-
-- ``-Wobjc-messaging-id`` is a new, non-default warning that warns about
-  message sends to unqualified ``id`` in Objective-C. This warning is useful
-  for projects that would like to avoid any potential future compiler
-  errors/warnings, as the system frameworks might add a method with the same
-  selector which could make the message send to ``id`` ambiguous.
-
-- ``-Wtautological-compare`` now warns when comparing an unsigned integer and 0
-  regardless of whether the constant is signed or unsigned."
-
-- ``-Wtautological-compare`` now warns about comparing a signed integer and 0
-  when the signed integer is coerced to an unsigned type for the comparison.
-  ``-Wsign-compare`` was adjusted not to warn in this case.
-
-- ``-Wtautological-constant-compare`` is a new warning that warns on
-  tautological comparisons between integer variable of the type ``T`` and the
-  largest/smallest possible integer constant of that same type.
-
-- ``-Wnull-pointer-arithmetic`` now warns about performing pointer arithmetic
-  on a null pointer. Such pointer arithmetic has an undefined behavior if the
-  offset is nonzero. It also now warns about arithmetic on a null pointer
-  treated as a cast from integer to pointer (GNU extension).
+- ...
 
 Non-comprehensive list of changes in this release
 -------------------------------------------------
 
-- Bitrig OS was merged back into OpenBSD, so Bitrig support has been
-  removed from Clang/LLVM.
-
-- The default value of _MSC_VER was raised from 1800 to 1911, making it
-  compatible with the Visual Studio 2015 and 2017 C++ standard library headers.
-  Users should generally expect this to be regularly raised to match the most
-  recently released version of the Visual C++ compiler.
+- ...
 
 New Compiler Flags
 ------------------
 
-- --autocomplete was implemented to obtain a list of flags and its arguments. This is used for shell autocompletion.
+- ...
 
 Deprecated Compiler Flags
 -------------------------
@@ -120,9 +80,12 @@ Clang now supports the ...
 Attribute Changes in Clang
 --------------------------
 
-- The presence of __attribute__((availability(...))) on a declaration no longer
-  implies default visibility for that declaration on macOS.
-
+- Clang now supports function multiversioning with attribute 'target' on ELF
+  based x86/x86-64 environments by using indirect functions. This implementation
+  has a few minor limitations over the GCC implementation for the sake of AST
+  sanity, however it is otherwise compatible with existing code using this
+  feature for GCC. Consult the documentation for the target attribute for more
+  information.
 - ...
 
 Windows Support
@@ -146,7 +109,7 @@ C11 Feature Support
 C++ Language Changes in Clang
 -----------------------------
 
-...
+- ...
 
 C++1z Feature Support
 ^^^^^^^^^^^^^^^^^^^^^
@@ -166,12 +129,12 @@ OpenCL C Language Changes in Clang
 OpenMP Support in Clang
 ----------------------------------
 
-...
+- ...
 
 Internal API Changes
 --------------------
 
-These are major API changes that have happened since the 4.0.0 release of
+These are major API changes that have happened since the 6.0.0 release of
 Clang. If upgrading an external codebase that uses Clang as a library,
 this section should help get you past the largest hurdles of upgrading.
 
@@ -180,54 +143,12 @@ this section should help get you past the largest hurdles of upgrading.
 AST Matchers
 ------------
 
-The hasDeclaration matcher now works the same for Type and QualType and only
-ever looks through one level of sugaring in a limited number of cases.
-
-There are two main patterns affected by this:
-
--  qualType(hasDeclaration(recordDecl(...))): previously, we would look through
-   sugar like TypedefType to get at the underlying recordDecl; now, we need
-   to explicitly remove the sugaring:
-   qualType(hasUnqualifiedDesugaredType(hasDeclaration(recordDecl(...))))
-
--  hasType(recordDecl(...)): hasType internally uses hasDeclaration; previously,
-   this matcher used to match for example TypedefTypes of the RecordType, but
-   after the change they don't; to fix, use:
-
-::
-   hasType(hasUnqualifiedDesugaredType(
-       recordType(hasDeclaration(recordDecl(...)))))
-
--  templateSpecializationType(hasDeclaration(classTemplateDecl(...))):
-   previously, we would directly match the underlying ClassTemplateDecl;
-   now, we can explicitly match the ClassTemplateSpecializationDecl, but that
-   requires to explicitly get the ClassTemplateDecl:
-
-::
-   templateSpecializationType(hasDeclaration(
-       classTemplateSpecializationDecl(
-           hasSpecializedTemplate(classTemplateDecl(...)))))
+- ...
 
 clang-format
 ------------
 
-* Option *IndentPPDirectives* added to indent preprocessor directives on
-  conditionals.
-
-  +----------------------+----------------------+
-  | Before               | After                |
-  +======================+======================+
-  |  .. code-block:: c++ | .. code-block:: c++  |
-  |                      |                      |
-  |    #if FOO           |   #if FOO            |
-  |    #if BAR           |   #  if BAR          |
-  |    #include     |   #    include  |
-  |    #endif            |   #  endif           |
-  |    #endif            |   #endif             |
-  +----------------------+----------------------+
-
-* Option -verbose added to the command line.
-  Shows the list of processed files.
+- ...
 
 libclang
 --------
@@ -238,15 +159,14 @@ libclang
 Static Analyzer
 ---------------
 
+- ...
+
 ...
 
 Undefined Behavior Sanitizer (UBSan)
 ------------------------------------
 
-* A minimal runtime is now available. It is suitable for use in production
-  environments, and has a small attack surface. It only provides very basic
-  issue logging and deduplication, and does not support ``-fsanitize=vptr``
-  checking.
+* ...
 
 Core Analysis Improvements
 ==========================
diff --git a/docs/ThinLTO.rst b/docs/ThinLTO.rst
index 607121fd1e5fea17a9ac26c68a6f578018e398b9..38873f464c29ca637d41e3ec45d3f43316abadd5 100644
--- a/docs/ThinLTO.rst
+++ b/docs/ThinLTO.rst
@@ -156,7 +156,7 @@ A policy string is a series of key-value pairs separated by ``:`` characters.
 Possible key-value pairs are:
 
 - ``cache_size=X%``: The maximum size for the cache directory is ``X`` percent
-  of the available space on the the disk. Set to 100 to indicate no limit,
+  of the available space on the disk. Set to 100 to indicate no limit,
   50 to indicate that the cache size will not be left over half the available
   disk space. A value over 100 is invalid. A value of 0 disables the percentage
   size-based pruning. The default is 75%.
@@ -173,6 +173,10 @@ Possible key-value pairs are:
   ``cache_size_bytes=1g`` on its own will cause both the 1GB and default 75%
   policies to be applied unless the default ``cache_size`` is overridden.
 
+- ``cache_size_files=X``:
+  Set the maximum number of files in the cache directory. Set to 0 to indicate
+  no limit. The default is 1000000 files.
+
 - ``prune_after=Xs``, ``prune_after=Xm``, ``prune_after=Xh``: Sets the
   expiration time for cache files to ``X`` seconds (or minutes, hours
   respectively).  When a file hasn't been accessed for ``prune_after`` seconds,
diff --git a/docs/Toolchain.rst b/docs/Toolchain.rst
index e727ccdc7c1ac63538fcc8aeb9eb98ad84fefb48..06bde35c3da6b088f2c765c87ac0f8a17ad3c346 100644
--- a/docs/Toolchain.rst
+++ b/docs/Toolchain.rst
@@ -106,7 +106,7 @@ Assember
 Clang can either use LLVM's integrated assembler or an external system-specific
 tool (for instance, the GNU Assembler on GNU OSes) to produce machine code from
 assembly.
-By default, Clang uses LLVM's integrataed assembler on all targets where it is
+By default, Clang uses LLVM's integrated assembler on all targets where it is
 supported. If you wish to use the system assember instead, use the
 ``-fno-integrated-as`` option.
 
diff --git a/docs/UndefinedBehaviorSanitizer.rst b/docs/UndefinedBehaviorSanitizer.rst
index 0a08a41e2d9b2e7badd5a9619d103fcd5e2e62f7..e9f85c24dde0ec56b4630d6a0e8df1d3495390bf 100644
--- a/docs/UndefinedBehaviorSanitizer.rst
+++ b/docs/UndefinedBehaviorSanitizer.rst
@@ -124,8 +124,8 @@ Available checks are:
   -  ``-fsanitize=signed-integer-overflow``: Signed integer overflow,
      including all the checks added by ``-ftrapv``, and checking for
      overflow in signed division (``INT_MIN / -1``).
-  -  ``-fsanitize=unreachable``: If control flow reaches
-     ``__builtin_unreachable``.
+  -  ``-fsanitize=unreachable``: If control flow reaches an unreachable
+     program point.
   -  ``-fsanitize=unsigned-integer-overflow``: Unsigned integer
      overflows. Note that unlike signed integer overflow, unsigned integer
      is not undefined behavior. However, while it has well-defined semantics,
diff --git a/docs/UsersManual.rst b/docs/UsersManual.rst
index 2757ced1c24c65de4cc5eb6b0bfc69533fa3426f..f19aacc4e99290a965b62bee0d072ea5cea63a28 100644
--- a/docs/UsersManual.rst
+++ b/docs/UsersManual.rst
@@ -694,6 +694,79 @@ a special character, which is the convention used by GNU Make. The -MV
 option tells Clang to put double-quotes around the entire filename, which
 is the convention used by NMake and Jom.
 
+Configuration files
+-------------------
+
+Configuration files group command-line options and allow all of them to be
+specified just by referencing the configuration file. They may be used, for
+example, to collect options required to tune compilation for particular
+target, such as -L, -I, -l, --sysroot, codegen options, etc.
+
+The command line option `--config` can be used to specify configuration
+file in a Clang invocation. For example:
+
+::
+
+    clang --config /home/user/cfgs/testing.txt
+    clang --config debug.cfg
+
+If the provided argument contains a directory separator, it is considered as
+a file path, and options are read from that file. Otherwise the argument is
+treated as a file name and is searched for sequentially in the directories:
+
+    - user directory,
+    - system directory,
+    - the directory where Clang executable resides.
+
+Both user and system directories for configuration files are specified during
+clang build using CMake parameters, CLANG_CONFIG_FILE_USER_DIR and
+CLANG_CONFIG_FILE_SYSTEM_DIR respectively. The first file found is used. It is
+an error if the required file cannot be found.
+
+Another way to specify a configuration file is to encode it in executable name.
+For example, if the Clang executable is named `armv7l-clang` (it may be a
+symbolic link to `clang`), then Clang will search for file `armv7l.cfg` in the
+directory where Clang resides.
+
+If a driver mode is specified in invocation, Clang tries to find a file specific
+for the specified mode. For example, if the executable file is named
+`x86_64-clang-cl`, Clang first looks for `x86_64-cl.cfg` and if it is not found,
+looks for `x86_64.cfg`.
+
+If the command line contains options that effectively change target architecture
+(these are -m32, -EL, and some others) and the configuration file starts with an
+architecture name, Clang tries to load the configuration file for the effective
+architecture. For example, invocation:
+
+::
+
+    x86_64-clang -m32 abc.c
+
+causes Clang search for a file `i368.cfg` first, and if no such file is found,
+Clang looks for the file `x86_64.cfg`.
+
+The configuration file consists of command-line options specified on one or
+more lines. Lines composed of whitespace characters only are ignored as well as
+lines in which the first non-blank character is `#`. Long options may be split
+between several lines by a trailing backslash. Here is example of a
+configuration file:
+
+::
+
+    # Several options on line
+    -c --target=x86_64-unknown-linux-gnu
+
+    # Long option split between lines
+    -I/usr/lib/gcc/x86_64-linux-gnu/5.4.0/../../../../\
+    include/c++/5.4.0
+
+    # other config files may be included
+    @linux.options
+
+Files included by `@file` directives in configuration files are resolved
+relative to the including file. For example, if a configuration file
+`~/.llvm/target.cfg` contains the directive `@os/linux.opts`, the file
+`linux.opts` is searched for in the directory `~/.llvm/os`.
 
 Language and Target-Independent Features
 ========================================
@@ -1002,7 +1075,7 @@ location.
 Building a relocatable precompiled header requires two additional
 arguments. First, pass the ``--relocatable-pch`` flag to indicate that
 the resulting PCH file should be relocatable. Second, pass
-`-isysroot /path/to/build`, which makes all includes for your library
+``-isysroot /path/to/build``, which makes all includes for your library
 relative to the build directory. For example:
 
 .. code-block:: console
@@ -1012,9 +1085,9 @@ relative to the build directory. For example:
 When loading the relocatable PCH file, the various headers used in the
 PCH file are found from the system header root. For example, ``mylib.h``
 can be found in ``/usr/include/mylib.h``. If the headers are installed
-in some other system root, the `-isysroot` option can be used provide
+in some other system root, the ``-isysroot`` option can be used provide
 a different system root from which the headers will be based. For
-example, `-isysroot /Developer/SDKs/MacOSX10.4u.sdk` will look for
+example, ``-isysroot /Developer/SDKs/MacOSX10.4u.sdk`` will look for
 ``mylib.h`` in ``/Developer/SDKs/MacOSX10.4u.sdk/usr/include/mylib.h``.
 
 Relocatable precompiled headers are intended to be used in a limited
@@ -1147,6 +1220,11 @@ are listed below.
    the behavior of sanitizers in the ``cfi`` group to allow checking
    of cross-DSO virtual and indirect calls.
 
+.. option:: -fsanitize-cfi-icall-generalize-pointers
+
+   Generalize pointers in return and argument types in function type signatures
+   checked by Control Flow Integrity indirect call checking. See
+   :doc:`ControlFlowIntegrity` for more details.
 
 .. option:: -fstrict-vtable-pointers
 
@@ -1297,7 +1375,8 @@ Profile Guided Optimization
 Profile information enables better optimization. For example, knowing that a
 branch is taken very frequently helps the compiler make better decisions when
 ordering basic blocks. Knowing that a function ``foo`` is called more
-frequently than another function ``bar`` helps the inliner.
+frequently than another function ``bar`` helps the inliner. Optimization
+levels ``-O2`` and above are recommended for use of profile guided optimization.
 
 Clang supports profile guided optimization with two different kinds of
 profiling. A sampling profiler can generate a profile with very low runtime
@@ -1776,6 +1855,27 @@ features. You can "tune" the debug info for one of several different debuggers.
   must come first.)
 
 
+Controlling LLVM IR Output
+--------------------------
+
+Controlling Value Names in LLVM IR
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Emitting value names in LLVM IR increases the size and verbosity of the IR.
+By default, value names are only emitted in assertion-enabled builds of Clang.
+However, when reading IR it can be useful to re-enable the emission of value
+names to improve readability.
+
+.. option:: -fdiscard-value-names
+
+  Discard value names when generating LLVM IR.
+
+.. option:: -fno-discard-value-names
+
+  Do not discard value names when generating LLVM IR. This option can be used
+  to re-enable names for release builds of Clang.
+
+
 Comment Parsing Options
 -----------------------
 
@@ -2037,6 +2137,11 @@ directives, and ``#pragma omp taskgroup`` directive.
 Use `-fopenmp` to enable OpenMP. Support for OpenMP can be disabled with
 `-fno-openmp`.
 
+Use `-fopenmp-simd` to enable OpenMP simd features only, without linking
+the runtime library; for combined constructs
+(e.g. ``#pragma omp parallel for simd``) the non-simd directives and clauses
+will be ignored. This can be disabled with `-fno-openmp-simd`.
+
 Controlling implementation limits
 ---------------------------------
 
@@ -2579,10 +2684,37 @@ compatibility with the Visual C++ compiler, cl.exe.
 To enable clang-cl to find system headers, libraries, and the linker when run
 from the command-line, it should be executed inside a Visual Studio Native Tools
 Command Prompt or a regular Command Prompt where the environment has been set
-up using e.g. `vcvars32.bat `_.
+up using e.g. `vcvarsall.bat `_.
+
+clang-cl can also be used from inside Visual Studio by selecting the LLVM
+Platform Toolset. The toolset is installed by the LLVM installer, which can be
+downloaded from the `LLVM release `_ or
+`snapshot build `_ web pages. To use the toolset,
+select a project in Solution Explorer, open its Property Page (Alt+F7), and in
+the "General" section of "Configuration Properties" change "Platform Toolset"
+to e.g. LLVM-vs2014.
+
+To use the toolset with MSBuild directly, invoke it with e.g.
+``/p:PlatformToolset=LLVM-vs2014``. This allows trying out the clang-cl
+toolchain without modifying your project files.
+
+It's also possible to point MSBuild at clang-cl without changing toolset by
+passing ``/p:CLToolPath=c:\llvm\bin /p:CLToolExe=clang-cl.exe``.
+
+When using CMake and the Visual Studio generators, the toolset can be set with the ``-T`` flag:
+
+  ::
+
+    cmake -G"Visual Studio 15 2017" -T LLVM-vs2014 ..
+
+When using CMake with the Ninja generator, set the ``CMAKE_C_COMPILER`` and
+``CMAKE_CXX_COMPILER`` variables to clang-cl:
+
+  ::
+
+    cmake -GNinja -DCMAKE_C_COMPILER="c:/Program Files (x86)/LLVM/bin/clang-cl.exe"
+        -DCMAKE_CXX_COMPILER="c:/Program Files (x86)/LLVM/bin/clang-cl.exe" ..
 
-clang-cl can also be used from inside Visual Studio by using an LLVM Platform
-Toolset.
 
 Command-Line Options
 --------------------
@@ -2649,6 +2781,7 @@ Execute ``clang-cl /?`` to see a list of supported options:
       /Gd                     Set __cdecl as a default calling convention
       /GF-                    Disable string pooling
       /GR-                    Disable emission of RTTI data
+      /Gregcall               Set __regcall as a default calling convention
       /GR                     Enable emission of RTTI data
       /Gr                     Set __fastcall as a default calling convention
       /GS-                    Disable buffer security check
@@ -2705,7 +2838,7 @@ Execute ``clang-cl /?`` to see a list of supported options:
       /W2                     Enable -Wall
       /W3                     Enable -Wall
       /W4                     Enable -Wall and -Wextra
-      /Wall                   Enable -Wall and -Wextra
+      /Wall                   Enable -Weverything
       /WX-                    Do not treat warnings as errors
       /WX                     Treat warnings as errors
       /w                      Disable all warnings
@@ -2762,6 +2895,8 @@ Execute ``clang-cl /?`` to see a list of supported options:
                               Disable specified features of coverage instrumentation for Sanitizers
       -fno-sanitize-memory-track-origins
                               Disable origins tracking in MemorySanitizer
+      -fno-sanitize-memory-use-after-dtor
+                              Disable use-after-destroy detection in MemorySanitizer
       -fno-sanitize-recover=
                               Disable recovery for specified sanitizers
       -fno-sanitize-stats     Disable sanitizer statistics gathering.
@@ -2792,6 +2927,8 @@ Execute ``clang-cl /?`` to see a list of supported options:
                               Path to blacklist file for sanitizers
       -fsanitize-cfi-cross-dso
                               Enable control flow integrity (CFI) checks for cross-DSO calls.
+      -fsanitize-cfi-icall-generalize-pointers
+                              Generalize pointers in CFI indirect call type signature checks
       -fsanitize-coverage=
                               Specify the type of coverage instrumentation for Sanitizers
       -fsanitize-memory-track-origins=
@@ -2815,6 +2952,7 @@ Execute ``clang-cl /?`` to see a list of supported options:
       -fsanitize=      Turn on runtime checks for various forms of undefined or suspicious
                               behavior. See user manual for available checks
       -fstandalone-debug      Emit full debug info for all types used by the program
+      -fwhole-program-vtables Enables whole-program vtable optimization. Requires -flto
       -gcodeview              Generate CodeView debug information
       -gline-tables-only      Emit debug line number tables only
       -miamcu                 Use Intel MCU ABI
@@ -2823,6 +2961,7 @@ Execute ``clang-cl /?`` to see a list of supported options:
       -Qunused-arguments      Don't emit warning for unused driver arguments
       -R              Enable the specified remark
       --target=        Generate code for the given target
+      --version               Print version information
       -v                      Show commands to run and use verbose output
       -W             Enable the specified warning
       -Xclang            Pass  to the clang compiler
diff --git a/docs/analyzer/DebugChecks.rst b/docs/analyzer/DebugChecks.rst
index e2a8e05417b69fa88492fca849fefea8e7840cc0..67521b82cabca8423eb4ff658575e806c3f8f4b4 100644
--- a/docs/analyzer/DebugChecks.rst
+++ b/docs/analyzer/DebugChecks.rst
@@ -242,6 +242,19 @@ ExprInspection checks
       clang_analyzer_printState(); // Read the stderr!
     }
 
+- ``void clang_analyzer_hashDump(int);``
+
+  The analyzer can generate a hash to identify reports. To debug what information
+  is used to calculate this hash it is possible to dump the hashed string as a
+  warning of an arbitrary expression using the function above.
+
+  Example usage::
+
+    void foo() {
+      int x = 1;
+      clang_analyzer_hashDump(x); // expected-warning{{hashed string for x}}
+    }
+
 Statistics
 ==========
 
diff --git a/docs/conf.py b/docs/conf.py
index a12f99ad6d9a46a4145623af7d3e4c625d90f7f3..b38c93af23c205dbd515e31d3522314a58ebd567 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -49,9 +49,9 @@ copyright = u'2007-%d, The Clang Team' % date.today().year
 # built documents.
 #
 # The short version.
-version = '6'
+version = '7'
 # The full version, including alpha/beta/rc tags.
-release = '6'
+release = '7'
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
diff --git a/docs/doxygen.cfg.in b/docs/doxygen.cfg.in
index 13ed72222beaaeba7e26cf41c6f0b912ba662e51..08f4253d851bb9fba16f6a01a449796b80d0ec87 100644
--- a/docs/doxygen.cfg.in
+++ b/docs/doxygen.cfg.in
@@ -284,7 +284,7 @@ MARKDOWN_SUPPORT       = YES
 
 # When enabled doxygen tries to link words that correspond to documented
 # classes, or namespaces to their corresponding documentation. Such a link can
-# be prevented in individual cases by by putting a % sign in front of the word
+# be prevented in individual cases by putting a % sign in front of the word
 # or globally by setting AUTOLINK_SUPPORT to NO.
 # The default value is: YES.
 
diff --git a/docs/index.rst b/docs/index.rst
index daf943a60bd3710651b6361bcc77971a823f8798..ed479534ee9780872cd137b40fdb8fc7e0c263d2 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -39,6 +39,7 @@ Using Clang as a Compiler
    SourceBasedCodeCoverage
    Modules
    MSVCCompatibility
+   OpenMPSupport
    ThinLTO
    CommandGuide/index
    FAQ
@@ -84,6 +85,7 @@ Design Documents
    PTHInternals
    PCHInternals
    ItaniumMangleAbiTags
+   HardwareAssistedAddressSanitizerDesign.rst
 
 
 Indices and tables
diff --git a/docs/tools/dump_ast_matchers.py b/docs/tools/dump_ast_matchers.py
index 45540405de97ccf9895d2ae260e66fbb680146bb..d38977548fd954308ec70f09345a258f5b902be1 100755
--- a/docs/tools/dump_ast_matchers.py
+++ b/docs/tools/dump_ast_matchers.py
@@ -95,7 +95,7 @@ def strip_doxygen(comment):
 def unify_arguments(args):
   """Gets rid of anything the user doesn't care about in the argument list."""
   args = re.sub(r'internal::', r'', args)
-  args = re.sub(r'const\s+(.*)&', r'\1 ', args)
+  args = re.sub(r'extern const\s+(.*)&', r'\1 ', args)
   args = re.sub(r'&', r' ', args)
   args = re.sub(r'(^|\s)M\d?(\s)', r'\1Matcher<*>\2', args)
   return args
@@ -150,11 +150,11 @@ def act_on_decl(declaration, comment, allowed_types):
                   comment, is_dyncast=True)
       return
 
-    # Parse the various matcher definition macros.
-    m = re.match(""".*AST_TYPE_MATCHER\(
-                       \s*([^\s,]+\s*),
-                       \s*([^\s,]+\s*)
-                     \)\s*;\s*$""", declaration, flags=re.X)
+    # Special case of type matchers:
+    #   AstTypeMatcher name
+    m = re.match(r""".*AstTypeMatcher\s*<
+                       \s*([^\s>]+)\s*>
+                       \s*([^\s;]+)\s*;\s*$""", declaration, flags=re.X)
     if m:
       inner, name = m.groups()
       add_matcher('Type', name, 'Matcher<%s>...' % inner,
@@ -165,7 +165,8 @@ def act_on_decl(declaration, comment, allowed_types):
       #             comment, is_dyncast=True)
       return
 
-    m = re.match(""".*AST_TYPE(LOC)?_TRAVERSE_MATCHER\(
+    # Parse the various matcher definition macros.
+    m = re.match(""".*AST_TYPE(LOC)?_TRAVERSE_MATCHER(?:_DECL)?\(
                        \s*([^\s,]+\s*),
                        \s*(?:[^\s,]+\s*),
                        \s*AST_POLYMORPHIC_SUPPORTED_TYPES\(([^)]*)\)
@@ -236,7 +237,7 @@ def act_on_decl(declaration, comment, allowed_types):
                        (?:,\s*([^\s,]+)\s*
                           ,\s*([^\s,]+)\s*)?
                        (?:,\s*\d+\s*)?
-                      \)\s*{\s*$""", declaration, flags=re.X)
+                      \)\s*{""", declaration, flags=re.X)
     if m:
       p, n, result, name = m.groups()[0:4]
       args = m.groups()[4:]
@@ -256,8 +257,8 @@ def act_on_decl(declaration, comment, allowed_types):
 
     # Parse ArgumentAdapting matchers.
     m = re.match(
-        r"""^.*ArgumentAdaptingMatcherFunc<.*>\s*(?:LLVM_ATTRIBUTE_UNUSED\s*)
-              ([a-zA-Z]*)\s*=\s*{};$""",
+        r"""^.*ArgumentAdaptingMatcherFunc<.*>\s*
+              ([a-zA-Z]*);$""",
         declaration, flags=re.X)
     if m:
       name = m.groups()[0]
@@ -267,7 +268,7 @@ def act_on_decl(declaration, comment, allowed_types):
     # Parse Variadic functions.
     m = re.match(
         r"""^.*internal::VariadicFunction\s*<\s*([^,]+),\s*([^,]+),\s*[^>]+>\s*
-              ([a-zA-Z]*)\s*=\s*{.*};$""",
+              ([a-zA-Z]*);$""",
         declaration, flags=re.X)
     if m:
       result, arg, name = m.groups()[:3]
@@ -276,15 +277,15 @@ def act_on_decl(declaration, comment, allowed_types):
 
     # Parse Variadic operator matchers.
     m = re.match(
-        r"""^.*VariadicOperatorMatcherFunc\s*<\s*([^,]+),\s*([^\s>]+)\s*>\s*
-              ([a-zA-Z]*)\s*=\s*{.*};$""",
+        r"""^.*VariadicOperatorMatcherFunc\s*<\s*([^,]+),\s*([^\s]+)\s*>\s*
+              ([a-zA-Z]*);$""",
         declaration, flags=re.X)
     if m:
       min_args, max_args, name = m.groups()[:3]
       if max_args == '1':
         add_matcher('*', name, 'Matcher<*>', comment)
         return
-      elif max_args == 'UINT_MAX':
+      elif max_args == 'std::numeric_limits::max()':
         add_matcher('*', name, 'Matcher<*>, ..., Matcher<*>', comment)
         return
 
diff --git a/docs/tools/dump_format_style.py b/docs/tools/dump_format_style.py
index e2571f46448d2b53f760e279b0ad48ab2161c6c3..1ca050e062b7496134709b159c0f5e81a74e54af 100755
--- a/docs/tools/dump_format_style.py
+++ b/docs/tools/dump_format_style.py
@@ -177,7 +177,8 @@ def read_options(header):
   for option in options:
     if not option.type in ['bool', 'unsigned', 'int', 'std::string',
                            'std::vector',
-                           'std::vector']:
+                           'std::vector',
+                           'std::vector']:
       if enums.has_key(option.type):
         option.enum = enums[option.type]
       elif nested_structs.has_key(option.type):
diff --git a/examples/analyzer-plugin/MainCallChecker.cpp b/examples/analyzer-plugin/MainCallChecker.cpp
index 7f08760e3d4cec1dfabc433e53fa8d23eee71dfc..74fe663e981f58ed50a9fb241d92702fb1b5e663 100644
--- a/examples/analyzer-plugin/MainCallChecker.cpp
+++ b/examples/analyzer-plugin/MainCallChecker.cpp
@@ -16,10 +16,8 @@ public:
 } // end anonymous namespace
 
 void MainCallChecker::checkPreStmt(const CallExpr *CE, CheckerContext &C) const {
-  const ProgramStateRef state = C.getState();
-  const LocationContext *LC = C.getLocationContext();
   const Expr *Callee = CE->getCallee();
-  const FunctionDecl *FD = state->getSVal(Callee, LC).getAsFunctionDecl();
+  const FunctionDecl *FD = C.getSVal(Callee).getAsFunctionDecl();
 
   if (!FD)
     return;
diff --git a/examples/clang-interpreter/CMakeLists.txt b/examples/clang-interpreter/CMakeLists.txt
index e7e59d930877680205adf611faca4f8d6d3a313e..3084238844802363545360fcb2065464007f4d2a 100644
--- a/examples/clang-interpreter/CMakeLists.txt
+++ b/examples/clang-interpreter/CMakeLists.txt
@@ -17,6 +17,7 @@ add_dependencies(clang-interpreter
   )
 
 target_link_libraries(clang-interpreter
+  PRIVATE
   clangBasic
   clangCodeGen
   clangDriver
diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h
index c72be56fdc712ab37426b7a4515bbfedc1a72d57..6468d1aa404f13bf412e822747792d6945e5bfbc 100644
--- a/include/clang-c/Index.h
+++ b/include/clang-c/Index.h
@@ -32,7 +32,7 @@
  * compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable.
  */
 #define CINDEX_VERSION_MAJOR 0
-#define CINDEX_VERSION_MINOR 43
+#define CINDEX_VERSION_MINOR 48
 
 #define CINDEX_VERSION_ENCODE(major, minor) ( \
       ((major) * 10000)                       \
@@ -333,6 +333,16 @@ CINDEX_LINKAGE void clang_CXIndex_setGlobalOptions(CXIndex, unsigned options);
  */
 CINDEX_LINKAGE unsigned clang_CXIndex_getGlobalOptions(CXIndex);
 
+/**
+ * \brief Sets the invocation emission path option in a CXIndex.
+ *
+ * The invocation emission path specifies a path which will contain log
+ * files for certain libclang invocations. A null value (default) implies that
+ * libclang invocations are not logged..
+ */
+CINDEX_LINKAGE void
+clang_CXIndex_setInvocationEmissionPathOption(CXIndex, const char *Path);
+
 /**
  * \defgroup CINDEX_FILES File manipulation routines
  *
@@ -393,6 +403,21 @@ clang_isFileMultipleIncludeGuarded(CXTranslationUnit tu, CXFile file);
 CINDEX_LINKAGE CXFile clang_getFile(CXTranslationUnit tu,
                                     const char *file_name);
 
+/**
+ * \brief Retrieve the buffer associated with the given file.
+ *
+ * \param tu the translation unit
+ *
+ * \param file the file for which to retrieve the buffer.
+ *
+ * \param size [out] if non-NULL, will be set to the size of the buffer.
+ *
+ * \returns a pointer to the buffer in memory that holds the contents of
+ * \p file, or a NULL pointer when the file is not loaded.
+ */
+CINDEX_LINKAGE const char *clang_getFileContents(CXTranslationUnit tu,
+                                                 CXFile file, size_t *size);
+
 /**
  * \brief Returns non-zero if the \c file1 and \c file2 point to the same file,
  * or they are both NULL.
@@ -2616,6 +2641,16 @@ CINDEX_LINKAGE enum CXCursorKind clang_getCursorKind(CXCursor);
  */
 CINDEX_LINKAGE unsigned clang_isDeclaration(enum CXCursorKind);
 
+/**
+ * \brief Determine whether the given declaration is invalid.
+ *
+ * A declaration is invalid if it could not be parsed successfully.
+ *
+ * \returns non-zero if the cursor represents a declaration and it is
+ * invalid, otherwise NULL.
+ */
+CINDEX_LINKAGE unsigned clang_isInvalidDeclaration(CXCursor);
+
 /**
  * \brief Determine whether the given cursor kind represents a simple
  * reference.
@@ -4056,6 +4091,89 @@ CINDEX_LINKAGE CXSourceRange clang_Cursor_getSpellingNameRange(CXCursor,
                                                           unsigned pieceIndex,
                                                           unsigned options);
 
+/**
+ * \brief Opaque pointer representing a policy that controls pretty printing
+ * for \c clang_getCursorPrettyPrinted.
+ */
+typedef void *CXPrintingPolicy;
+
+/**
+ * \brief Properties for the printing policy.
+ *
+ * See \c clang::PrintingPolicy for more information.
+ */
+enum CXPrintingPolicyProperty {
+  CXPrintingPolicy_Indentation,
+  CXPrintingPolicy_SuppressSpecifiers,
+  CXPrintingPolicy_SuppressTagKeyword,
+  CXPrintingPolicy_IncludeTagDefinition,
+  CXPrintingPolicy_SuppressScope,
+  CXPrintingPolicy_SuppressUnwrittenScope,
+  CXPrintingPolicy_SuppressInitializers,
+  CXPrintingPolicy_ConstantArraySizeAsWritten,
+  CXPrintingPolicy_AnonymousTagLocations,
+  CXPrintingPolicy_SuppressStrongLifetime,
+  CXPrintingPolicy_SuppressLifetimeQualifiers,
+  CXPrintingPolicy_SuppressTemplateArgsInCXXConstructors,
+  CXPrintingPolicy_Bool,
+  CXPrintingPolicy_Restrict,
+  CXPrintingPolicy_Alignof,
+  CXPrintingPolicy_UnderscoreAlignof,
+  CXPrintingPolicy_UseVoidForZeroParams,
+  CXPrintingPolicy_TerseOutput,
+  CXPrintingPolicy_PolishForDeclaration,
+  CXPrintingPolicy_Half,
+  CXPrintingPolicy_MSWChar,
+  CXPrintingPolicy_IncludeNewlines,
+  CXPrintingPolicy_MSVCFormatting,
+  CXPrintingPolicy_ConstantsAsWritten,
+  CXPrintingPolicy_SuppressImplicitBase,
+  CXPrintingPolicy_FullyQualifiedName,
+
+  CXPrintingPolicy_LastProperty = CXPrintingPolicy_FullyQualifiedName
+};
+
+/**
+ * \brief Get a property value for the given printing policy.
+ */
+CINDEX_LINKAGE unsigned
+clang_PrintingPolicy_getProperty(CXPrintingPolicy Policy,
+                                 enum CXPrintingPolicyProperty Property);
+
+/**
+ * \brief Set a property value for the given printing policy.
+ */
+CINDEX_LINKAGE void clang_PrintingPolicy_setProperty(CXPrintingPolicy Policy,
+                                                     enum CXPrintingPolicyProperty Property,
+                                                     unsigned Value);
+
+/**
+ * \brief Retrieve the default policy for the cursor.
+ *
+ * The policy should be released after use with \c
+ * clang_PrintingPolicy_dispose.
+ */
+CINDEX_LINKAGE CXPrintingPolicy clang_getCursorPrintingPolicy(CXCursor);
+
+/**
+ * \brief Release a printing policy.
+ */
+CINDEX_LINKAGE void clang_PrintingPolicy_dispose(CXPrintingPolicy Policy);
+
+/**
+ * \brief Pretty print declarations.
+ *
+ * \param Cursor The cursor representing a declaration.
+ *
+ * \param Policy The policy to control the entities being printed. If
+ * NULL, a default policy is used.
+ *
+ * \returns The pretty printed declaration or the empty string for
+ * other cursors.
+ */
+CINDEX_LINKAGE CXString clang_getCursorPrettyPrinted(CXCursor Cursor,
+                                                     CXPrintingPolicy Policy);
+
 /**
  * \brief Retrieve the display name for the entity referenced by this cursor.
  *
@@ -4441,6 +4559,12 @@ CINDEX_LINKAGE unsigned clang_CXXMethod_isStatic(CXCursor C);
  */
 CINDEX_LINKAGE unsigned clang_CXXMethod_isVirtual(CXCursor C);
 
+/**
+ * \brief Determine if a C++ record is abstract, i.e. whether a class or struct
+ * has a pure virtual member function.
+ */
+CINDEX_LINKAGE unsigned clang_CXXRecord_isAbstract(CXCursor C);
+
 /**
  * \brief Determine if an enum declaration refers to a scoped enum.
  */
@@ -5120,7 +5244,14 @@ enum CXCodeComplete_Flags {
    * \brief Whether to include brief documentation within the set of code
    * completions returned.
    */
-  CXCodeComplete_IncludeBriefComments = 0x04
+  CXCodeComplete_IncludeBriefComments = 0x04,
+
+  /**
+   * Whether to speed up completion by omitting top- or namespace-level entities
+   * defined in the preamble. There's no guarantee any particular entity is
+   * omitted. This may be useful if the headers are indexed externally.
+   */
+  CXCodeComplete_SkipPreamble = 0x08
 };
 
 /**
@@ -5961,6 +6092,9 @@ typedef struct {
 
 /**
  * \brief Data for IndexerCallbacks#indexEntityReference.
+ *
+ * This may be deprecated in a future version as this duplicates
+ * the \c CXSymbolRole_Implicit bit in \c CXSymbolRole.
  */
 typedef enum {
   /**
@@ -5974,6 +6108,25 @@ typedef enum {
   CXIdxEntityRef_Implicit = 2
 } CXIdxEntityRefKind;
 
+/**
+ * \brief Roles that are attributed to symbol occurrences.
+ *
+ * Internal: this currently mirrors low 9 bits of clang::index::SymbolRole with
+ * higher bits zeroed. These high bits may be exposed in the future.
+ */
+typedef enum {
+  CXSymbolRole_None = 0,
+  CXSymbolRole_Declaration = 1 << 0,
+  CXSymbolRole_Definition = 1 << 1,
+  CXSymbolRole_Reference = 1 << 2,
+  CXSymbolRole_Read = 1 << 3,
+  CXSymbolRole_Write = 1 << 4,
+  CXSymbolRole_Call = 1 << 5,
+  CXSymbolRole_Dynamic = 1 << 6,
+  CXSymbolRole_AddressOf = 1 << 7,
+  CXSymbolRole_Implicit = 1 << 8
+} CXSymbolRole;
+
 /**
  * \brief Data for IndexerCallbacks#indexEntityReference.
  */
@@ -6004,6 +6157,10 @@ typedef struct {
    * \brief Lexical container context of the reference.
    */
   const CXIdxContainerInfo *container;
+  /**
+   * \brief Sets of symbol roles of the reference.
+   */
+  CXSymbolRole role;
 } CXIdxEntityRefInfo;
 
 /**
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index 09035be0219f93531323984b429e844e2f7f5488..a5b090d355d8185a90cebab2ce4c2eaffab22235 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -1,4 +1,4 @@
-//===--- ASTContext.h - Context to hold long-lived AST nodes ----*- C++ -*-===//
+//===- ASTContext.h - Context to hold long-lived AST nodes ------*- C++ -*-===//
 //
 //                     The LLVM Compiler Infrastructure
 //
@@ -6,10 +6,10 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-///
+//
 /// \file
 /// \brief Defines the clang::ASTContext interface.
-///
+//
 //===----------------------------------------------------------------------===//
 
 #ifndef LLVM_CLANG_AST_ASTCONTEXT_H
@@ -19,8 +19,8 @@
 #include "clang/AST/CanonicalType.h"
 #include "clang/AST/CommentCommandTraits.h"
 #include "clang/AST/Decl.h"
-#include "clang/AST/DeclarationName.h"
 #include "clang/AST/DeclBase.h"
+#include "clang/AST/DeclarationName.h"
 #include "clang/AST/ExternalASTSource.h"
 #include "clang/AST/NestedNameSpecifier.h"
 #include "clang/AST/PrettyPrinter.h"
@@ -30,10 +30,9 @@
 #include "clang/AST/Type.h"
 #include "clang/Basic/AddressSpaces.h"
 #include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LLVM.h"
 #include "clang/Basic/LangOptions.h"
 #include "clang/Basic/Linkage.h"
-#include "clang/Basic/LLVM.h"
-#include "clang/Basic/Module.h"
 #include "clang/Basic/OperatorKinds.h"
 #include "clang/Basic/PartialDiagnostic.h"
 #include "clang/Basic/SanitizerBlacklist.h"
@@ -46,17 +45,17 @@
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/FoldingSet.h"
 #include "llvm/ADT/IntrusiveRefCntPtr.h"
-#include "llvm/ADT/iterator_range.h"
 #include "llvm/ADT/MapVector.h"
 #include "llvm/ADT/None.h"
 #include "llvm/ADT/Optional.h"
 #include "llvm/ADT/PointerIntPair.h"
 #include "llvm/ADT/PointerUnion.h"
-#include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/TinyPtrVector.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/TinyPtrVector.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/ADT/iterator_range.h"
 #include "llvm/Support/AlignOf.h"
 #include "llvm/Support/Allocator.h"
 #include "llvm/Support/Casting.h"
@@ -66,7 +65,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -76,49 +74,72 @@ namespace llvm {
 
 struct fltSemantics;
 
-} // end namespace llvm
+} // namespace llvm
 
 namespace clang {
 
+class APValue;
 class ASTMutationListener;
 class ASTRecordLayout;
 class AtomicExpr;
 class BlockExpr;
+class BuiltinTemplateDecl;
 class CharUnits;
 class CXXABI;
+class CXXConstructorDecl;
+class CXXMethodDecl;
+class CXXRecordDecl;
 class DiagnosticsEngine;
 class Expr;
+class MangleContext;
 class MangleNumberingContext;
 class MaterializeTemporaryExpr;
-// Decls
-class MangleContext;
+class MemberSpecializationInfo;
+class Module;
+class ObjCCategoryDecl;
+class ObjCCategoryImplDecl;
+class ObjCContainerDecl;
+class ObjCImplDecl;
+class ObjCImplementationDecl;
+class ObjCInterfaceDecl;
 class ObjCIvarDecl;
+class ObjCMethodDecl;
 class ObjCPropertyDecl;
+class ObjCPropertyImplDecl;
+class ObjCProtocolDecl;
+class ObjCTypeParamDecl;
+class Preprocessor;
+class Stmt;
+class StoredDeclsMap;
+class TemplateDecl;
+class TemplateParameterList;
+class TemplateTemplateParmDecl;
+class TemplateTypeParmDecl;
 class UnresolvedSetIterator;
-class UsingDecl;
 class UsingShadowDecl;
+class VarTemplateDecl;
 class VTableContextBase;
 
 namespace Builtin {
 
-  class Context;
+class Context;
 
-} // end namespace Builtin
+} // namespace Builtin
 
 enum BuiltinTemplateKind : int;
 
 namespace comments {
 
-  class FullComment;
+class FullComment;
 
-} // end namespace comments
+} // namespace comments
 
 struct TypeInfo {
-  uint64_t Width;
-  unsigned Align;
+  uint64_t Width = 0;
+  unsigned Align = 0;
   bool AlignIsRequired : 1;
 
-  TypeInfo() : Width(0), Align(0), AlignIsRequired(false) {}
+  TypeInfo() : AlignIsRequired(false) {}
   TypeInfo(uint64_t Width, unsigned Align, bool AlignIsRequired)
       : Width(Width), Align(Align), AlignIsRequired(AlignIsRequired) {}
 };
@@ -126,7 +147,7 @@ struct TypeInfo {
 /// \brief Holds long-lived AST nodes (such as types and decls) that can be
 /// referred to throughout the semantic analysis of a file.
 class ASTContext : public RefCountedBase {
-  ASTContext &this_() { return *this; }
+  friend class NestedNameSpecifier;
 
   mutable SmallVector Types;
   mutable llvm::FoldingSet ExtQualNodes;
@@ -189,8 +210,7 @@ class ASTContext : public RefCountedBase {
   ///
   /// This set is managed by the NestedNameSpecifier class.
   mutable llvm::FoldingSet NestedNameSpecifiers;
-  mutable NestedNameSpecifier *GlobalNestedNameSpecifier;
-  friend class NestedNameSpecifier;
+  mutable NestedNameSpecifier *GlobalNestedNameSpecifier = nullptr;
 
   /// \brief A cache mapping from RecordDecls to ASTRecordLayouts.
   ///
@@ -201,7 +221,7 @@ class ASTContext : public RefCountedBase {
     ObjCLayouts;
 
   /// \brief A cache from types to size and alignment information.
-  typedef llvm::DenseMap TypeInfoMap;
+  using TypeInfoMap = llvm::DenseMap;
   mutable TypeInfoMap MemoizedTypeInfo;
 
   /// \brief A cache mapping from CXXRecordDecls to key functions.
@@ -235,7 +255,7 @@ class ASTContext : public RefCountedBase {
 
   public:
     CanonicalTemplateTemplateParm(TemplateTemplateParmDecl *Parm)
-      : Parm(Parm) { }
+        : Parm(Parm) {}
 
     TemplateTemplateParmDecl *getParam() const { return Parm; }
 
@@ -251,32 +271,32 @@ class ASTContext : public RefCountedBase {
     getCanonicalTemplateTemplateParmDecl(TemplateTemplateParmDecl *TTP) const;
 
   /// \brief The typedef for the __int128_t type.
-  mutable TypedefDecl *Int128Decl;
+  mutable TypedefDecl *Int128Decl = nullptr;
 
   /// \brief The typedef for the __uint128_t type.
-  mutable TypedefDecl *UInt128Decl;
+  mutable TypedefDecl *UInt128Decl = nullptr;
 
   /// \brief The typedef for the target specific predefined
   /// __builtin_va_list type.
-  mutable TypedefDecl *BuiltinVaListDecl;
+  mutable TypedefDecl *BuiltinVaListDecl = nullptr;
 
   /// The typedef for the predefined \c __builtin_ms_va_list type.
-  mutable TypedefDecl *BuiltinMSVaListDecl;
+  mutable TypedefDecl *BuiltinMSVaListDecl = nullptr;
 
   /// \brief The typedef for the predefined \c id type.
-  mutable TypedefDecl *ObjCIdDecl;
+  mutable TypedefDecl *ObjCIdDecl = nullptr;
 
   /// \brief The typedef for the predefined \c SEL type.
-  mutable TypedefDecl *ObjCSelDecl;
+  mutable TypedefDecl *ObjCSelDecl = nullptr;
 
   /// \brief The typedef for the predefined \c Class type.
-  mutable TypedefDecl *ObjCClassDecl;
+  mutable TypedefDecl *ObjCClassDecl = nullptr;
 
   /// \brief The typedef for the predefined \c Protocol class in Objective-C.
-  mutable ObjCInterfaceDecl *ObjCProtocolClassDecl;
+  mutable ObjCInterfaceDecl *ObjCProtocolClassDecl = nullptr;
 
   /// \brief The typedef for the predefined 'BOOL' type.
-  mutable TypedefDecl *BOOLDecl;
+  mutable TypedefDecl *BOOLDecl = nullptr;
 
   // Typedefs which may be provided defining the structure of Objective-C
   // pseudo-builtins
@@ -300,42 +320,42 @@ class ASTContext : public RefCountedBase {
   mutable IdentifierInfo *TypePackElementName = nullptr;
 
   QualType ObjCConstantStringType;
-  mutable RecordDecl *CFConstantStringTagDecl;
-  mutable TypedefDecl *CFConstantStringTypeDecl;
+  mutable RecordDecl *CFConstantStringTagDecl = nullptr;
+  mutable TypedefDecl *CFConstantStringTypeDecl = nullptr;
 
   mutable QualType ObjCSuperType;
 
   QualType ObjCNSStringType;
 
   /// \brief The typedef declaration for the Objective-C "instancetype" type.
-  TypedefDecl *ObjCInstanceTypeDecl;
+  TypedefDecl *ObjCInstanceTypeDecl = nullptr;
 
   /// \brief The type for the C FILE type.
-  TypeDecl *FILEDecl;
+  TypeDecl *FILEDecl = nullptr;
 
   /// \brief The type for the C jmp_buf type.
-  TypeDecl *jmp_bufDecl;
+  TypeDecl *jmp_bufDecl = nullptr;
 
   /// \brief The type for the C sigjmp_buf type.
-  TypeDecl *sigjmp_bufDecl;
+  TypeDecl *sigjmp_bufDecl = nullptr;
 
   /// \brief The type for the C ucontext_t type.
-  TypeDecl *ucontext_tDecl;
+  TypeDecl *ucontext_tDecl = nullptr;
 
   /// \brief Type for the Block descriptor for Blocks CodeGen.
   ///
   /// Since this is only used for generation of debug info, it is not
   /// serialized.
-  mutable RecordDecl *BlockDescriptorType;
+  mutable RecordDecl *BlockDescriptorType = nullptr;
 
   /// \brief Type for the Block descriptor for Blocks CodeGen.
   ///
   /// Since this is only used for generation of debug info, it is not
   /// serialized.
-  mutable RecordDecl *BlockDescriptorExtendedType;
+  mutable RecordDecl *BlockDescriptorExtendedType = nullptr;
 
   /// \brief Declaration for the CUDA cudaConfigureCall function.
-  FunctionDecl *cudaConfigureCallDecl;
+  FunctionDecl *cudaConfigureCallDecl = nullptr;
 
   /// \brief Keeps track of all declaration attributes.
   ///
@@ -365,12 +385,19 @@ class ASTContext : public RefCountedBase {
   };
   llvm::DenseMap ModuleInitializers;
 
+  ASTContext &this_() { return *this; }
+
 public:
   /// \brief A type synonym for the TemplateOrInstantiation mapping.
-  typedef llvm::PointerUnion
-  TemplateOrSpecializationInfo;
+  using TemplateOrSpecializationInfo =
+      llvm::PointerUnion;
 
 private:
+  friend class ASTDeclReader;
+  friend class ASTReader;
+  friend class ASTWriter;
+  friend class CXXRecordDecl;
+
   /// \brief A mapping to contain the template or declaration that
   /// a variable declaration describes or was instantiated from,
   /// respectively.
@@ -440,7 +467,7 @@ private:
   /// Since most C++ member functions aren't virtual and therefore
   /// don't override anything, we store the overridden functions in
   /// this map on the side rather than within the CXXMethodDecl structure.
-  typedef llvm::TinyPtrVector CXXMethodVector;
+  using CXXMethodVector = llvm::TinyPtrVector;
   llvm::DenseMap OverriddenMethods;
 
   /// \brief Mapping from each declaration context to its corresponding
@@ -456,16 +483,16 @@ private:
 
   /// \brief Mapping that stores parameterIndex values for ParmVarDecls when
   /// that value exceeds the bitfield size of ParmVarDeclBits.ParameterIndex.
-  typedef llvm::DenseMap ParameterIndexTable;
+  using ParameterIndexTable = llvm::DenseMap;
   ParameterIndexTable ParamIndices;
 
-  ImportDecl *FirstLocalImport;
-  ImportDecl *LastLocalImport;
+  ImportDecl *FirstLocalImport = nullptr;
+  ImportDecl *LastLocalImport = nullptr;
 
   TranslationUnitDecl *TUDecl;
-  mutable ExternCContextDecl *ExternCContext;
-  mutable BuiltinTemplateDecl *MakeIntegerSeqDecl;
-  mutable BuiltinTemplateDecl *TypePackElementDecl;
+  mutable ExternCContextDecl *ExternCContext = nullptr;
+  mutable BuiltinTemplateDecl *MakeIntegerSeqDecl = nullptr;
+  mutable BuiltinTemplateDecl *TypePackElementDecl = nullptr;
 
   /// \brief The associated SourceManager object.
   SourceManager &SourceMgr;
@@ -496,19 +523,14 @@ private:
   CXXABI *createCXXABI(const TargetInfo &T);
 
   /// \brief The logical -> physical address space map.
-  const LangASMap *AddrSpaceMap;
+  const LangASMap *AddrSpaceMap = nullptr;
 
   /// \brief Address space map mangling must be used with language specific
   /// address spaces (e.g. OpenCL/CUDA)
   bool AddrSpaceMapMangling;
 
-  friend class ASTDeclReader;
-  friend class ASTReader;
-  friend class ASTWriter;
-  friend class CXXRecordDecl;
-
-  const TargetInfo *Target;
-  const TargetInfo *AuxTarget;
+  const TargetInfo *Target = nullptr;
+  const TargetInfo *AuxTarget = nullptr;
   clang::PrintingPolicy PrintingPolicy;
 
 public:
@@ -517,31 +539,33 @@ public:
   Builtin::Context &BuiltinInfo;
   mutable DeclarationNameTable DeclarationNames;
   IntrusiveRefCntPtr ExternalSource;
-  ASTMutationListener *Listener;
+  ASTMutationListener *Listener = nullptr;
 
   /// \brief Contains parents of a node.
-  typedef llvm::SmallVector ParentVector;
+  using ParentVector = llvm::SmallVector;
 
   /// \brief Maps from a node to its parents. This is used for nodes that have
   /// pointer identity only, which are more common and we can save space by
   /// only storing a unique pointer to them.
-  typedef llvm::DenseMap> ParentMapPointers;
+  using ParentMapPointers =
+      llvm::DenseMap>;
 
   /// Parent map for nodes without pointer identity. We store a full
   /// DynTypedNode for all keys.
-  typedef llvm::DenseMap<
-      ast_type_traits::DynTypedNode,
-      llvm::PointerUnion4>
-      ParentMapOtherNodes;
+  using ParentMapOtherNodes =
+      llvm::DenseMap>;
 
   /// Container for either a single DynTypedNode or for an ArrayRef to
   /// DynTypedNode. For use with ParentMap.
   class DynTypedNodeList {
-    typedef ast_type_traits::DynTypedNode DynTypedNode;
+    using DynTypedNode = ast_type_traits::DynTypedNode;
+
     llvm::AlignedCharArrayUnion> Storage;
     bool IsSingleNode;
@@ -550,6 +574,7 @@ public:
     DynTypedNodeList(const DynTypedNode &N) : IsSingleNode(true) {
       new (Storage.buffer) DynTypedNode(N);
     }
+
     DynTypedNodeList(ArrayRef A) : IsSingleNode(false) {
       new (Storage.buffer) ArrayRef(A);
     }
@@ -628,13 +653,14 @@ public:
   template  T *Allocate(size_t Num = 1) const {
     return static_cast(Allocate(Num * sizeof(T), alignof(T)));
   }
-  void Deallocate(void *Ptr) const { }
+  void Deallocate(void *Ptr) const {}
 
   /// Return the total amount of physical memory allocated for representing
   /// AST nodes and type information.
   size_t getASTAllocatedMemory() const {
     return BumpAlloc.getTotalMemory();
   }
+
   /// Return the total memory used for various side tables.
   size_t getSideTableAllocatedMemory() const;
 
@@ -651,6 +677,7 @@ public:
   /// Returns empty type if there is no appropriate target types.
   QualType getIntTypeForBitwidth(unsigned DestWidth,
                                  unsigned Signed) const;
+
   /// getRealTypeForBitwidth -
   /// sets floating point QualTy according to specified bitwidth.
   /// Returns empty type if there is no appropriate target types.
@@ -678,7 +705,7 @@ public:
   RawCommentList Comments;
 
   /// \brief True if comments are already loaded from ExternalASTSource.
-  mutable bool CommentsLoaded;
+  mutable bool CommentsLoaded = false;
 
   class RawCommentAndCacheFlags {
   public:
@@ -757,28 +784,28 @@ public:
   void addComment(const RawComment &RC) {
     assert(LangOpts.RetainCommentsFromSystemHeaders ||
            !SourceMgr.isInSystemHeader(RC.getSourceRange().getBegin()));
-    Comments.addComment(RC, BumpAlloc);
+    Comments.addComment(RC, LangOpts.CommentOpts, BumpAlloc);
   }
 
   /// \brief Return the documentation comment attached to a given declaration.
-  /// Returns NULL if no comment is attached.
+  /// Returns nullptr if no comment is attached.
   ///
-  /// \param OriginalDecl if not NULL, is set to declaration AST node that had
-  /// the comment, if the comment we found comes from a redeclaration.
+  /// \param OriginalDecl if not nullptr, is set to declaration AST node that
+  /// had the comment, if the comment we found comes from a redeclaration.
   const RawComment *
   getRawCommentForAnyRedecl(const Decl *D,
                             const Decl **OriginalDecl = nullptr) const;
 
   /// Return parsed documentation comment attached to a given declaration.
-  /// Returns NULL if no comment is attached.
+  /// Returns nullptr if no comment is attached.
   ///
-  /// \param PP the Preprocessor used with this TU.  Could be NULL if
+  /// \param PP the Preprocessor used with this TU.  Could be nullptr if
   /// preprocessor is not available.
   comments::FullComment *getCommentForDecl(const Decl *D,
                                            const Preprocessor *PP) const;
 
   /// Return parsed documentation comment attached to a given declaration.
-  /// Returns NULL if no comment is attached. Does not look at any
+  /// Returns nullptr if no comment is attached. Does not look at any
   /// redeclarations of the declaration.
   comments::FullComment *getLocalCommentForDeclUncached(const Decl *D) const;
 
@@ -790,16 +817,16 @@ private:
 
   /// \brief Iterator that visits import declarations.
   class import_iterator {
-    ImportDecl *Import;
+    ImportDecl *Import = nullptr;
 
   public:
-    typedef ImportDecl               *value_type;
-    typedef ImportDecl               *reference;
-    typedef ImportDecl               *pointer;
-    typedef int                       difference_type;
-    typedef std::forward_iterator_tag iterator_category;
+    using value_type = ImportDecl *;
+    using reference = ImportDecl *;
+    using pointer = ImportDecl *;
+    using difference_type = int;
+    using iterator_category = std::forward_iterator_tag;
 
-    import_iterator() : Import() {}
+    import_iterator() = default;
     explicit import_iterator(ImportDecl *Import) : Import(Import) {}
 
     reference operator*() const { return Import; }
@@ -878,7 +905,7 @@ public:
   void setInstantiatedFromUnnamedFieldDecl(FieldDecl *Inst, FieldDecl *Tmpl);
 
   // Access to the set of methods overridden by the given C++ method.
-  typedef CXXMethodVector::const_iterator overridden_cxx_method_iterator;
+  using overridden_cxx_method_iterator = CXXMethodVector::const_iterator;
   overridden_cxx_method_iterator
   overridden_methods_begin(const CXXMethodDecl *Method) const;
 
@@ -886,8 +913,10 @@ public:
   overridden_methods_end(const CXXMethodDecl *Method) const;
 
   unsigned overridden_methods_size(const CXXMethodDecl *Method) const;
-  typedef llvm::iterator_range
-      overridden_method_range;
+
+  using overridden_method_range =
+      llvm::iterator_range;
+
   overridden_method_range overridden_methods(const CXXMethodDecl *Method) const;
 
   /// \brief Note that the given C++ \p Method overrides the given \p
@@ -914,7 +943,8 @@ public:
     return Import->NextLocalImport;
   }
 
-  typedef llvm::iterator_range import_range;
+  using import_range = llvm::iterator_range;
+
   import_range local_imports() const {
     return import_range(import_iterator(FirstLocalImport), import_iterator());
   }
@@ -931,6 +961,7 @@ public:
   /// and should be visible whenever \p M is visible.
   void mergeDefinitionIntoModule(NamedDecl *ND, Module *M,
                                  bool NotifyListeners = true);
+
   /// \brief Clean up the merged definition list. Call this if you might have
   /// added duplicates into the list.
   void deduplicateMergedDefinitonsFor(NamedDecl *ND);
@@ -1131,6 +1162,13 @@ public:
   /// \brief Change the result type of a function type once it is deduced.
   void adjustDeducedFunctionResultType(FunctionDecl *FD, QualType ResultType);
 
+  /// Get a function type and produce the equivalent function type with the
+  /// specified exception specification. Type sugar that can be present on a
+  /// declaration of a function with an exception specification is permitted
+  /// and preserved. Other type sugar (for instance, typedefs) is not.
+  QualType getFunctionTypeWithExceptionSpec(
+      QualType Orig, const FunctionProtoType::ExceptionSpecInfo &ESI);
+
   /// \brief Determine whether two function types are the same, ignoring
   /// exception specifications in cases where they're part of the type.
   bool hasSameFunctionTypeIgnoringExceptionSpec(QualType T, QualType U);
@@ -1141,6 +1179,10 @@ public:
                            const FunctionProtoType::ExceptionSpecInfo &ESI,
                            bool AsWritten = false);
 
+  /// Determine whether a type is a class that should be detructed in the
+  /// callee function.
+  bool isParamDestroyedInCallee(QualType T) const;
+
   /// \brief Return the uniqued reference to the type for a complex
   /// number with the specified element type.
   QualType getComplexType(QualType T) const;
@@ -1185,6 +1227,7 @@ public:
 
   /// \brief Return a read_only pipe type for the specified type.
   QualType getReadPipeType(QualType T) const;
+
   /// \brief Return a write_only pipe type for the specified type.
   QualType getWritePipeType(QualType T) const;
 
@@ -1192,9 +1235,16 @@ public:
   /// pointer to blocks.
   QualType getBlockDescriptorExtendedType() const;
 
+  /// Map an AST Type to an OpenCLTypeKind enum value.
+  TargetInfo::OpenCLTypeKind getOpenCLTypeKind(const Type *T) const;
+
+  /// Get address space for OpenCL type.
+  LangAS getOpenCLTypeAddrSpace(const Type *T) const;
+
   void setcudaConfigureCallDecl(FunctionDecl *FD) {
     cudaConfigureCallDecl = FD;
   }
+
   FunctionDecl *getcudaConfigureCallDecl() {
     return cudaConfigureCallDecl;
   }
@@ -1202,7 +1252,6 @@ public:
   /// Returns true iff we need copy/dispose helpers for the given type.
   bool BlockRequiresCopying(QualType Ty, const VarDecl *D);
 
-
   /// Returns true, if given type has a known lifetime. HasByrefExtendedLayout is set
   /// to false in this case. If HasByrefExtendedLayout returns true, byref variable
   /// has extended lifetime.
@@ -1410,6 +1459,7 @@ public:
                                 QualType Canonical = QualType()) const;
 
   bool ObjCObjectAdoptsQTypeProtocols(QualType QT, ObjCInterfaceDecl *Decl);
+
   /// QIdProtocolsAdoptObjCObjectProtocols - Checks that protocols in
   /// QT's qualified-id protocol list adopt all protocols in IDecl's list
   /// of protocols.
@@ -1440,7 +1490,7 @@ public:
   /// \brief C++11 deduction pattern for 'auto &&' type.
   QualType getAutoRRefDeductType() const;
 
-  /// \brief C++1z deduced class template specialization type.
+  /// \brief C++17 deduced class template specialization type.
   QualType getDeducedTemplateSpecializationType(TemplateName Template,
                                                 QualType DeducedType,
                                                 bool IsDependent) const;
@@ -1902,10 +1952,17 @@ public:
                                         const TemplateArgument &ArgPack) const;
 
   enum GetBuiltinTypeError {
-    GE_None,              ///< No error
-    GE_Missing_stdio,     ///< Missing a type from 
-    GE_Missing_setjmp,    ///< Missing a type from 
-    GE_Missing_ucontext   ///< Missing a type from 
+    /// No error
+    GE_None,
+
+    /// Missing a type from 
+    GE_Missing_stdio,
+
+    /// Missing a type from 
+    GE_Missing_setjmp,
+
+    /// Missing a type from 
+    GE_Missing_ucontext
   };
 
   /// \brief Return the type for the specified builtin.
@@ -2056,7 +2113,7 @@ public:
   getASTObjCImplementationLayout(const ObjCImplementationDecl *D) const;
 
   /// \brief Get our current best idea for the key function of the
-  /// given record decl, or NULL if there isn't one.
+  /// given record decl, or nullptr if there isn't one.
   ///
   /// The key function is, according to the Itanium C++ ABI section 5.2.3:
   ///   ...the first non-pure virtual function that is not inline at the
@@ -2109,6 +2166,10 @@ public:
   void CollectInheritedProtocols(const Decl *CDecl,
                           llvm::SmallPtrSet &Protocols);
 
+  /// \brief Return true if the specified type has unique object representations
+  /// according to (C++17 [meta.unary.prop]p9)
+  bool hasUniqueObjectRepresentations(QualType Ty) const;
+
   //===--------------------------------------------------------------------===//
   //                            Type Operators
   //===--------------------------------------------------------------------===//
@@ -2140,7 +2201,6 @@ public:
   bool hasSameType(QualType T1, QualType T2) const {
     return getCanonicalType(T1) == getCanonicalType(T2);
   }
-
   bool hasSameType(const Type *T1, const Type *T2) const {
     return getCanonicalType(T1) == getCanonicalType(T2);
   }
@@ -2392,12 +2452,15 @@ public:
   bool isObjCIdType(QualType T) const {
     return T == getObjCIdType();
   }
+
   bool isObjCClassType(QualType T) const {
     return T == getObjCClassType();
   }
+
   bool isObjCSelType(QualType T) const {
     return T == getObjCSelType();
   }
+
   bool ObjCQualifiedIdTypesAreCompatible(QualType LHS, QualType RHS,
                                          bool ForCompare);
 
@@ -2490,12 +2553,13 @@ public:
 
   bool isSentinelNullExpr(const Expr *E);
 
-  /// \brief Get the implementation of the ObjCInterfaceDecl \p D, or NULL if
+  /// \brief Get the implementation of the ObjCInterfaceDecl \p D, or nullptr if
   /// none exists.
   ObjCImplementationDecl *getObjCImplementation(ObjCInterfaceDecl *D);
-  /// \brief Get the implementation of the ObjCCategoryDecl \p D, or NULL if
+
+  /// \brief Get the implementation of the ObjCCategoryDecl \p D, or nullptr if
   /// none exists.
-  ObjCCategoryImplDecl   *getObjCImplementation(ObjCCategoryDecl *D);
+  ObjCCategoryImplDecl *getObjCImplementation(ObjCCategoryDecl *D);
 
   /// \brief Return true if there is at least one \@implementation in the TU.
   bool AnyObjCImplementation() {
@@ -2505,6 +2569,7 @@ public:
   /// \brief Set the implementation of ObjCInterfaceDecl.
   void setObjCImplementation(ObjCInterfaceDecl *IFaceD,
                              ObjCImplementationDecl *ImplD);
+
   /// \brief Set the implementation of ObjCCategoryDecl.
   void setObjCImplementation(ObjCCategoryDecl *CatD,
                              ObjCCategoryImplDecl *ImplD);
@@ -2524,8 +2589,9 @@ public:
 
   /// \brief Set the copy inialization expression of a block var decl.
   void setBlockVarCopyInits(VarDecl*VD, Expr* Init);
+
   /// \brief Get the copy initialization expression of the VarDecl \p VD, or
-  /// NULL if none exists.
+  /// nullptr if none exists.
   Expr *getBlockVarCopyInits(const VarDecl* VD);
 
   /// \brief Allocate an uninitialized TypeSourceInfo.
@@ -2578,6 +2644,12 @@ public:
   /// it is not used.
   bool DeclMustBeEmitted(const Decl *D);
 
+  /// \brief Visits all versions of a multiversioned function with the passed
+  /// predicate.
+  void forEachMultiversionedFunctionVersion(
+      const FunctionDecl *FD,
+      llvm::function_ref Pred) const;
+
   const CXXConstructorDecl *
   getCopyConstructorForExceptionObject(CXXRecordDecl *RD);
 
@@ -2694,6 +2766,7 @@ private:
                                        const FieldDecl *Field,
                                        bool includeVBases = true,
                                        QualType *NotEncodedT=nullptr) const;
+
 public:
   // Adds the encoding of a method parameter or return type.
   void getObjCEncodingForMethodParameter(Decl::ObjCDeclQualifier QT,
@@ -2705,11 +2778,19 @@ public:
   bool isMSStaticDataMemberInlineDefinition(const VarDecl *VD) const;
 
   enum class InlineVariableDefinitionKind {
-    None,        ///< Not an inline variable.
-    Weak,        ///< Weak definition of inline variable.
-    WeakUnknown, ///< Weak for now, might become strong later in this TU.
-    Strong       ///< Strong definition.
+    /// Not an inline variable.
+    None,
+
+    /// Weak definition of inline variable.
+    Weak,
+
+    /// Weak for now, might become strong later in this TU.
+    WeakUnknown,
+
+    /// Strong definition.
+    Strong
   };
+
   /// \brief Determine whether a definition of this inline variable should
   /// be treated as a weak or strong definition. For compatibility with
   /// C++14 and before, for a constexpr static data member, if there is an
@@ -2719,6 +2800,9 @@ public:
   getInlineVariableDefinitionKind(const VarDecl *VD) const;
 
 private:
+  friend class DeclarationNameTable;
+  friend class DeclContext;
+
   const ASTRecordLayout &
   getObjCLayout(const ObjCInterfaceDecl *D,
                 const ObjCImplementationDecl *Impl) const;
@@ -2731,26 +2815,23 @@ private:
   // into the datastructures which avoids this mess during deallocation but is
   // wasteful of memory, and here we require a lot of error prone book keeping
   // in order to track and run destructors while we're tearing things down.
-  typedef llvm::SmallVector, 16>
-      DeallocationFunctionsAndArguments;
+  using DeallocationFunctionsAndArguments =
+      llvm::SmallVector, 16>;
   DeallocationFunctionsAndArguments Deallocations;
 
   // FIXME: This currently contains the set of StoredDeclMaps used
   // by DeclContext objects.  This probably should not be in ASTContext,
   // but we include it here so that ASTContext can quickly deallocate them.
-  llvm::PointerIntPair LastSDM;
-
-  friend class DeclContext;
-  friend class DeclarationNameTable;
-
-  void ReleaseDeclContextMaps();
-  void ReleaseParentMapEntries();
+  llvm::PointerIntPair LastSDM;
 
   std::unique_ptr PointerParents;
   std::unique_ptr OtherParents;
 
   std::unique_ptr VTContext;
 
+  void ReleaseDeclContextMaps();
+  void ReleaseParentMapEntries();
+
 public:
   enum PragmaSectionFlag : unsigned {
     PSF_None = 0,
@@ -2770,27 +2851,26 @@ public:
     SectionInfo(DeclaratorDecl *Decl,
                 SourceLocation PragmaSectionLocation,
                 int SectionFlags)
-      : Decl(Decl),
-        PragmaSectionLocation(PragmaSectionLocation),
-        SectionFlags(SectionFlags) {}
+        : Decl(Decl), PragmaSectionLocation(PragmaSectionLocation),
+          SectionFlags(SectionFlags) {}
   };
 
   llvm::StringMap SectionInfos;
 };
 
 /// \brief Utility function for constructing a nullary selector.
-static inline Selector GetNullarySelector(StringRef name, ASTContext& Ctx) {
+inline Selector GetNullarySelector(StringRef name, ASTContext &Ctx) {
   IdentifierInfo* II = &Ctx.Idents.get(name);
   return Ctx.Selectors.getSelector(0, &II);
 }
 
 /// \brief Utility function for constructing an unary selector.
-static inline Selector GetUnarySelector(StringRef name, ASTContext& Ctx) {
+inline Selector GetUnarySelector(StringRef name, ASTContext &Ctx) {
   IdentifierInfo* II = &Ctx.Idents.get(name);
   return Ctx.Selectors.getSelector(1, &II);
 }
 
-}  // end namespace clang
+} // namespace clang
 
 // operator new and delete aren't allowed inside namespaces.
 
@@ -2821,11 +2901,12 @@ static inline Selector GetUnarySelector(StringRef name, ASTContext& Ctx) {
 /// @param C The ASTContext that provides the allocator.
 /// @param Alignment The alignment of the allocated memory (if the underlying
 ///                  allocator supports it).
-/// @return The allocated memory. Could be NULL.
+/// @return The allocated memory. Could be nullptr.
 inline void *operator new(size_t Bytes, const clang::ASTContext &C,
                           size_t Alignment) {
   return C.Allocate(Bytes, Alignment);
 }
+
 /// @brief Placement delete companion to the new above.
 ///
 /// This operator is just a companion to the new above. There is no way of
@@ -2858,7 +2939,7 @@ inline void operator delete(void *Ptr, const clang::ASTContext &C, size_t) {
 /// @param C The ASTContext that provides the allocator.
 /// @param Alignment The alignment of the allocated memory (if the underlying
 ///                  allocator supports it).
-/// @return The allocated memory. Could be NULL.
+/// @return The allocated memory. Could be nullptr.
 inline void *operator new[](size_t Bytes, const clang::ASTContext& C,
                             size_t Alignment = 8) {
   return C.Allocate(Bytes, Alignment);
diff --git a/include/clang/AST/ASTMutationListener.h b/include/clang/AST/ASTMutationListener.h
index ed82b32342722893ea3618b51b916f15efad660c..9395d36d87e5875edf12a09fb69f1fd04183e4b9 100644
--- a/include/clang/AST/ASTMutationListener.h
+++ b/include/clang/AST/ASTMutationListener.h
@@ -36,6 +36,7 @@ namespace clang {
   class QualType;
   class RecordDecl;
   class TagDecl;
+  class ValueDecl;
   class VarDecl;
   class VarTemplateDecl;
   class VarTemplateSpecializationDecl;
@@ -87,8 +88,13 @@ public:
   /// \brief An implicit member got a definition.
   virtual void CompletedImplicitDefinition(const FunctionDecl *D) {}
 
-  /// \brief A static data member was implicitly instantiated.
-  virtual void StaticDataMemberInstantiated(const VarDecl *D) {}
+  /// \brief The instantiation of a templated function or variable was
+  /// requested. In particular, the point of instantiation and template
+  /// specialization kind of \p D may have changed.
+  virtual void InstantiationRequested(const ValueDecl *D) {}
+
+  /// \brief A templated variable's definition was implicitly instantiated.
+  virtual void VariableDefinitionInstantiated(const VarDecl *D) {}
 
   /// \brief A function template's definition was instantiated.
   virtual void FunctionDefinitionInstantiated(const FunctionDecl *D) {}
diff --git a/include/clang/AST/ASTUnresolvedSet.h b/include/clang/AST/ASTUnresolvedSet.h
index 9078a0e80299cf4b7419d3b9f7490b8efa78ba6a..3693aeccfe14f26a76b388b688842c19db307c8f 100644
--- a/include/clang/AST/ASTUnresolvedSet.h
+++ b/include/clang/AST/ASTUnresolvedSet.h
@@ -1,4 +1,4 @@
-//===-- ASTUnresolvedSet.h - Unresolved sets of declarations  ---*- C++ -*-===//
+//===- ASTUnresolvedSet.h - Unresolved sets of declarations -----*- C++ -*-===//
 //
 //                     The LLVM Compiler Infrastructure
 //
@@ -16,14 +16,22 @@
 #define LLVM_CLANG_AST_ASTUNRESOLVEDSET_H
 
 #include "clang/AST/ASTVector.h"
+#include "clang/AST/DeclAccessPair.h"
 #include "clang/AST/UnresolvedSet.h"
+#include "clang/Basic/Specifiers.h"
+#include 
+#include 
 
 namespace clang {
 
+class NamedDecl;
+
 /// \brief An UnresolvedSet-like class which uses the ASTContext's allocator.
 class ASTUnresolvedSet {
+  friend class LazyASTUnresolvedSet;
+
   struct DeclsTy : ASTVector {
-    DeclsTy() {}
+    DeclsTy() = default;
     DeclsTy(ASTContext &C, unsigned N) : ASTVector(C, N) {}
 
     bool isLazy() const { return getTag(); }
@@ -32,14 +40,12 @@ class ASTUnresolvedSet {
 
   DeclsTy Decls;
 
-  friend class LazyASTUnresolvedSet;
-
 public:
-  ASTUnresolvedSet() {}
+  ASTUnresolvedSet() = default;
   ASTUnresolvedSet(ASTContext &C, unsigned N) : Decls(C, N) {}
 
-  typedef UnresolvedSetIterator iterator;
-  typedef UnresolvedSetIterator const_iterator;
+  using iterator = UnresolvedSetIterator;
+  using const_iterator = UnresolvedSetIterator;
 
   iterator begin() { return iterator(Decls.begin()); }
   iterator end() { return iterator(Decls.end()); }
@@ -98,13 +104,14 @@ public:
   }
 
   void reserve(ASTContext &C, unsigned N) { Impl.reserve(C, N); }
+
   void addLazyDecl(ASTContext &C, uintptr_t ID, AccessSpecifier AS) {
     assert(Impl.empty() || Impl.Decls.isLazy());
     Impl.Decls.setLazy(true);
-    Impl.addDecl(C, reinterpret_cast(ID << 2), AS);
+    Impl.addDecl(C, reinterpret_cast(ID << 2), AS);
   }
 };
 
 } // namespace clang
 
-#endif
+#endif // LLVM_CLANG_AST_ASTUNRESOLVEDSET_H
diff --git a/include/clang/AST/ASTVector.h b/include/clang/AST/ASTVector.h
index 717a9e9dff340288cd3b6d6fbc4828c0d5d6563f..80cd6b7007a6dad33bc958a2867b79e71fdf792a 100644
--- a/include/clang/AST/ASTVector.h
+++ b/include/clang/AST/ASTVector.h
@@ -1,4 +1,4 @@
-//===- ASTVector.h - Vector that uses ASTContext for allocation  --*- C++ -*-=//
+//===- ASTVector.h - Vector that uses ASTContext for allocation ---*- C++ -*-=//
 //
 //                     The LLVM Compiler Infrastructure
 //
@@ -18,22 +18,26 @@
 #ifndef LLVM_CLANG_AST_ASTVECTOR_H
 #define LLVM_CLANG_AST_ASTVECTOR_H
 
-#include "clang/AST/AttrIterator.h"
 #include "llvm/ADT/PointerIntPair.h"
-#include "llvm/Support/type_traits.h"
 #include 
+#include 
 #include 
 #include 
+#include 
 #include 
+#include 
+#include 
 
 namespace clang {
-  class ASTContext;
+
+class ASTContext;
 
 template
 class ASTVector {
 private:
-  T *Begin, *End;
-  llvm::PointerIntPair Capacity;
+  T *Begin = nullptr;
+  T *End = nullptr;
+  llvm::PointerIntPair Capacity;
 
   void setEnd(T *P) { this->End = P; }
 
@@ -45,7 +49,7 @@ protected:
 
 public:
   // Default ctor - Initialize to empty.
-  ASTVector() : Begin(nullptr), End(nullptr), Capacity(nullptr, false) {}
+  ASTVector() : Capacity(nullptr, false) {}
 
   ASTVector(ASTVector &&O) : Begin(O.Begin), End(O.End), Capacity(O.Capacity) {
     O.Begin = O.End = nullptr;
@@ -53,14 +57,15 @@ public:
     O.Capacity.setInt(false);
   }
 
-  ASTVector(const ASTContext &C, unsigned N)
-      : Begin(nullptr), End(nullptr), Capacity(nullptr, false) {
+  ASTVector(const ASTContext &C, unsigned N) : Capacity(nullptr, false) {
     reserve(C, N);
   }
 
   ASTVector &operator=(ASTVector &&RHS) {
     ASTVector O(std::move(RHS));
+
     using std::swap;
+
     swap(Begin, O.Begin);
     swap(End, O.End);
     swap(Capacity, O.Capacity);
@@ -74,19 +79,19 @@ public:
     }
   }
 
-  typedef size_t size_type;
-  typedef ptrdiff_t difference_type;
-  typedef T value_type;
-  typedef T* iterator;
-  typedef const T* const_iterator;
+  using size_type = size_t;
+  using difference_type = ptrdiff_t;
+  using value_type = T;
+  using iterator = T *;
+  using const_iterator = const T *;
 
-  typedef std::reverse_iterator  const_reverse_iterator;
-  typedef std::reverse_iterator  reverse_iterator;
+  using const_reverse_iterator = std::reverse_iterator;
+  using reverse_iterator = std::reverse_iterator;
 
-  typedef T& reference;
-  typedef const T& const_reference;
-  typedef T* pointer;
-  typedef const T* const_pointer;
+  using reference = T &;
+  using const_reference = const T &;
+  using pointer = T *;
+  using const_pointer = const T *;
 
   // forward iterator creation methods.
   iterator begin() { return Begin; }
@@ -175,7 +180,6 @@ public:
   size_t capacity() const { return this->capacity_ptr() - Begin; }
 
   /// append - Add the specified range to the end of the SmallVector.
-  ///
   template
   void append(const ASTContext &C, in_iter in_start, in_iter in_end) {
     size_type NumInputs = std::distance(in_start, in_end);
@@ -195,7 +199,6 @@ public:
   }
 
   /// append - Add the specified range to the end of the SmallVector.
-  ///
   void append(const ASTContext &C, size_type NumInputs, const T &Elt) {
     // Grow allocated space if needed.
     if (NumInputs > size_type(this->capacity_ptr()-this->end()))
@@ -368,6 +371,7 @@ protected:
   const_iterator capacity_ptr() const {
     return (iterator) Capacity.getPointer();
   }
+
   iterator capacity_ptr() { return (iterator)Capacity.getPointer(); }
 };
 
@@ -401,5 +405,6 @@ void ASTVector::grow(const ASTContext &C, size_t MinSize) {
   Capacity.setPointer(Begin+NewCapacity);
 }
 
-} // end: clang namespace
-#endif
+} // namespace clang
+
+#endif // LLVM_CLANG_AST_ASTVECTOR_H
diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h
index bbe320c28a3b5afab9a752f752b1970b46c38540..38dce44ddecd0d983eae78c24dff3685ffb451df 100644
--- a/include/clang/AST/Attr.h
+++ b/include/clang/AST/Attr.h
@@ -52,8 +52,10 @@ protected:
   unsigned Inherited : 1;
   unsigned IsPackExpansion : 1;
   unsigned Implicit : 1;
+  // FIXME: These are properties of the attribute kind, not state for this
+  // instance of the attribute.
   unsigned IsLateParsed : 1;
-  unsigned DuplicatesAllowed : 1;
+  unsigned InheritEvenIfAlreadyPresent : 1;
 
   void *operator new(size_t bytes) noexcept {
     llvm_unreachable("Attrs cannot be allocated with regular 'new'.");
@@ -74,10 +76,10 @@ public:
 
 protected:
   Attr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex,
-       bool IsLateParsed, bool DuplicatesAllowed)
+       bool IsLateParsed)
     : Range(R), AttrKind(AK), SpellingListIndex(SpellingListIndex),
       Inherited(false), IsPackExpansion(false), Implicit(false),
-      IsLateParsed(IsLateParsed), DuplicatesAllowed(DuplicatesAllowed) {}
+      IsLateParsed(IsLateParsed), InheritEvenIfAlreadyPresent(false) {}
 
 public:
 
@@ -109,18 +111,13 @@ public:
 
   // Pretty print this attribute.
   void printPretty(raw_ostream &OS, const PrintingPolicy &Policy) const;
-
-  /// \brief By default, attributes cannot be duplicated when being merged;
-  /// however, an attribute can override this. Returns true if the attribute
-  /// can be duplicated when merging.
-  bool duplicatesAllowed() const { return DuplicatesAllowed; }
 };
 
 class StmtAttr : public Attr {
 protected:
   StmtAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex,
-                  bool IsLateParsed, bool DuplicatesAllowed)
-      : Attr(AK, R, SpellingListIndex, IsLateParsed, DuplicatesAllowed) {}
+                  bool IsLateParsed)
+      : Attr(AK, R, SpellingListIndex, IsLateParsed) {}
 
 public:
   static bool classof(const Attr *A) {
@@ -132,12 +129,20 @@ public:
 class InheritableAttr : public Attr {
 protected:
   InheritableAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex,
-                  bool IsLateParsed, bool DuplicatesAllowed)
-      : Attr(AK, R, SpellingListIndex, IsLateParsed, DuplicatesAllowed) {}
+                  bool IsLateParsed, bool InheritEvenIfAlreadyPresent)
+      : Attr(AK, R, SpellingListIndex, IsLateParsed) {
+    this->InheritEvenIfAlreadyPresent = InheritEvenIfAlreadyPresent;
+  }
 
 public:
   void setInherited(bool I) { Inherited = I; }
 
+  /// Should this attribute be inherited from a prior declaration even if it's
+  /// explicitly provided in the current declaration?
+  bool shouldInheritEvenIfAlreadyPresent() const {
+    return InheritEvenIfAlreadyPresent;
+  }
+
   // Implement isa/cast/dyncast/etc.
   static bool classof(const Attr *A) {
     return A->getKind() >= attr::FirstInheritableAttr &&
@@ -148,9 +153,9 @@ public:
 class InheritableParamAttr : public InheritableAttr {
 protected:
   InheritableParamAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex,
-                       bool IsLateParsed, bool DuplicatesAllowed)
+                       bool IsLateParsed, bool InheritEvenIfAlreadyPresent)
       : InheritableAttr(AK, R, SpellingListIndex, IsLateParsed,
-                        DuplicatesAllowed) {}
+                        InheritEvenIfAlreadyPresent) {}
 
 public:
   // Implement isa/cast/dyncast/etc.
@@ -166,9 +171,9 @@ class ParameterABIAttr : public InheritableParamAttr {
 protected:
   ParameterABIAttr(attr::Kind AK, SourceRange R,
                    unsigned SpellingListIndex, bool IsLateParsed,
-                   bool DuplicatesAllowed)
+                   bool InheritEvenIfAlreadyPresent)
     : InheritableParamAttr(AK, R, SpellingListIndex, IsLateParsed,
-                           DuplicatesAllowed) {}
+                           InheritEvenIfAlreadyPresent) {}
 
 public:
   ParameterABI getABI() const {
@@ -190,6 +195,120 @@ public:
    }
 };
 
+/// A single parameter index whose accessors require each use to make explicit
+/// the parameter index encoding needed.
+class ParamIdx {
+  // Idx is exposed only via accessors that specify specific encodings.
+  unsigned Idx : 30;
+  unsigned HasThis : 1;
+  unsigned IsValid : 1;
+
+  void assertComparable(const ParamIdx &I) const {
+    assert(isValid() && I.isValid() &&
+           "ParamIdx must be valid to be compared");
+    // It's possible to compare indices from separate functions, but so far
+    // it's not proven useful.  Moreover, it might be confusing because a
+    // comparison on the results of getASTIndex might be inconsistent with a
+    // comparison on the ParamIdx objects themselves.
+    assert(HasThis == I.HasThis &&
+           "ParamIdx must be for the same function to be compared");
+  }
+
+public:
+  /// Construct an invalid parameter index (\c isValid returns false and
+  /// accessors fail an assert).
+  ParamIdx() : Idx(0), HasThis(false), IsValid(false) {}
+
+  /// \param Idx is the parameter index as it is normally specified in
+  /// attributes in the source: one-origin including any C++ implicit this
+  /// parameter.
+  ///
+  /// \param D is the declaration containing the parameters.  It is used to
+  /// determine if there is a C++ implicit this parameter.
+  ParamIdx(unsigned Idx, const Decl *D)
+      : Idx(Idx), HasThis(false), IsValid(true) {
+    if (const auto *FD = dyn_cast(D))
+      HasThis = FD->isCXXInstanceMember();
+  }
+
+  /// \param Idx is the parameter index as it is normally specified in
+  /// attributes in the source: one-origin including any C++ implicit this
+  /// parameter.
+  ///
+  /// \param HasThis specifies whether the function has a C++ implicit this
+  /// parameter.
+  ParamIdx(unsigned Idx, bool HasThis)
+      : Idx(Idx), HasThis(HasThis), IsValid(true) {}
+
+  /// Is this parameter index valid?
+  bool isValid() const { return IsValid; }
+
+  /// Is there a C++ implicit this parameter?
+  bool hasThis() const {
+    assert(isValid() && "ParamIdx must be valid");
+    return HasThis;
+  }
+
+  /// Get the parameter index as it would normally be encoded for attributes at
+  /// the source level of representation: one-origin including any C++ implicit
+  /// this parameter.
+  ///
+  /// This encoding thus makes sense for diagnostics, pretty printing, and
+  /// constructing new attributes from a source-like specification.
+  unsigned getSourceIndex() const {
+    assert(isValid() && "ParamIdx must be valid");
+    return Idx;
+  }
+
+  /// Get the parameter index as it would normally be encoded at the AST level
+  /// of representation: zero-origin not including any C++ implicit this
+  /// parameter.
+  ///
+  /// This is the encoding primarily used in Sema.  However, in diagnostics,
+  /// Sema uses \c getSourceIndex instead.
+  unsigned getASTIndex() const {
+    assert(isValid() && "ParamIdx must be valid");
+    assert(Idx >= 1 + HasThis &&
+           "stored index must be base-1 and not specify C++ implicit this");
+    return Idx - 1 - HasThis;
+  }
+
+  /// Get the parameter index as it would normally be encoded at the LLVM level
+  /// of representation: zero-origin including any C++ implicit this parameter.
+  ///
+  /// This is the encoding primarily used in CodeGen.
+  unsigned getLLVMIndex() const {
+    assert(isValid() && "ParamIdx must be valid");
+    assert(Idx >= 1 && "stored index must be base-1");
+    return Idx - 1;
+  }
+
+  bool operator==(const ParamIdx &I) const {
+    assertComparable(I);
+    return Idx == I.Idx;
+  }
+  bool operator!=(const ParamIdx &I) const {
+    assertComparable(I);
+    return Idx != I.Idx;
+  }
+  bool operator<(const ParamIdx &I) const {
+    assertComparable(I);
+    return Idx < I.Idx;
+  }
+  bool operator>(const ParamIdx &I) const {
+    assertComparable(I);
+    return Idx > I.Idx;
+  }
+  bool operator<=(const ParamIdx &I) const {
+    assertComparable(I);
+    return Idx <= I.Idx;
+  }
+  bool operator>=(const ParamIdx &I) const {
+    assertComparable(I);
+    return Idx >= I.Idx;
+  }
+};
+
 #include "clang/AST/Attrs.inc"
 
 inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
diff --git a/include/clang/AST/AttrIterator.h b/include/clang/AST/AttrIterator.h
index fb9b049e5d6b12b4ec8264bd45a4872432a1921d..56807b4590d378d824bbb15f991c894c77d9fc98 100644
--- a/include/clang/AST/AttrIterator.h
+++ b/include/clang/AST/AttrIterator.h
@@ -1,4 +1,4 @@
-//===--- AttrIterator.h - Classes for attribute iteration -------*- C++ -*-===//
+//===- AttrIterator.h - Classes for attribute iteration ---------*- C++ -*-===//
 //
 //                     The LLVM Compiler Infrastructure
 //
@@ -15,16 +15,23 @@
 #define LLVM_CLANG_AST_ATTRITERATOR_H
 
 #include "clang/Basic/LLVM.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Casting.h"
+#include 
+#include 
 #include 
 
 namespace clang {
-  class ASTContext;
-  class Attr;
-}
+
+class ASTContext;
+class Attr;
+
+} // namespace clang
 
 // Defined in ASTContext.h
 void *operator new(size_t Bytes, const clang::ASTContext &C,
                    size_t Alignment = 8);
+
 // FIXME: Being forced to not have a default argument here due to redeclaration
 //        rules on default arguments sucks
 void *operator new[](size_t Bytes, const clang::ASTContext &C,
@@ -39,13 +46,13 @@ void operator delete[](void *Ptr, const clang::ASTContext &C, size_t);
 namespace clang {
 
 /// AttrVec - A vector of Attr, which is how they are stored on the AST.
-typedef SmallVector AttrVec;
+using AttrVec = SmallVector;
 
 /// specific_attr_iterator - Iterates over a subrange of an AttrVec, only
 /// providing attributes that are of a specific type.
 template 
 class specific_attr_iterator {
-  typedef typename Container::const_iterator Iterator;
+  using Iterator = typename Container::const_iterator;
 
   /// Current - The current, underlying iterator.
   /// In order to ensure we don't dereference an invalid iterator unless
@@ -67,14 +74,14 @@ class specific_attr_iterator {
   }
 
 public:
-  typedef SpecificAttr*             value_type;
-  typedef SpecificAttr*             reference;
-  typedef SpecificAttr*             pointer;
-  typedef std::forward_iterator_tag iterator_category;
-  typedef std::ptrdiff_t            difference_type;
+  using value_type = SpecificAttr *;
+  using reference = SpecificAttr *;
+  using pointer = SpecificAttr *;
+  using iterator_category = std::forward_iterator_tag;
+  using difference_type = std::ptrdiff_t;
 
-  specific_attr_iterator() : Current() { }
-  explicit specific_attr_iterator(Iterator i) : Current(i) { }
+  specific_attr_iterator() = default;
+  explicit specific_attr_iterator(Iterator i) : Current(i) {}
 
   reference operator*() const {
     AdvanceToNext();
@@ -136,6 +143,6 @@ inline SpecificAttr *getSpecificAttr(const Container& container) {
     return nullptr;
 }
 
-}  // end namespace clang
+} // namespace clang
 
-#endif
+#endif // LLVM_CLANG_AST_ATTRITERATOR_H
diff --git a/include/clang/AST/BaseSubobject.h b/include/clang/AST/BaseSubobject.h
index 66af023c828e41b340c8ccb46cee41c03288f31d..fdb7e718fe9e4602c3b9823981ef00328ce248d7 100644
--- a/include/clang/AST/BaseSubobject.h
+++ b/include/clang/AST/BaseSubobject.h
@@ -1,4 +1,4 @@
-//===--- BaseSubobject.h - BaseSubobject class ----------------------------===//
+//===- BaseSubobject.h - BaseSubobject class --------------------*- C++ -*-===//
 //
 //                     The LLVM Compiler Infrastructure
 //
@@ -15,12 +15,15 @@
 #define LLVM_CLANG_AST_BASESUBOBJECT_H
 
 #include "clang/AST/CharUnits.h"
-#include "clang/AST/DeclCXX.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/Support/DataTypes.h"
+#include "llvm/ADT/DenseMapInfo.h"
 #include "llvm/Support/type_traits.h"
+#include 
+#include 
 
 namespace clang {
+
+class CXXRecordDecl;
+
 // BaseSubobject - Uniquely identifies a direct or indirect base class. 
 // Stores both the base class decl and the offset from the most derived class to
 // the base class. Used for vtable and VTT generation.
@@ -32,9 +35,9 @@ class BaseSubobject {
   CharUnits BaseOffset;
   
 public:
-  BaseSubobject() { }
+  BaseSubobject() = default;
   BaseSubobject(const CXXRecordDecl *Base, CharUnits BaseOffset)
-    : Base(Base), BaseOffset(BaseOffset) { }
+      : Base(Base), BaseOffset(BaseOffset) {}
   
   /// getBase - Returns the base class declaration.
   const CXXRecordDecl *getBase() const { return Base; }
@@ -47,7 +50,7 @@ public:
  }
 };
 
-} // end namespace clang
+} // namespace clang
 
 namespace llvm {
 
@@ -65,7 +68,8 @@ template<> struct DenseMapInfo {
   }
 
   static unsigned getHashValue(const clang::BaseSubobject &Base) {
-    typedef std::pair PairTy;
+    using PairTy = std::pair;
+
     return DenseMapInfo::getHashValue(PairTy(Base.getBase(),
                                                      Base.getBaseOffset()));
   }
@@ -81,6 +85,6 @@ template <> struct isPodLike {
   static const bool value = true;
 };
 
-}
+} // namespace llvm
 
-#endif
+#endif // LLVM_CLANG_AST_BASESUBOBJECT_H
diff --git a/include/clang/AST/CXXInheritance.h b/include/clang/AST/CXXInheritance.h
index 980608570fd68044d2f876d0a95f6761056ab12c..11fb229f0c091c8ce2e8d42fceb395bc659908c3 100644
--- a/include/clang/AST/CXXInheritance.h
+++ b/include/clang/AST/CXXInheritance.h
@@ -1,4 +1,4 @@
-//===------ CXXInheritance.h - C++ Inheritance ------------------*- C++ -*-===//
+//===- CXXInheritance.h - C++ Inheritance -----------------------*- C++ -*-===//
 //
 //                     The LLVM Compiler Infrastructure
 //
@@ -16,19 +16,23 @@
 
 #include "clang/AST/DeclBase.h"
 #include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclarationName.h"
 #include "clang/AST/Type.h"
 #include "clang/AST/TypeOrdering.h"
+#include "clang/Basic/Specifiers.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/MapVector.h"
 #include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/SmallVector.h"
-#include 
+#include "llvm/ADT/iterator_range.h"
 #include 
+#include 
+#include 
 
 namespace clang {
-  
-class CXXBaseSpecifier;
-class CXXMethodDecl;
-class CXXRecordDecl;
+
+class ASTContext;
 class NamedDecl;
   
 /// \brief Represents an element in a path from a derived class to a
@@ -66,12 +70,12 @@ struct CXXBasePathElement {
 /// subobject is being used.
 class CXXBasePath : public SmallVector {
 public:
-  CXXBasePath() : Access(AS_public) {}
-
   /// \brief The access along this inheritance path.  This is only
   /// calculated when recording paths.  AS_none is a special value
   /// used to indicate a path which permits no legal access.
-  AccessSpecifier Access;
+  AccessSpecifier Access = AS_public;
+
+  CXXBasePath() = default;
 
   /// \brief The set of declarations found inside this base class
   /// subobject.
@@ -113,8 +117,10 @@ public:
 /// refer to the same base class subobject of type A (the virtual
 /// one), there is no ambiguity.
 class CXXBasePaths {
+  friend class CXXRecordDecl;
+
   /// \brief The type from which this search originated.
-  CXXRecordDecl *Origin;
+  CXXRecordDecl *Origin = nullptr;
   
   /// Paths - The actual set of paths that can be taken from the
   /// derived class to the same base class.
@@ -152,15 +158,13 @@ class CXXBasePaths {
   CXXBasePath ScratchPath;
 
   /// DetectedVirtual - The base class that is virtual.
-  const RecordType *DetectedVirtual;
+  const RecordType *DetectedVirtual = nullptr;
   
   /// \brief Array of the declarations that have been found. This
   /// array is constructed only if needed, e.g., to iterate over the
   /// results within LookupResult.
   std::unique_ptr DeclsFound;
-  unsigned NumDeclsFound;
-  
-  friend class CXXRecordDecl;
+  unsigned NumDeclsFound = 0;
   
   void ComputeDeclsFound();
 
@@ -169,17 +173,16 @@ class CXXBasePaths {
                      bool LookupInDependent = false);
 
 public:
-  typedef std::list::iterator paths_iterator;
-  typedef std::list::const_iterator const_paths_iterator;
-  typedef NamedDecl **decl_iterator;
+  using paths_iterator = std::list::iterator;
+  using const_paths_iterator = std::list::const_iterator;
+  using decl_iterator = NamedDecl **;
   
   /// BasePaths - Construct a new BasePaths structure to record the
   /// paths for a derived-to-base search.
   explicit CXXBasePaths(bool FindAmbiguities = true, bool RecordPaths = true,
                         bool DetectVirtual = true)
-      : Origin(), FindAmbiguities(FindAmbiguities), RecordPaths(RecordPaths),
-        DetectVirtual(DetectVirtual), DetectedVirtual(nullptr),
-        NumDeclsFound(0) {}
+      : FindAmbiguities(FindAmbiguities), RecordPaths(RecordPaths),
+        DetectVirtual(DetectVirtual) {}
 
   paths_iterator begin() { return Paths.begin(); }
   paths_iterator end()   { return Paths.end(); }
@@ -189,7 +192,8 @@ public:
   CXXBasePath&       front()       { return Paths.front(); }
   const CXXBasePath& front() const { return Paths.front(); }
   
-  typedef llvm::iterator_range decl_range;
+  using decl_range = llvm::iterator_range;
+
   decl_range found_decls();
   
   /// \brief Determine whether the path from the most-derived type to the
@@ -231,25 +235,24 @@ public:
 /// \brief Uniquely identifies a virtual method within a class
 /// hierarchy by the method itself and a class subobject number.
 struct UniqueVirtualMethod {
-  UniqueVirtualMethod()
-    : Method(nullptr), Subobject(0), InVirtualSubobject(nullptr) { }
-
-  UniqueVirtualMethod(CXXMethodDecl *Method, unsigned Subobject,
-                      const CXXRecordDecl *InVirtualSubobject)
-    : Method(Method), Subobject(Subobject), 
-      InVirtualSubobject(InVirtualSubobject) { }
-
   /// \brief The overriding virtual method.
-  CXXMethodDecl *Method;
+  CXXMethodDecl *Method = nullptr;
 
   /// \brief The subobject in which the overriding virtual method
   /// resides.
-  unsigned Subobject;
+  unsigned Subobject = 0;
 
   /// \brief The virtual base class subobject of which this overridden
   /// virtual method is a part. Note that this records the closest
   /// derived virtual base class subobject.
-  const CXXRecordDecl *InVirtualSubobject;
+  const CXXRecordDecl *InVirtualSubobject = nullptr;
+
+  UniqueVirtualMethod() = default;
+
+  UniqueVirtualMethod(CXXMethodDecl *Method, unsigned Subobject,
+                      const CXXRecordDecl *InVirtualSubobject)
+      : Method(Method), Subobject(Subobject),
+        InVirtualSubobject(InVirtualSubobject) {}
 
   friend bool operator==(const UniqueVirtualMethod &X,
                          const UniqueVirtualMethod &Y) {
@@ -271,14 +274,16 @@ struct UniqueVirtualMethod {
 /// pair is the virtual method that overrides it (including the
 /// subobject in which that virtual function occurs).
 class OverridingMethods {
-  typedef SmallVector ValuesT;
-  typedef llvm::MapVector MapType;
+  using ValuesT = SmallVector;
+  using MapType = llvm::MapVector;
+
   MapType Overrides;
 
 public:
   // Iterate over the set of subobjects that have overriding methods.
-  typedef MapType::iterator iterator;
-  typedef MapType::const_iterator const_iterator;
+  using iterator = MapType::iterator;
+  using const_iterator = MapType::const_iterator;
+
   iterator begin() { return Overrides.begin(); }
   const_iterator begin() const { return Overrides.begin(); }
   iterator end() { return Overrides.end(); }
@@ -287,10 +292,10 @@ public:
 
   // Iterate over the set of overriding virtual methods in a given
   // subobject.
-  typedef SmallVectorImpl::iterator
-    overriding_iterator;
-  typedef SmallVectorImpl::const_iterator
-    overriding_const_iterator;
+  using overriding_iterator =
+      SmallVectorImpl::iterator;
+  using overriding_const_iterator =
+      SmallVectorImpl::const_iterator;
 
   // Add a new overriding method for a particular subobject.
   void add(unsigned OverriddenSubobject, UniqueVirtualMethod Overriding);
@@ -357,12 +362,12 @@ public:
 /// subobject numbers greater than 0 refer to non-virtual base class
 /// subobjects of that type.
 class CXXFinalOverriderMap
-  : public llvm::MapVector { };
+  : public llvm::MapVector {};
 
 /// \brief A set of all the primary bases for a class.
 class CXXIndirectPrimaryBaseSet
-  : public llvm::SmallSet { };
+  : public llvm::SmallSet {};
 
-} // end namespace clang
+} // namespace clang
 
-#endif
+#endif // LLVM_CLANG_AST_CXXINHERITANCE_H
diff --git a/include/clang/AST/CanonicalType.h b/include/clang/AST/CanonicalType.h
index 023456e2e3bc4ca8babb41aa299c3b5635c9e98a..6487613200de326e58858e8feb4833c5820798f9 100644
--- a/include/clang/AST/CanonicalType.h
+++ b/include/clang/AST/CanonicalType.h
@@ -1,4 +1,4 @@
-//===-- CanonicalType.h - C Language Family Type Representation -*- C++ -*-===//
+//===- CanonicalType.h - C Language Family Type Representation --*- C++ -*-===//
 //
 //                     The LLVM Compiler Infrastructure
 //
@@ -16,13 +16,29 @@
 #define LLVM_CLANG_AST_CANONICALTYPE_H
 
 #include "clang/AST/Type.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/FoldingSet.h"
 #include "llvm/ADT/iterator.h"
 #include "llvm/Support/Casting.h"
+#include "llvm/Support/PointerLikeTypeTraits.h"
+#include 
+#include 
+#include 
 
 namespace clang {
 
 template class CanProxy;
 template struct CanProxyAdaptor;
+class CXXRecordDecl;
+class EnumDecl;
+class Expr;
+class IdentifierInfo;
+class ObjCInterfaceDecl;
+class RecordDecl;
+class TagDecl;
+class TemplateTypeParmDecl;
 
 //----------------------------------------------------------------------------//
 // Canonical, qualified type template
@@ -46,8 +62,6 @@ template struct CanProxyAdaptor;
 /// converted to @c CanQual. Note that any @c CanQual type can
 /// be implicitly converted to a QualType, but the reverse operation requires
 /// a call to ASTContext::getCanonicalType().
-///
-///
 template
 class CanQual {
   /// \brief The actual, canonical type.
@@ -55,7 +69,7 @@ class CanQual {
 
 public:
   /// \brief Constructs a NULL canonical type.
-  CanQual() : Stored() { }
+  CanQual() = default;
 
   /// \brief Converting constructor that permits implicit upcasting of
   /// canonical type pointers.
@@ -66,12 +80,11 @@ public:
   /// \brief Retrieve the underlying type pointer, which refers to a
   /// canonical type.
   ///
-  /// The underlying pointer must not be NULL.
+  /// The underlying pointer must not be nullptr.
   const T *getTypePtr() const { return cast(Stored.getTypePtr()); }
 
   /// \brief Retrieve the underlying type pointer, which refers to a
-  /// canonical type, or NULL.
-  ///
+  /// canonical type, or nullptr.
   const T *getTypePtrOrNull() const { 
     return cast_or_null(Stored.getTypePtrOrNull()); 
   }
@@ -125,9 +138,11 @@ public:
   bool isConstQualified() const {
     return Stored.isLocalConstQualified();
   }
+
   bool isVolatileQualified() const {
     return Stored.isLocalVolatileQualified();
   }
+
   bool isRestrictQualified() const {
     return Stored.isLocalRestrictQualified();
   }
@@ -195,7 +210,7 @@ inline bool operator!=(CanQual x, CanQual y) {
 }
 
 /// \brief Represents a canonical, potentially-qualified type.
-typedef CanQual CanQualType;
+using CanQualType = CanQual;
 
 inline CanQualType Type::getCanonicalTypeUnqualified() const {
   return CanQualType::CreateUnsafe(getCanonicalTypeInternal());
@@ -320,7 +335,7 @@ public:
 /// than the more typical @c QualType, to propagate the notion of "canonical"
 /// through the system.
 template
-struct CanProxyAdaptor : CanProxyBase { };
+struct CanProxyAdaptor : CanProxyBase {};
 
 /// \brief Canonical proxy type returned when retrieving the members of a
 /// canonical type or as the result of the @c CanQual::getAs member
@@ -333,7 +348,7 @@ template
 class CanProxy : public CanProxyAdaptor {
 public:
   /// \brief Build a NULL proxy.
-  CanProxy() { }
+  CanProxy() = default;
 
   /// \brief Build a proxy to the given canonical type.
   CanProxy(CanQual Stored) { this->Stored = Stored; }
@@ -342,7 +357,7 @@ public:
   operator CanQual() const { return this->Stored; }
 };
 
-} // end namespace clang
+} // namespace clang
 
 namespace llvm {
 
@@ -350,8 +365,9 @@ namespace llvm {
 /// CanQual to a specific Type class. We're prefer isa/dyn_cast/cast/etc.
 /// to return smart pointer (proxies?).
 template
-struct simplify_type< ::clang::CanQual > {
-  typedef const T *SimpleType;
+struct simplify_type< ::clang::CanQual> {
+  using SimpleType = const T *;
+
   static SimpleType getSimplifiedValue(::clang::CanQual Val) {
     return Val.getTypePtr();
   }
@@ -359,18 +375,20 @@ struct simplify_type< ::clang::CanQual > {
 
 // Teach SmallPtrSet that CanQual is "basically a pointer".
 template
-struct PointerLikeTypeTraits > {
-  static inline void *getAsVoidPointer(clang::CanQual P) {
+struct PointerLikeTypeTraits> {
+  static void *getAsVoidPointer(clang::CanQual P) {
     return P.getAsOpaquePtr();
   }
-  static inline clang::CanQual getFromVoidPointer(void *P) {
+
+  static clang::CanQual getFromVoidPointer(void *P) {
     return clang::CanQual::getFromOpaquePtr(P);
   }
+
   // qualifier information is encoded in the low bits.
   enum { NumLowBitsAvailable = 0 };
 };
 
-} // end namespace llvm
+} // namespace llvm
 
 namespace clang {
 
@@ -388,7 +406,7 @@ struct CanTypeIterator
           CanQualType,
           typename std::iterator_traits::difference_type,
           CanProxy, CanQualType> {
-  CanTypeIterator() {}
+  CanTypeIterator() = default;
   explicit CanTypeIterator(InputIterator Iter)
       : CanTypeIterator::iterator_adaptor_base(std::move(Iter)) {}
 
@@ -486,6 +504,7 @@ struct CanProxyAdaptor
   LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasExtParameterInfos)
   LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(
             ArrayRef, getExtParameterInfos)
+
   CanQualType getParamType(unsigned i) const {
     return CanQualType::CreateUnsafe(this->getTypePtr()->getParamType(i));
   }
@@ -493,8 +512,8 @@ struct CanProxyAdaptor
   LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVariadic)
   LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getTypeQuals)
 
-  typedef CanTypeIterator
-  param_type_iterator;
+  using param_type_iterator =
+      CanTypeIterator;
 
   param_type_iterator param_type_begin() const {
     return param_type_iterator(this->getTypePtr()->param_type_begin());
@@ -566,7 +585,8 @@ struct CanProxyAdaptor
   LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedId)
   LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedClass)
 
-  typedef ObjCObjectPointerType::qual_iterator qual_iterator;
+  using qual_iterator = ObjCObjectPointerType::qual_iterator;
+
   LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_begin)
   LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_end)
   LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, qual_empty)
@@ -584,7 +604,8 @@ struct CanProxyAdaptor
   LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedIdType)
   LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedClassType)
 
-  typedef ObjCObjectPointerType::qual_iterator qual_iterator;
+  using qual_iterator = ObjCObjectPointerType::qual_iterator;
+
   LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_begin)
   LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_end)
   LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, qual_empty)
@@ -661,7 +682,6 @@ CanProxy CanTypeIterator::operator->() const {
   return CanProxy(*this);
 }
 
-}
-
+} // namespace clang
 
-#endif
+#endif // LLVM_CLANG_AST_CANONICALTYPE_H
diff --git a/include/clang/AST/CommentVisitor.h b/include/clang/AST/CommentVisitor.h
index 21641bfeb89f0eff8f637656e5f9f5dc71b2b206..d1cc2d0a4e5e1a981e0a9501cbf426254501b093 100644
--- a/include/clang/AST/CommentVisitor.h
+++ b/include/clang/AST/CommentVisitor.h
@@ -1,4 +1,4 @@
-//===--- CommentVisitor.h - Visitor for Comment subclasses ------*- C++ -*-===//
+//===- CommentVisitor.h - Visitor for Comment subclasses --------*- C++ -*-===//
 //
 //                     The LLVM Compiler Infrastructure
 //
@@ -16,8 +16,8 @@
 namespace clang {
 namespace comments {
 
-template  struct make_ptr       { typedef       T *type; };
-template  struct make_const_ptr { typedef const T *type; };
+template  struct make_ptr { using type = T *; };
+template  struct make_const_ptr { using type = const T *; };
 
 template