diff --git a/.clang-tidy b/.clang-tidy index 2cfcc2ac22b6ad25dfb70b6ae8aea71d183642da..849c26987efd5336f6131a8f669ee7855a8f4643 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,4 +1,9 @@ -Checks: '-*,clang-diagnostic-*,llvm-*,misc-*,-misc-unused-parameters,readability-identifier-naming' +Checks: '-*,clang-diagnostic-*,llvm-*,misc-*,-misc-unused-parameters,-misc-non-private-member-variables-in-classes,-readability-identifier-naming' +# Note that the readability-identifier-naming check is disabled, there are too +# many violations in the codebase and they create too much noise in clang-tidy +# results. +# Naming settings are kept for documentation purposes and allowing to run the +# check if the users would override this file, e.g. via a command-line arg. CheckOptions: - key: readability-identifier-naming.ClassCase value: CamelCase diff --git a/.gitignore b/.gitignore index 3ea38b6e0054802e977eeebef0bb1733b6110678..9ee83231d375a7eb4fe780fa91ad9409335d4db7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,6 @@ #==============================================================================# # This file specifies intentionally untracked files that git should ignore. # See: http://www.kernel.org/pub/software/scm/git/docs/gitignore.html -# -# This file is intentionally different from the output of `git svn show-ignore`, -# as most of those are useless. #==============================================================================# #==============================================================================# diff --git a/LICENSE.TXT b/LICENSE.TXT index 547f6a4893820664ac3caa03397c245bab139eaf..24806ab4c9eb291db4d28e159901f7a0901b9fd1 100644 --- a/LICENSE.TXT +++ b/LICENSE.TXT @@ -1,10 +1,245 @@ ============================================================================== -LLVM Release License +The LLVM Project is under the Apache License v2.0 with LLVM Exceptions: +============================================================================== + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +---- LLVM Exceptions to the Apache 2.0 License ---- + +As an exception, if, as a result of your compiling your source code, portions +of this Software are embedded into an Object form of such source code, you +may redistribute such embedded portions in such Object form without complying +with the conditions of Sections 4(a), 4(b) and 4(d) of the License. + +In addition, if you combine or link compiled forms of this Software with +software that is licensed under the GPLv2 ("Combined Software") and if a +court of competent jurisdiction determines that the patent provision (Section +3), the indemnity provision (Section 9) or other Section of the License +conflicts with the conditions of the GPLv2, you may retroactively and +prospectively choose to deem waived or otherwise exclude such Section(s) of +the License, but only in their entirety and only with respect to the Combined +Software. + +============================================================================== +Software from third parties included in the LLVM Project: +============================================================================== +The LLVM Project contains third party software which is under different license +terms. All such code will be identified clearly using at least one of two +mechanisms: +1) It will be in a separate directory tree with its own `LICENSE.txt` or + `LICENSE` file at the top containing the specific license and restrictions + which apply to that software, or +2) It will contain specific license and restriction terms at the top of every + file. + +============================================================================== +Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy): ============================================================================== University of Illinois/NCSA Open Source License -Copyright (c) 2007-2018 University of Illinois at Urbana-Champaign. +Copyright (c) 2007-2019 University of Illinois at Urbana-Champaign. All rights reserved. Developed by: @@ -41,23 +276,3 @@ CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. - -============================================================================== -The LLVM software contains code written by third parties. Such software will -have its own individual LICENSE.TXT file in the directory in which it appears. -This file will describe the copyrights, license, and restrictions which apply -to that code. - -The disclaimer of warranty in the University of Illinois Open Source License -applies to all code in the LLVM Distribution, and nothing in any of the -other licenses gives permission to use the names of the LLVM Team or the -University of Illinois to endorse or promote products derived from this -Software. - -The following pieces of software have additional or alternate copyrights, -licenses, and/or restrictions: - -Program Directory -------- --------- - - diff --git a/bindings/python/clang/__init__.py b/bindings/python/clang/__init__.py index 88f30812383f8ebdcf095566500b1ecc78c92710..14944b63e6dac1ea074f29ba125ca90b022676f7 100644 --- a/bindings/python/clang/__init__.py +++ b/bindings/python/clang/__init__.py @@ -1,9 +1,8 @@ #===- __init__.py - Clang Python Bindings --------------------*- python -*--===# # -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. +# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +# See https://llvm.org/LICENSE.txt for license information. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception # #===------------------------------------------------------------------------===# diff --git a/bindings/python/clang/cindex.py b/bindings/python/clang/cindex.py index 54514b8daefa651c1819a7177bbb40ed5fc4254d..8630c59c135990ef8f8379e8befd1ebf7e7a902b 100644 --- a/bindings/python/clang/cindex.py +++ b/bindings/python/clang/cindex.py @@ -1,9 +1,8 @@ #===- cindex.py - Python Indexing Library Bindings -----------*- python -*--===# # -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. +# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +# See https://llvm.org/LICENSE.txt for license information. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception # #===------------------------------------------------------------------------===# @@ -64,7 +63,6 @@ from __future__ import absolute_import, division, print_function # o implement additional SourceLocation, SourceRange, and File methods. from ctypes import * -import collections import clang.enumerations @@ -123,6 +121,14 @@ elif sys.version_info[0] == 2: def b(x): return x +# Importing ABC-s directly from collections is deprecated since Python 3.7, +# will stop working in Python 3.8. +# See: https://docs.python.org/dev/whatsnew/3.7.html#id3 +if sys.version_info[:2] >= (3, 7): + from collections import abc as collections_abc +else: + import collections as collections_abc + # We only support PathLike objects on Python version with os.fspath present # to be consistent with the Python standard library. On older Python versions # we only support strings and we have dummy fspath to just pass them through. @@ -1336,6 +1342,7 @@ CursorKind.VISIBILITY_ATTR = CursorKind(417) CursorKind.DLLEXPORT_ATTR = CursorKind(418) CursorKind.DLLIMPORT_ATTR = CursorKind(419) +CursorKind.CONVERGENT_ATTR = CursorKind(420) ### # Preprocessing @@ -2181,7 +2188,7 @@ class Type(Structure): The returned object is iterable and indexable. Each item in the container is a Type instance. """ - class ArgumentsIterator(collections.Sequence): + class ArgumentsIterator(collections_abc.Sequence): def __init__(self, parent): self.parent = parent self.length = None @@ -2808,9 +2815,9 @@ class TranslationUnit(ClangObject): for i, (name, contents) in enumerate(unsaved_files): if hasattr(contents, "read"): contents = contents.read() - + contents = b(contents) unsaved_array[i].name = b(fspath(name)) - unsaved_array[i].contents = b(contents) + unsaved_array[i].contents = contents unsaved_array[i].length = len(contents) ptr = conf.lib.clang_parseTranslationUnit(index, @@ -2987,17 +2994,13 @@ class TranslationUnit(ClangObject): unsaved_files_array = 0 if len(unsaved_files): unsaved_files_array = (_CXUnsavedFile * len(unsaved_files))() - for i,(name,value) in enumerate(unsaved_files): - if not isinstance(value, str): - # FIXME: It would be great to support an efficient version - # of this, one day. - value = value.read() - print(value) - if not isinstance(value, str): - raise TypeError('Unexpected unsaved file contents.') - unsaved_files_array[i].name = fspath(name) - unsaved_files_array[i].contents = value - unsaved_files_array[i].length = len(value) + for i,(name,contents) in enumerate(unsaved_files): + if hasattr(contents, "read"): + contents = contents.read() + contents = b(contents) + unsaved_files_array[i].name = b(fspath(name)) + unsaved_files_array[i].contents = contents + unsaved_files_array[i].length = len(contents) ptr = conf.lib.clang_reparseTranslationUnit(self, len(unsaved_files), unsaved_files_array, options) @@ -3051,17 +3054,13 @@ class TranslationUnit(ClangObject): unsaved_files_array = 0 if len(unsaved_files): unsaved_files_array = (_CXUnsavedFile * len(unsaved_files))() - for i,(name,value) in enumerate(unsaved_files): - if not isinstance(value, str): - # FIXME: It would be great to support an efficient version - # of this, one day. - value = value.read() - print(value) - if not isinstance(value, str): - raise TypeError('Unexpected unsaved file contents.') + for i,(name,contents) in enumerate(unsaved_files): + if hasattr(contents, "read"): + contents = contents.read() + contents = b(contents) unsaved_files_array[i].name = b(fspath(name)) - unsaved_files_array[i].contents = b(value) - unsaved_files_array[i].length = len(value) + unsaved_files_array[i].contents = contents + unsaved_files_array[i].length = len(contents) ptr = conf.lib.clang_codeCompleteAt(self, fspath(path), line, column, unsaved_files_array, len(unsaved_files), options) if ptr: diff --git a/bindings/python/clang/enumerations.py b/bindings/python/clang/enumerations.py index a86a48ade3bd7ad00e455bebb3b94ecf25ddf8e4..520e1346d3ebe7746dab82480d606ba24975fbfc 100644 --- a/bindings/python/clang/enumerations.py +++ b/bindings/python/clang/enumerations.py @@ -1,9 +1,8 @@ #===- enumerations.py - Python Enumerations ------------------*- python -*--===# # -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. +# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +# See https://llvm.org/LICENSE.txt for license information. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception # #===------------------------------------------------------------------------===# diff --git a/bindings/python/examples/cindex/cindex-dump.py b/bindings/python/examples/cindex/cindex-dump.py index acec7e0e00544ad1c7d001e6aa4d49824e1de511..46073b285cb36284e02c300f80a3eb6d29790a42 100644 --- a/bindings/python/examples/cindex/cindex-dump.py +++ b/bindings/python/examples/cindex/cindex-dump.py @@ -2,10 +2,9 @@ #===- cindex-dump.py - cindex/Python Source Dump -------------*- python -*--===# # -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. +# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +# See https://llvm.org/LICENSE.txt for license information. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception # #===------------------------------------------------------------------------===# diff --git a/bindings/python/examples/cindex/cindex-includes.py b/bindings/python/examples/cindex/cindex-includes.py index 17500227a349b14bfdae7e4fbeb2d387245826c0..ec1fbc0c3edb40651f927727cb3784f7ef019553 100644 --- a/bindings/python/examples/cindex/cindex-includes.py +++ b/bindings/python/examples/cindex/cindex-includes.py @@ -2,10 +2,9 @@ #===- cindex-includes.py - cindex/Python Inclusion Graph -----*- python -*--===# # -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. +# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +# See https://llvm.org/LICENSE.txt for license information. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception # #===------------------------------------------------------------------------===# diff --git a/bindings/python/tests/CMakeLists.txt b/bindings/python/tests/CMakeLists.txt index 3386e6428c20877d0a2e478c7ec26548b94e7afd..7af6503f158865d9a973d7ec47f96086bf44f9bb 100644 --- a/bindings/python/tests/CMakeLists.txt +++ b/bindings/python/tests/CMakeLists.txt @@ -10,6 +10,11 @@ add_custom_target(check-clang-python set(RUN_PYTHON_TESTS TRUE) set_target_properties(check-clang-python PROPERTIES FOLDER "Clang tests") +# Tests require libclang.so which is only built with LLVM_ENABLE_PIC=ON +if(NOT LLVM_ENABLE_PIC) + set(RUN_PYTHON_TESTS FALSE) +endif() + # Do not try to run if libclang was built with ASan because # the sanitizer library will likely be loaded too late to perform # interception and will then fail. diff --git a/bindings/python/tests/cindex/test_diagnostics.py b/bindings/python/tests/cindex/test_diagnostics.py index 79d7a5fd411d22431db93861df7bf1d9ecdcdee5..c17d5b28efe9e1e81c84c3f3f8e21af5f9ee0d53 100644 --- a/bindings/python/tests/cindex/test_diagnostics.py +++ b/bindings/python/tests/cindex/test_diagnostics.py @@ -51,7 +51,7 @@ class TestDiagnostics(unittest.TestCase): self.assertEqual(tu.diagnostics[0].fixits[0].value, '.f0 = ') def test_diagnostic_range(self): - tu = get_tu('void f() { int i = "a" + 1; }') + tu = get_tu('void f() { int i = "a"; }') self.assertEqual(len(tu.diagnostics), 1) self.assertEqual(tu.diagnostics[0].severity, Diagnostic.Warning) self.assertEqual(tu.diagnostics[0].location.line, 1) @@ -63,7 +63,7 @@ class TestDiagnostics(unittest.TestCase): 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) + self.assertEqual(tu.diagnostics[0].ranges[0].end.column, 23) with self.assertRaises(IndexError): tu.diagnostics[0].ranges[1].start.line diff --git a/bindings/python/tests/cindex/test_translation_unit.py b/bindings/python/tests/cindex/test_translation_unit.py index b3075eb85de1fe08b5ad4afd2d6c94c2773a7c53..f3e770a93611718ee597d9912b3299df8fe2ff84 100644 --- a/bindings/python/tests/cindex/test_translation_unit.py +++ b/bindings/python/tests/cindex/test_translation_unit.py @@ -6,6 +6,7 @@ if 'CLANG_LIBRARY_PATH' in os.environ: from contextlib import contextmanager import gc import os +import sys import tempfile import unittest @@ -93,10 +94,10 @@ int SOME_DEFINE; self.assertEqual(spellings[-1], 'y') def test_unsaved_files_2(self): - try: - from StringIO import StringIO - except: + if sys.version_info.major >= 3: from io import StringIO + else: + from io import BytesIO as StringIO tu = TranslationUnit.from_source('fake.c', unsaved_files = [ ('fake.c', StringIO('int x;'))]) spellings = [c.spelling for c in tu.cursor.get_children()] diff --git a/cmake/caches/Fuchsia-stage2.cmake b/cmake/caches/Fuchsia-stage2.cmake index 9413c79dc3de0cd0e1c7ea53ac4947a138840748..8696aed6249978660cf29a28b1df57133758c4a1 100644 --- a/cmake/caches/Fuchsia-stage2.cmake +++ b/cmake/caches/Fuchsia-stage2.cmake @@ -1,36 +1,42 @@ -# This file sets up a CMakeCache for the second stage of a Fuchsia toolchain -# build. +# This file sets up a CMakeCache for the second stage of a Fuchsia toolchain build. set(LLVM_TARGETS_TO_BUILD X86;ARM;AArch64 CACHE STRING "") set(PACKAGE_VENDOR Fuchsia CACHE STRING "") -set(LLVM_INCLUDE_EXAMPLES OFF CACHE BOOL "") -set(LLVM_INCLUDE_DOCS OFF CACHE BOOL "") set(LLVM_ENABLE_BACKTRACES OFF CACHE BOOL "") +if(NOT APPLE) + set(LLVM_ENABLE_LLD ON CACHE BOOL "") +endif() +set(LLVM_ENABLE_LTO ON CACHE BOOL "") set(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR ON 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 "") +set(LLVM_INCLUDE_EXAMPLES OFF CACHE BOOL "") +set(LLVM_INCLUDE_DOCS OFF CACHE BOOL "") -set(LLVM_ENABLE_LTO ON CACHE BOOL "") +set(CLANG_DEFAULT_CXX_STDLIB libc++ CACHE STRING "") 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() -set(CLANG_DEFAULT_CXX_STDLIB libc++ CACHE STRING "") set(CLANG_DEFAULT_RTLIB compiler-rt CACHE STRING "") +set(CLANG_PLUGIN_SUPPORT OFF CACHE BOOL "") + +set(ENABLE_LINKER_BUILD_ID ON CACHE BOOL "") +set(ENABLE_X86_RELAX_RELOCATIONS ON CACHE BOOL "") -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(CMAKE_C_FLAGS_RELWITHDEBINFO "-O3 -gline-tables-only" CACHE STRING "") +set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 -gline-tables-only" CACHE STRING "") if(APPLE) list(APPEND BUILTIN_TARGETS "default") list(APPEND RUNTIME_TARGETS "default") + + set(COMPILER_RT_ENABLE_TVOS OFF CACHE BOOL "") + set(COMPILER_RT_ENABLE_WATCHOS OFF CACHE BOOL "") endif() foreach(target aarch64-linux-gnu;armv7-linux-gnueabihf;i386-linux-gnu;x86_64-linux-gnu) @@ -107,14 +113,17 @@ if(FUCHSIA_SDK) set(RUNTIMES_${target}-fuchsia_CMAKE_SYSROOT ${FUCHSIA_${target}_SYSROOT} CACHE PATH "") set(RUNTIMES_${target}-fuchsia_LLVM_ENABLE_ASSERTIONS ON CACHE BOOL "") set(RUNTIMES_${target}-fuchsia_LIBUNWIND_USE_COMPILER_RT ON CACHE BOOL "") + set(RUNTIMES_${target}-fuchsia_LIBUNWIND_HERMETIC_STATIC_LIBRARY ON CACHE BOOL "") set(RUNTIMES_${target}-fuchsia_LIBUNWIND_INSTALL_STATIC_LIBRARY OFF CACHE BOOL "") set(RUNTIMES_${target}-fuchsia_LIBCXXABI_USE_COMPILER_RT ON CACHE BOOL "") set(RUNTIMES_${target}-fuchsia_LIBCXXABI_USE_LLVM_UNWINDER ON CACHE BOOL "") set(RUNTIMES_${target}-fuchsia_LIBCXXABI_ENABLE_STATIC_UNWINDER ON CACHE BOOL "") + set(RUNTIMES_${target}-fuchsia_LIBCXXABI_HERMETIC_STATIC_LIBRARY ON CACHE BOOL "") set(RUNTIMES_${target}-fuchsia_LIBCXXABI_INSTALL_STATIC_LIBRARY OFF CACHE BOOL "") set(RUNTIMES_${target}-fuchsia_LIBCXXABI_STATICALLY_LINK_UNWINDER_IN_SHARED_LIBRARY OFF CACHE BOOL "") set(RUNTIMES_${target}-fuchsia_LIBCXX_USE_COMPILER_RT ON CACHE BOOL "") set(RUNTIMES_${target}-fuchsia_LIBCXX_ENABLE_STATIC_ABI_LIBRARY ON CACHE BOOL "") + set(RUNTIMES_${target}-fuchsia_LIBCXX_HERMETIC_STATIC_LIBRARY ON CACHE BOOL "") set(RUNTIMES_${target}-fuchsia_LIBCXX_STATICALLY_LINK_ABI_IN_SHARED_LIBRARY OFF CACHE BOOL "") set(RUNTIMES_${target}-fuchsia_LIBCXX_ABI_VERSION 2 CACHE STRING "") endforeach() @@ -154,7 +163,6 @@ set(LLVM_TOOLCHAIN_TOOLS set(LLVM_DISTRIBUTION_COMPONENTS clang - libclang lld LTO clang-apply-replacements diff --git a/cmake/caches/Fuchsia.cmake b/cmake/caches/Fuchsia.cmake index e711f501a72781003916b7226f0bab843320b2c6..6b4fefcb0480460af2cd7dc333d61167fe383888 100644 --- a/cmake/caches/Fuchsia.cmake +++ b/cmake/caches/Fuchsia.cmake @@ -4,30 +4,26 @@ set(LLVM_TARGETS_TO_BUILD X86;ARM;AArch64 CACHE STRING "") set(PACKAGE_VENDOR Fuchsia CACHE STRING "") -set(LLVM_INCLUDE_EXAMPLES OFF CACHE BOOL "") -set(LLVM_INCLUDE_TESTS OFF CACHE BOOL "") -set(LLVM_INCLUDE_DOCS OFF CACHE BOOL "") set(LLVM_ENABLE_BACKTRACES OFF CACHE BOOL "") set(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR ON CACHE BOOL "") set(LLVM_ENABLE_TERMINFO OFF CACHE BOOL "") set(LLVM_ENABLE_ZLIB OFF CACHE BOOL "") -set(CLANG_INCLUDE_TESTS 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 "") -if(NOT APPLE) - set(BOOTSTRAP_LLVM_ENABLE_LLD ON CACHE BOOL "") -endif() +set(LLVM_INCLUDE_EXAMPLES OFF CACHE BOOL "") +set(LLVM_INCLUDE_DOCS OFF CACHE BOOL "") +set(CLANG_DEFAULT_CXX_STDLIB libc++ CACHE STRING "") if(NOT APPLE) set(CLANG_DEFAULT_LINKER lld CACHE STRING "") set(CLANG_DEFAULT_OBJCOPY llvm-objcopy CACHE STRING "") endif() -set(CLANG_DEFAULT_CXX_STDLIB libc++ CACHE STRING "") set(CLANG_DEFAULT_RTLIB compiler-rt CACHE STRING "") +set(CLANG_PLUGIN_SUPPORT OFF CACHE BOOL "") + +set(ENABLE_LINKER_BUILD_ID ON CACHE BOOL "") +set(ENABLE_X86_RELAX_RELOCATIONS ON CACHE BOOL "") + +set(LLVM_ENABLE_ASSERTIONS ON CACHE BOOL "") +set(CMAKE_BUILD_TYPE Release CACHE STRING "") if(APPLE) set(COMPILER_RT_ENABLE_IOS OFF CACHE BOOL "") @@ -78,18 +74,32 @@ if(BOOTSTRAP_CMAKE_SYSTEM_NAME) endif() endif() +if(UNIX) + set(BOOTSTRAP_CMAKE_SHARED_LINKER_FLAGS "-ldl -lpthread" CACHE STRING "") + set(BOOTSTRAP_CMAKE_MODULE_LINKER_FLAGS "-ldl -lpthread" CACHE STRING "") + set(BOOTSTRAP_CMAKE_EXE_LINKER_FLAGS "-ldl -lpthread" CACHE STRING "") +endif() + +set(BOOTSTRAP_LLVM_ENABLE_LTO ON CACHE BOOL "") +if(NOT APPLE) + set(BOOTSTRAP_LLVM_ENABLE_LLD ON CACHE BOOL "") +endif() + set(CLANG_BOOTSTRAP_TARGETS check-all check-llvm check-clang + check-lld llvm-config test-suite test-depends llvm-test-depends clang-test-depends + lld-test-depends distribution install-distribution install-distribution-stripped + install-distribution-toolchain clang CACHE STRING "") get_cmake_property(variableNames VARIABLES) diff --git a/docs/AutomaticReferenceCounting.rst b/docs/AutomaticReferenceCounting.rst index d8cda0c05f9e5213b766690f41b3a2853341daba..746c445f9019efd2487a0faadbb699062a1a8c84 100644 --- a/docs/AutomaticReferenceCounting.rst +++ b/docs/AutomaticReferenceCounting.rst @@ -9,7 +9,7 @@ /* * Automatic numbering is described in this article: - * http://dev.opera.com/articles/view/automatic-numbering-with-css-counters/ + * https://dev.opera.com/articles/view/automatic-numbering-with-css-counters/ */ /* * Automatic numbering for the TOC. @@ -1734,20 +1734,78 @@ A program is ill-formed if it refers to the ``NSAutoreleasePool`` class. rest of the language. Not draining the pool during an unwind is apparently required by the Objective-C exceptions implementation. +.. _arc.misc.externally_retained: + +Externally-Retained Variables +----------------------------- + +In some situations, variables with strong ownership are considered +externally-retained by the implementation. This means that the variable is +retained elsewhere, and therefore the implementation can elide retaining and +releasing its value. Such a variable is implicitly ``const`` for safety. In +contrast with ``__unsafe_unretained``, an externally-retained variable still +behaves as a strong variable outside of initialization and destruction. For +instance, when an externally-retained variable is captured in a block the value +of the variable is retained and released on block capture and destruction. It +also affects C++ features such as lambda capture, ``decltype``, and template +argument deduction. + +Implicitly, the implementation assumes that the :ref:`self parameter in a +non-init method ` and the :ref:`variable in a for-in loop +` are externally-retained. + +Externally-retained semantics can also be opted into with the +``objc_externally_retained`` attribute. This attribute can apply to strong local +variables, functions, methods, or blocks: + +.. code-block:: objc + + @class WobbleAmount; + + @interface Widget : NSObject + -(void)wobble:(WobbleAmount *)amount; + @end + + @implementation Widget + + -(void)wobble:(WobbleAmount *)amount + __attribute__((objc_externally_retained)) { + // 'amount' and 'alias' aren't retained on entry, nor released on exit. + __attribute__((objc_externally_retained)) WobbleAmount *alias = amount; + } + @end + +Annotating a function with this attribute makes every parameter with strong +retainable object pointer type externally-retained, unless the variable was +explicitly qualified with ``__strong``. For instance, ``first_param`` is +externally-retained (and therefore ``const``) below, but not ``second_param``: + +.. code-block:: objc + + __attribute__((objc_externally_retained)) + void f(NSArray *first_param, __strong NSArray *second_param) { + // ... + } + +You can test if your compiler has support for ``objc_externally_retained`` with +``__has_attribute``: + +.. code-block:: objc + + #if __has_attribute(objc_externally_retained) + // Use externally retained... + #endif + .. _arc.misc.self: ``self`` -------- -The ``self`` parameter variable of an Objective-C method is never actually -retained by the implementation. It is undefined behavior, or at least -dangerous, to cause an object to be deallocated during a message send to that -object. - -To make this safe, for Objective-C instance methods ``self`` is implicitly -``const`` unless the method is in the :ref:`init family -`. Further, ``self`` is **always** implicitly -``const`` within a class method. +The ``self`` parameter variable of an non-init Objective-C method is considered +:ref:`externally-retained ` by the implementation. +It is undefined behavior, or at least dangerous, to cause an object to be +deallocated during a message send to that object. In an init method, ``self`` +follows the :ref:``init family rules ``. .. admonition:: Rationale @@ -1758,9 +1816,9 @@ To make this safe, for Objective-C instance methods ``self`` is implicitly without this retain and release. Since it's extremely uncommon to actually do so, even unintentionally, and since there's no natural way for the programmer to remove this retain/release pair otherwise (as there is for - other parameters by, say, making the variable ``__unsafe_unretained``), we - chose to make this optimizing assumption and shift some amount of risk to the - user. + other parameters by, say, making the variable ``objc_externally_retained`` or + qualifying it with ``__unsafe_unretained``), we chose to make this optimizing + assumption and shift some amount of risk to the user. .. _arc.misc.enumeration: @@ -1769,8 +1827,9 @@ Fast enumeration iteration variables If a variable is declared in the condition of an Objective-C fast enumeration loop, and the variable has no explicit ownership qualifier, then it is -qualified with ``const __strong`` and objects encountered during the -enumeration are not actually retained. +implicitly :ref:`externally-retained ` so that +objects encountered during the enumeration are not actually retained and +released. .. admonition:: Rationale diff --git a/docs/ClangCommandLineReference.rst b/docs/ClangCommandLineReference.rst index 61abd05e0cc964e32bb4d6536d09d9fc2b5dc17e..e852c3e3879855cf293180b1880c27c54bad1d9d 100644 --- a/docs/ClangCommandLineReference.rst +++ b/docs/ClangCommandLineReference.rst @@ -158,7 +158,7 @@ Compile CUDA code for host only. Has no effect on non-CUDA compilations. .. option:: --cuda-include-ptx=, --no-cuda-include-ptx= -Include PTX for the follwing GPU architecture (e.g. sm\_35) or 'all'. May be specified more than once. +Include PTX for the following GPU architecture (e.g. sm\_35) or 'all'. May be specified more than once. .. option:: --cuda-noopt-device-debug, --no-cuda-noopt-device-debug diff --git a/docs/ClangFormat.rst b/docs/ClangFormat.rst index e9c236735bb5851eb721c0a40d1c633c475aec86..f2228c57505bd06840c4905268a65fe06f5a1772 100644 --- a/docs/ClangFormat.rst +++ b/docs/ClangFormat.rst @@ -200,6 +200,12 @@ So to reformat all the lines in the latest :program:`git` commit, just do: git diff -U0 --no-color HEAD^ | clang-format-diff.py -i -p1 +With Mercurial/:program:`hg`: + +.. code-block:: console + + hg diff -U0 --color=never | clang-format-diff.py -i -p1 + In an SVN client, you can do: .. code-block:: console diff --git a/docs/ClangFormatStyleOptions.rst b/docs/ClangFormatStyleOptions.rst index c9f4c4589a44737e2ff40c475ba627c85df5444c..ce821ba9c10f251cecd1a56ecaefd095f3870acd 100644 --- a/docs/ClangFormatStyleOptions.rst +++ b/docs/ClangFormatStyleOptions.rst @@ -137,13 +137,13 @@ the configuration (without a prefix: ``Auto``). `_ * ``Chromium`` A style complying with `Chromium's style guide - `_ + `_ * ``Mozilla`` A style complying with `Mozilla's style guide `_ * ``WebKit`` A style complying with `WebKit's style guide - `_ + `_ .. START_FORMAT_STYLE_OPTIONS @@ -1278,7 +1278,7 @@ the configuration (without a prefix: ``Auto``). used for ordering ``#includes``. `POSIX extended - `_ + `_ regular expressions are supported. These regular expressions are matched against the filename of an include @@ -1398,7 +1398,7 @@ the configuration (without a prefix: ``Auto``). **JavaImportGroups** (``std::vector``) A vector of prefixes ordered by the desired groups for Java imports. - Each group is seperated by a newline. Static imports will also follow the + Each group is separated by a newline. Static imports will also follow the same grouping convention above all non-static imports. One group's prefix can be a subset of another - the longest prefix is always matched. Within a group, the imports are ordered lexicographically. diff --git a/docs/ClangPlugins.rst b/docs/ClangPlugins.rst index 5e6082e903405a9b71b1000ef353a4049e1978d3..8d954407a4fc814895c94ba65babbde73bc6279a 100644 --- a/docs/ClangPlugins.rst +++ b/docs/ClangPlugins.rst @@ -69,7 +69,7 @@ Putting it all together Let's look at an example plugin that prints top-level function names. This example is checked into the clang repository; please take a look at the `latest version of PrintFunctionNames.cpp -`_. +`_. Running the plugin ================== @@ -110,7 +110,7 @@ source tree: -plugin -Xclang print-fns Also see the print-function-name plugin example's -`README `_ +`README `_ Using the clang command line diff --git a/docs/ClangStaticAnalyzer.rst b/docs/ClangStaticAnalyzer.rst new file mode 100644 index 0000000000000000000000000000000000000000..f18fd81384e5aa2f4eaa5240bb40841adeced484 --- /dev/null +++ b/docs/ClangStaticAnalyzer.rst @@ -0,0 +1,19 @@ +===================== +Clang Static Analyzer +===================== + +The Clang Static Analyzer is a source code analysis tool that finds bugs in C, C++, and Objective-C programs. +It implements *path-sensitive*, *inter-procedural analysis* based on *symbolic execution* technique. + +This is the Static Analyzer documentation page. + +See the `Official Tool Page `_. + +.. toctree:: + :caption: Table of Contents + :numbered: + :maxdepth: 2 + + analyzer/checkers + analyzer/developer-docs + diff --git a/docs/ClangTools.rst b/docs/ClangTools.rst index 99e8a5e4f685ce2d072aaeeae03185964e498b91..bc30459957abc986b3657f5664bb8e0af7aa00af 100644 --- a/docs/ClangTools.rst +++ b/docs/ClangTools.rst @@ -9,22 +9,9 @@ functionality such as fast syntax checking, automatic formatting, refactoring, etc. Only a couple of the most basic and fundamental tools are kept in the -primary Clang Subversion project. The rest of the tools are kept in a -side-project so that developers who don't want or need to build them -don't. If you want to get access to the extra Clang Tools repository, -simply check it out into the tools tree of your Clang checkout and -follow the usual process for building and working with a combined -LLVM/Clang checkout: - -- With Subversion: - - - ``cd llvm/tools/clang/tools`` - - ``svn co https://llvm.org/svn/llvm-project/clang-tools-extra/trunk extra`` - -- Or with Git: - - - ``cd llvm/tools/clang/tools`` - - ``git clone https://llvm.org/git/clang-tools-extra.git extra`` +primary Clang tree. The rest of the tools are kept in a separate +directory tree, `clang-tools-extra +`_. This document describes a high-level overview of the organization of Clang Tools within the project as well as giving an introduction to some diff --git a/docs/ControlFlowIntegrity.rst b/docs/ControlFlowIntegrity.rst index b0b37f83f1c7886f5d509f4de27618dbae847777..f57bdf5d2cbc7be100190611f9e330b6e2651435 100644 --- a/docs/ControlFlowIntegrity.rst +++ b/docs/ControlFlowIntegrity.rst @@ -335,7 +335,7 @@ Please refer to the :doc:`design document`. Publications ============ -`Control-Flow Integrity: Principles, Implementations, and Applications `_. +`Control-Flow Integrity: Principles, Implementations, and Applications `_. Martin Abadi, Mihai Budiu, Ăšlfar Erlingsson, Jay Ligatti. `Enforcing Forward-Edge Control-Flow Integrity in GCC & LLVM `_. diff --git a/docs/ControlFlowIntegrityDesign.rst b/docs/ControlFlowIntegrityDesign.rst index bb1770da5af4b650dd9e5bde52e9dd5a257bc56d..076713201a7197a72619492ec31183af54165527 100644 --- a/docs/ControlFlowIntegrityDesign.rst +++ b/docs/ControlFlowIntegrityDesign.rst @@ -92,7 +92,7 @@ The compiler relies on co-operation from the linker in order to assemble the bit vectors for the whole program. It currently does this using LLVM's `type metadata`_ mechanism together with link-time optimization. -.. _address point: http://itanium-cxx-abi.github.io/cxx-abi/abi.html#vtable-general +.. _address point: https://itanium-cxx-abi.github.io/cxx-abi/abi.html#vtable-general .. _type metadata: https://llvm.org/docs/TypeMetadata.html .. _ByteArrayBuilder: https://llvm.org/docs/doxygen/html/structllvm_1_1ByteArrayBuilder.html @@ -196,7 +196,7 @@ those sub-hierarchies need to be (see "Stripping Leading/Trailing Zeros in Bit Vectors" above). The `GlobalLayoutBuilder`_ class is responsible for laying out the globals efficiently to minimize the sizes of the underlying bitsets. -.. _GlobalLayoutBuilder: https://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/IPO/LowerTypeTests.h?view=markup +.. _GlobalLayoutBuilder: https://github.com/llvm/llvm-project/blob/master/llvm/include/llvm/Transforms/IPO/LowerTypeTests.h Alignment ~~~~~~~~~ @@ -300,7 +300,7 @@ The interleaving scheme, however, can only work with individual virtual tables s In comparison, the old scheme does not require the splitting but it is more efficient when the combined virtual tables have been split. The `GlobalSplit`_ pass is responsible for splitting combined virtual tables into individual ones. -.. _GlobalSplit: https://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/GlobalSplit.cpp?view=markup +.. _GlobalSplit: https://github.com/llvm/llvm-project/blob/master/llvm/lib/Transforms/IPO/GlobalSplit.cpp Order virtual tables by a pre-order traversal of the class hierarchy ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -746,7 +746,7 @@ RCFI does not protect `RET` instructions: * embedded into other instructions (e.g. `0f4fc3 cmovg %ebx,%eax`). .. _SafeStack: https://clang.llvm.org/docs/SafeStack.html -.. _RFG: http://xlab.tencent.com/en/2016/11/02/return-flow-guard +.. _RFG: https://xlab.tencent.com/en/2016/11/02/return-flow-guard .. _Intel CET: https://software.intel.com/en-us/blogs/2016/06/09/intel-release-new-technology-specifications-protect-rop-attacks Hardware support diff --git a/docs/DiagnosticsReference.rst b/docs/DiagnosticsReference.rst index 94502f9c49ec3201ea051604bb370c917bfc5661..7d9b1e8359a8d3ae156aaeb9a75eee6151ea8f4a 100644 --- a/docs/DiagnosticsReference.rst +++ b/docs/DiagnosticsReference.rst @@ -7885,6 +7885,10 @@ This diagnostic is enabled by default. | |+---------------------+| +-----------------------------------------------------------------------------------------------+-----------------------+ +-Woverride-init +--------------- +Synonym for `-Winitializer-overrides`_. + -Woverride-module ----------------- diff --git a/docs/ExternalClangExamples.rst b/docs/ExternalClangExamples.rst index b92fa3fcc068ff2479bd5de2b97c068691a00343..58c605a9a836384cd3236064c7a50c3dfe6e20cd 100644 --- a/docs/ExternalClangExamples.rst +++ b/docs/ExternalClangExamples.rst @@ -20,7 +20,7 @@ where Clang is used are: If you know of (or wrote!) a tool or project using Clang, please send an email to Clang's `development discussion mailing list -`_ to have it added. +`_ to have it added. (or if you are already a Clang contributor, feel free to directly commit additions). Since the primary purpose of this page is to provide examples that can help developers, generally they must have code available. @@ -33,7 +33,7 @@ List of projects and tools a persistent in-memory database of references, symbolnames, completions etc." -``_ +``_ "A C/C++ source code indexer and navigator" ``_ @@ -42,7 +42,7 @@ List of projects and tools ``_ "The Woboq Code Browser is a web-based code browser for C/C++ projects. - Check out ``_ for an example!" + Check out ``_ for an example!" ``_ "DXR is a source code cross-reference tool that uses static analysis diff --git a/docs/HardwareAssistedAddressSanitizerDesign.rst b/docs/HardwareAssistedAddressSanitizerDesign.rst index 4e6f5d14cde4cbce57d0afd2c4edadd888663036..6bbfcb7192cb472d962fb0408d88b111bc3ee107 100644 --- a/docs/HardwareAssistedAddressSanitizerDesign.rst +++ b/docs/HardwareAssistedAddressSanitizerDesign.rst @@ -162,7 +162,7 @@ Related Work * *TODO: add more "related work" links. Suggestions are welcome.* -.. _Watchdog: http://www.cis.upenn.edu/acg/papers/isca12_watchdog.pdf +.. _Watchdog: https://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 diff --git a/docs/HowToSetupToolingForLLVM.rst b/docs/HowToSetupToolingForLLVM.rst index 686aca840adaf5f7853f8d77291eb52f5c9f3dcf..dfa199ec5951acebdb635e9788ff5a349f057c95 100644 --- a/docs/HowToSetupToolingForLLVM.rst +++ b/docs/HowToSetupToolingForLLVM.rst @@ -23,7 +23,7 @@ Setup Clang Tooling Using CMake and Make ======================================== If you intend to use make to build LLVM, you should have CMake 2.8.6 or -later installed (can be found `here `_). +later installed (can be found `here `_). First, you need to generate Makefiles for LLVM with CMake. You need to make a build directory and run CMake from it: diff --git a/docs/InternalsManual.rst b/docs/InternalsManual.rst index b6b49d7547b02ce35810cb63af6bca02d7647219..0b180b95d5d658ea989c586588a991cbda788913 100644 --- a/docs/InternalsManual.rst +++ b/docs/InternalsManual.rst @@ -534,7 +534,7 @@ token. This concept maps directly to the "spelling location" for the token. ``SourceRange`` and ``CharSourceRange`` --------------------------------------- -.. mostly taken from http://lists.llvm.org/pipermail/cfe-dev/2010-August/010595.html +.. mostly taken from https://lists.llvm.org/pipermail/cfe-dev/2010-August/010595.html Clang represents most source ranges by [first, last], where "first" and "last" each point to the beginning of their respective tokens. For example consider @@ -1364,7 +1364,7 @@ constructed for function bodies (usually an instance of ``CompoundStmt``), but can also be instantiated to represent the control-flow of any class that subclasses ``Stmt``, which includes simple expressions. Control-flow graphs are especially useful for performing `flow- or path-sensitive -`_ program +`_ program analyses on a given function. Basic Blocks @@ -1686,7 +1686,7 @@ semantic checking for some attributes, etc. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The first step to adding a new attribute to Clang is to add its definition to `include/clang/Basic/Attr.td -`_. +`_. This tablegen definition must derive from the ``Attr`` (tablegen, not semantic) type, or one of its derivatives. Most attributes will derive from the ``InheritableAttr`` type, which specifies that the attribute can be inherited by @@ -1748,10 +1748,10 @@ the ``SubjectList``. The diagnostics generated for subject list violations are either ``diag::warn_attribute_wrong_decl_type`` or ``diag::err_attribute_wrong_decl_type``, and the parameter enumeration is found in `include/clang/Sema/ParsedAttr.h -`_ +`_ If a previously unused Decl node is added to the ``SubjectList``, the logic used to automatically determine the diagnostic parameter in `utils/TableGen/ClangAttrEmitter.cpp -`_ +`_ may need to be updated. By default, all subjects in the SubjectList must either be a Decl node defined @@ -1773,7 +1773,7 @@ All attributes must have some form of documentation associated with them. Documentation is table generated on the public web server by a server-side process that runs daily. Generally, the documentation for an attribute is a stand-alone definition in `include/clang/Basic/AttrDocs.td -`_ +`_ that is named after the attribute being documented. If the attribute is not for public consumption, or is an implicitly-created @@ -1824,7 +1824,7 @@ All arguments have a name and a flag that specifies whether the argument is optional. The associated C++ type of the argument is determined by the argument definition type. If the existing argument types are insufficient, new types can be created, but it requires modifying `utils/TableGen/ClangAttrEmitter.cpp -`_ +`_ to properly support the type. Other Properties @@ -1836,7 +1836,7 @@ document, however a few deserve mention. If the parsed form of the attribute is more complex, or differs from the semantic form, the ``HasCustomParsing`` bit can be set to ``1`` for the class, and the parsing code in `Parser::ParseGNUAttributeArgs() -`_ +`_ can be updated for the special case. Note that this only applies to arguments with a GNU spelling -- attributes with a __declspec spelling currently ignore this flag and are handled by ``Parser::ParseMicrosoftDeclSpec``. @@ -1899,7 +1899,7 @@ semantic attribute class object, with ``public`` access. Boilerplate ^^^^^^^^^^^ All semantic processing of declaration attributes happens in `lib/Sema/SemaDeclAttr.cpp -`_, +`_, and generally starts in the ``ProcessDeclAttribute()`` function. If the attribute is a "simple" attribute -- meaning that it requires no custom semantic processing aside from what is automatically provided, add a call to @@ -1915,11 +1915,11 @@ correct minimum number of arguments are passed, etc. If the attribute adds additional warnings, define a ``DiagGroup`` in `include/clang/Basic/DiagnosticGroups.td -`_ +`_ named after the attribute's ``Spelling`` with "_"s replaced by "-"s. If there is only a single diagnostic, it is permissible to use ``InGroup>`` directly in `DiagnosticSemaKinds.td -`_ +`_ All semantic diagnostics generated for your attribute, including automatically- generated ones (such as subjects and argument counts), should have a diff --git a/docs/IntroductionToTheClangAST.rst b/docs/IntroductionToTheClangAST.rst index f357c03507d3479ad91ccc21fbdedf36f10901d5..286ab88d01ef6a72e36fd72daeb0442f1b35993b 100644 --- a/docs/IntroductionToTheClangAST.rst +++ b/docs/IntroductionToTheClangAST.rst @@ -9,7 +9,7 @@ matchers. .. raw:: html -
+
`Slides `_ diff --git a/docs/JSONCompilationDatabase.rst b/docs/JSONCompilationDatabase.rst index 1f3441b033d40dabbc12614c4ce015ebbedf0940..b5766402e2d666a9b2efd1c8ba0fb26bba0ceffa 100644 --- a/docs/JSONCompilationDatabase.rst +++ b/docs/JSONCompilationDatabase.rst @@ -29,7 +29,7 @@ system is not necessarily the best solution: Supported Systems ================= -Currently `CMake `_ (since 2.8.5) supports generation +Currently `CMake `_ (since 2.8.5) supports generation of compilation databases for Unix Makefile builds (Ninja builds in the works) with the option ``CMAKE_EXPORT_COMPILE_COMMANDS``. diff --git a/docs/LanguageExtensions.rst b/docs/LanguageExtensions.rst index 0d358ad51a205da263777a72cd20efa16f24726b..d4c40b29f80efffebefb31e1992535e879403cb9 100644 --- a/docs/LanguageExtensions.rst +++ b/docs/LanguageExtensions.rst @@ -20,7 +20,7 @@ Introduction This document describes the language extensions provided by Clang. In addition to the language extensions listed here, Clang aims to support a broad range of GCC extensions. Please see the `GCC manual -`_ for more information on +`_ for more information on these extensions. .. _langext-feature_check: @@ -474,44 +474,58 @@ 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``). +``_Float16``. These types are supported in all language modes. + +``__fp16`` is supported on every target, as it is purely a storage format; see below. +``_Float16`` is currently only supported on the following targets, with further +targets pending ABI standardization: +- 32-bit ARM +- 64-bit ARM (AArch64) +- SPIR +``_Float16`` will be supported on more targets as they define ABIs for it. + +``__fp16`` is a storage and interchange format only. This means that values of +``__fp16`` are immediately promoted to (at least) ``float`` when used in arithmetic +operations, so that e.g. the result of adding two ``__fp16`` values has type ``float``. +The behavior of ``__fp16`` is specified by the ARM C Language Extensions (`ACLE `_). +Clang uses the ``binary16`` format from IEEE 754-2008 for ``__fp16``, not the ARM +alternative format. + +``_Float16`` is an extended floating-point type. This means that, just like arithmetic on +``float`` or ``double``, arithmetic on ``_Float16`` operands is formally performed in the +``_Float16`` type, so that e.g. the result of adding two ``_Float16`` values has type +``_Float16``. The behavior of ``_Float16`` is specified by ISO/IEC TS 18661-3:2015 +("Floating-point extensions for C"). As with ``__fp16``, Clang uses the ``binary16`` +format from IEEE 754-2008 for ``_Float16``. + +``_Float16`` arithmetic will be performed using native half-precision support +when available on the target (e.g. on ARMv8.2a); otherwise it will be performed +at a higher precision (currently always ``float``) and then truncated down to +``_Float16``. Note that C and C++ allow intermediate floating-point operands +of an expression to be computed with greater precision than is expressible in +their type, so Clang may avoid intermediate truncations in certain cases; this may +lead to results that are inconsistent with native arithmetic. + +It is recommended that portable code use ``_Float16`` instead of ``__fp16``, +as it has been defined by the C standards committee and has behavior that is +more familiar to most programmers. + +Because ``__fp16`` operands are always immediately promoted to ``float``, the +common real type of ``__fp16`` and ``_Float16`` for the purposes of the usual +arithmetic conversions is ``float``. + +A literal can be given ``_Float16`` type using the suffix ``f16``; for example: +``` +3.14f16 +``` + +Because default argument promotion only applies to the standard floating-point +types, ``_Float16`` values are not promoted to ``double`` when passed as variadic +or untyped arguments. As a consequence, some caution must be taken when using +certain library facilities with ``_Float16``; for example, there is no ``printf`` format +specifier for ``_Float16``, and (unlike ``float``) it will not be implicitly promoted to +``double`` when passed to ``printf``, so the programmer must explicitly cast it to +``double`` before using it with an ``%f`` or similar specifier. Messages on ``deprecated`` and ``unavailable`` Attributes ========================================================= @@ -1036,9 +1050,9 @@ the supported set of system headers, currently: * The Microsoft standard C++ library Clang supports the `GNU C++ type traits -`_ and a subset of the +`_ and a subset of the `Microsoft Visual C++ Type traits -`_. +`_. Feature detection is supported only for some of the primitives at present. User code should not use these checks because they bear no direct relation to the @@ -1354,7 +1368,7 @@ Objective-C retaining behavior attributes In Objective-C, functions and methods are generally assumed to follow the `Cocoa Memory Management -`_ +`_ conventions for ownership of object arguments and return values. However, there are exceptions, and so Clang provides attributes to allow these exceptions to be documented. This are used by ARC and the @@ -2218,7 +2232,7 @@ C++ Coroutines support builtins guaranteed. Clang provides experimental builtins to support C++ Coroutines as defined by -http://wg21.link/P0057. The following four are intended to be used by the +https://wg21.link/P0057. The following four are intended to be used by the standard library to implement `std::experimental::coroutine_handle` type. **Syntax**: @@ -2296,10 +2310,10 @@ Clang supports GCC's ``gnu`` attribute namespace. All GCC attributes which are accepted with the ``__attribute__((foo))`` syntax are also accepted as ``[[gnu::foo]]``. This only extends to attributes which are specified by GCC (see the list of `GCC function attributes -`_, `GCC variable -attributes `_, and +`_, `GCC variable +attributes `_, and `GCC type attributes -`_). As with the GCC +`_). As with the GCC implementation, these attributes must appertain to the *declarator-id* in a declaration, which means they must go either at the start of the declaration or immediately after the name being declared. @@ -2697,6 +2711,38 @@ The ``__declspec`` style syntax is also supported: A single push directive accepts only one attribute regardless of the syntax used. +Because multiple push directives can be nested, if you're writing a macro that +expands to ``_Pragma("clang attribute")`` it's good hygiene (though not +required) to add a namespace to your push/pop directives. A pop directive with a +namespace will pop the innermost push that has that same namespace. This will +ensure that another macro's ``pop`` won't inadvertently pop your attribute. Note +that an ``pop`` without a namespace will pop the innermost ``push`` without a +namespace. ``push``es with a namespace can only be popped by ``pop`` with the +same namespace. For instance: + +.. code-block:: c++ + + #define ASSUME_NORETURN_BEGIN _Pragma("clang attribute AssumeNoreturn.push ([[noreturn]], apply_to = function)") + #define ASSUME_NORETURN_END _Pragma("clang attribute AssumeNoreturn.pop") + + #define ASSUME_UNAVAILABLE_BEGIN _Pragma("clang attribute Unavailable.push (__attribute__((unavailable)), apply_to=function)") + #define ASSUME_UNAVAILABLE_END _Pragma("clang attribute Unavailable.pop") + + + ASSUME_NORETURN_BEGIN + ASSUME_UNAVAILABLE_BEGIN + void function(); // function has [[noreturn]] and __attribute__((unavailable)) + ASSUME_NORETURN_END + void other_function(); // function has __attribute__((unavailable)) + ASSUME_UNAVAILABLE_END + +Without the namespaces on the macros, ``other_function`` will be annotated with +``[[noreturn]]`` instead of ``__attribute__((unavailable))``. This may seem like +a contrived example, but its very possible for this kind of situation to appear +in real code if the pragmas are spread out across a large file. You can test if +your version of clang supports namespaces on ``#pragma clang attribute`` with +``__has_extension(pragma_clang_attribute_namespaces)``. + Subject Match Rules ------------------- @@ -2876,3 +2922,29 @@ 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. + +Evaluating Object Size Dynamically +================================== + +Clang supports the builtin ``__builtin_dynamic_object_size``, the semantics are +the same as GCC's ``__builtin_object_size`` (which Clang also supports), but +``__builtin_dynamic_object_size`` can evaluate the object's size at runtime. +``__builtin_dynamic_object_size`` is meant to be used as a drop-in replacement +for ``__builtin_object_size`` in libraries that support it. + +For instance, here is a program that ``__builtin_dynamic_object_size`` will make +safer: + +.. code-block:: c + + void copy_into_buffer(size_t size) { + char* buffer = malloc(size); + strlcpy(buffer, "some string", strlen("some string")); + // Previous line preprocesses to: + // __builtin___strlcpy_chk(buffer, "some string", strlen("some string"), __builtin_object_size(buffer, 0)) + } + +Since the size of ``buffer`` can't be known at compile time, Clang will fold +``__builtin_object_size(buffer, 0)`` into ``-1``. However, if this was written +as ``__builtin_dynamic_object_size(buffer, 0)``, Clang will fold it into +``size``, providing some extra runtime safety. diff --git a/docs/LibASTMatchersReference.html b/docs/LibASTMatchersReference.html index 27cb00b6bdfc2f2ac6d5f67cac765939a3dca090..6506282f08073f6aaff6183cb793b7c04178d7a6 100644 --- a/docs/LibASTMatchersReference.html +++ b/docs/LibASTMatchersReference.html @@ -718,7 +718,7 @@ Example matches a || b Matcher<Stmt>blockExprMatcher<BlockExpr>... -
MAtches a reference to a block.
+
Matches a reference to a block.
 
 Example: matches "^{}":
   void f() { ^{}(); }
@@ -4810,16 +4810,20 @@ with withInitializer matching (1)
 
 
 Matcher<CXXDependentScopeMemberExpr>hasObjectExpressionMatcher<Expr> InnerMatcher
-
Matches a member expression where the object expression is
-matched by a given matcher.
+
Matches a member expression where the object expression is matched by a
+given matcher. Implicit object expressions are included; that is, it matches
+use of implicit `this`.
 
 Given
-  struct X { int m; };
-  void f(X x) { x.m; m; }
-memberExpr(hasObjectExpression(hasType(cxxRecordDecl(hasName("X")))))))
-  matches "x.m" and "m"
-with hasObjectExpression(...)
-  matching "x" and the implicit object expression of "m" which has type X*.
+  struct X {
+    int m;
+    int f(X x) { x.m; return m; }
+  };
+memberExpr(hasObjectExpression(hasType(cxxRecordDecl(hasName("X")))))
+  matches `x.m`, but not `m`; however,
+memberExpr(hasObjectExpression(hasType(pointsTo(
+     cxxRecordDecl(hasName("X"))))))
+  matches `m` (aka. `this->m`), but not `x.m`.
 
@@ -4857,16 +4861,39 @@ matches 'a' in Matcher<CXXMemberCallExpr>onImplicitObjectArgumentMatcher<Expr> InnerMatcher -

+
Matches on the implicit object argument of a member call expression. Unlike
+`on`, matches the argument directly without stripping away anything.
+
+Given
+  class Y { public: void m(); };
+  Y g();
+  class X : public Y { void g(); };
+  void z(Y y, X x) { y.m(); x.m(); x.g(); (g()).m(); }
+cxxMemberCallExpr(onImplicitObjectArgument(hasType(
+    cxxRecordDecl(hasName("Y")))))
+  matches `y.m()`, `x.m()` and (g()).m(), but not `x.g()`.
+cxxMemberCallExpr(on(callExpr()))
+  does not match `(g()).m()`, because the parens are not ignored.
+
+FIXME: Overload to allow directly matching types?
+
Matcher<CXXMemberCallExpr>onMatcher<Expr> InnerMatcher -
Matches on the implicit object argument of a member call expression.
+
Matches on the implicit object argument of a member call expression, after
+stripping off any parentheses or implicit casts.
 
-Example matches y.x()
-  (matcher = cxxMemberCallExpr(on(hasType(cxxRecordDecl(hasName("Y"))))))
-  class Y { public: void x(); };
-  void z() { Y y; y.x(); }
+Given
+  class Y { public: void m(); };
+  Y g();
+  class X : public Y {};
+  void z(Y y, X x) { y.m(); (g()).m(); x.m(); }
+cxxMemberCallExpr(on(hasType(cxxRecordDecl(hasName("Y")))))
+  matches `y.m()` and `(g()).m()`.
+cxxMemberCallExpr(on(hasType(cxxRecordDecl(hasName("X")))))
+  matches `x.m()`.
+cxxMemberCallExpr(on(callExpr()))
+  matches `(g()).m()`.
 
 FIXME: Overload to allow directly matching types?
 
@@ -4878,8 +4905,20 @@ FIXME: Overload to allow directly matching types? Matcher<CXXMemberCallExpr>thisPointerTypeMatcher<QualType> InnerMatcher -
Matches if the expression's type either matches the specified
-matcher, or is a pointer to a type that matches the InnerMatcher.
+
Matches if the type of the expression's implicit object argument either
+matches the InnerMatcher, or is a pointer to a type that matches the
+InnerMatcher.
+
+Given
+  class Y { public: void m(); };
+  class X : public Y { void g(); };
+  void z() { Y y; y.m(); Y *p; p->m(); X x; x.m(); x.g(); }
+cxxMemberCallExpr(thisPointerType(hasDeclaration(
+    cxxRecordDecl(hasName("Y")))))
+  matches `y.m()`, `p->m()` and `x.m()`.
+cxxMemberCallExpr(thisPointerType(hasDeclaration(
+    cxxRecordDecl(hasName("X")))))
+  matches `x.g()`.
 
@@ -5866,6 +5905,15 @@ FIXME: Unit test this matcher
+Matcher<InitListExpr>hasInitunsigned N, ast_matchers::Matcher<Expr> InnerMatcher +
Matches the n'th item of an initializer list expression.
+
+Example matches y.
+    (matcher = initListExpr(hasInit(0, expr())))
+  int x{y}.
+
+ + Matcher<InitListExpr>hasSyntacticFormMatcher<Expr> InnerMatcher
Matches the syntactic form of init list expressions
 (if expression have it).
@@ -5975,16 +6023,20 @@ Usable as: Matcher<MemberExpr>hasObjectExpressionMatcher<Expr> InnerMatcher
-
Matches a member expression where the object expression is
-matched by a given matcher.
+
Matches a member expression where the object expression is matched by a
+given matcher. Implicit object expressions are included; that is, it matches
+use of implicit `this`.
 
 Given
-  struct X { int m; };
-  void f(X x) { x.m; m; }
-memberExpr(hasObjectExpression(hasType(cxxRecordDecl(hasName("X")))))))
-  matches "x.m" and "m"
-with hasObjectExpression(...)
-  matching "x" and the implicit object expression of "m" which has type X*.
+  struct X {
+    int m;
+    int f(X x) { x.m; return m; }
+  };
+memberExpr(hasObjectExpression(hasType(cxxRecordDecl(hasName("X")))))
+  matches `x.m`, but not `m`; however,
+memberExpr(hasObjectExpression(hasType(pointsTo(
+     cxxRecordDecl(hasName("X"))))))
+  matches `m` (aka. `this->m`), but not `x.m`.
 
@@ -6796,16 +6848,20 @@ Example matches true (matcher = hasUnaryOperand( Matcher<UnresolvedMemberExpr>hasObjectExpressionMatcher<Expr> InnerMatcher -
Matches a member expression where the object expression is
-matched by a given matcher.
+
Matches a member expression where the object expression is matched by a
+given matcher. Implicit object expressions are included; that is, it matches
+use of implicit `this`.
 
 Given
-  struct X { int m; };
-  void f(X x) { x.m; m; }
-memberExpr(hasObjectExpression(hasType(cxxRecordDecl(hasName("X")))))))
-  matches "x.m" and "m"
-with hasObjectExpression(...)
-  matching "x" and the implicit object expression of "m" which has type X*.
+  struct X {
+    int m;
+    int f(X x) { x.m; return m; }
+  };
+memberExpr(hasObjectExpression(hasType(cxxRecordDecl(hasName("X")))))
+  matches `x.m`, but not `m`; however,
+memberExpr(hasObjectExpression(hasType(pointsTo(
+     cxxRecordDecl(hasName("X"))))))
+  matches `m` (aka. `this->m`), but not `x.m`.
 
diff --git a/docs/LibASTMatchersTutorial.rst b/docs/LibASTMatchersTutorial.rst index 8b7ee7f98fa2dc8d0c0247763362e143e3a53841..24659a5209c9a99988720d7a15d8a49c78a78368 100644 --- a/docs/LibASTMatchersTutorial.rst +++ b/docs/LibASTMatchersTutorial.rst @@ -16,23 +16,16 @@ Step 0: Obtaining Clang ======================= As Clang is part of the LLVM project, you'll need to download LLVM's -source code first. Both Clang and LLVM are maintained as Subversion -repositories, but we'll be accessing them through the git mirror. For -further information, see the `getting started -guide `_. +source code first. Both Clang and LLVM are in the same git repository, +under different directories. For further information, see the `getting +started guide `_. .. code-block:: console - mkdir ~/clang-llvm && cd ~/clang-llvm - git clone https://llvm.org/git/llvm.git - cd llvm/tools - git clone https://llvm.org/git/clang.git - cd clang/tools - git clone https://llvm.org/git/clang-tools-extra.git extra + cd ~/clang-llvm + git clone https://github.com/llvm/llvm-project.git -Next you need to obtain the CMake build system and Ninja build tool. You -may already have CMake installed, but current binary versions of CMake -aren't built with Ninja support. +Next you need to obtain the CMake build system and Ninja build tool. .. code-block:: console @@ -57,7 +50,7 @@ Okay. Now we'll build Clang! cd ~/clang-llvm mkdir build && cd build - cmake -G Ninja ../llvm -DLLVM_BUILD_TESTS=ON # Enable tests; default is off. + cmake -G Ninja ../llvm -DLLVM_ENABLE_PROJECTS=clang -DLLVM_BUILD_TESTS=ON # Enable tests; default is off. ninja ninja check # Test LLVM only. ninja clang-test # Test Clang only. @@ -65,9 +58,7 @@ Okay. Now we'll build Clang! And we're live. -All of the tests should pass, though there is a (very) small chance that -you can catch LLVM and Clang out of sync. Running ``'git svn rebase'`` -in both the llvm and clang directories should fix any problems. +All of the tests should pass. Finally, we want to set Clang as its own compiler. diff --git a/docs/LibTooling.rst b/docs/LibTooling.rst index 41110f5d31493d6af0c8c104b93dfbc10b70704d..498baa2c46c3a2e9ae152cde50b7fec94b667f66 100644 --- a/docs/LibTooling.rst +++ b/docs/LibTooling.rst @@ -196,6 +196,6 @@ with ``-v`` and look at the search paths it looks through. Linking ^^^^^^^ -For a list of libraries to link, look at one of the tools' Makefiles (for -example `clang-check/Makefile -`_). +For a list of libraries to link, look at one of the tools' CMake files (for +example `clang-check/CMakeList.txt +`_). diff --git a/docs/MSVCCompatibility.rst b/docs/MSVCCompatibility.rst index cd2acae970290c8c1f2881c631f19fe514be44fd..b2486052abf9afb33da4f2a1d1517f6239132b62 100644 --- a/docs/MSVCCompatibility.rst +++ b/docs/MSVCCompatibility.rst @@ -68,8 +68,8 @@ The status of major ABI-impacting C++ features: base class`_. Clang does not yet support this. .. _#pragma pointers_to_members: - http://msdn.microsoft.com/en-us/library/83cch5a6.aspx -.. _/vm: http://msdn.microsoft.com/en-us/library/yad46a6z.aspx + https://msdn.microsoft.com/en-us/library/83cch5a6.aspx +.. _/vm: https://msdn.microsoft.com/en-us/library/yad46a6z.aspx .. _pointer to a member of a virtual base class: https://llvm.org/PR15713 * Debug info: :good:`Mostly complete`. Clang emits relatively complete CodeView diff --git a/docs/OpenMPSupport.rst b/docs/OpenMPSupport.rst index e8ec1e371b0498d941bb6839b377f091b3b4899c..a8bfddce63abef5989db92362bd533c8c337cd61 100644 --- a/docs/OpenMPSupport.rst +++ b/docs/OpenMPSupport.rst @@ -17,61 +17,50 @@ OpenMP Support ================== -Clang fully supports OpenMP 4.5. Clang supports offloading to X86_64, AArch64, -PPC64[LE] and has `basic support for Cuda devices`_. - -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: :good:`Complete`. - -* #pragma omp teams: :good:`Complete`. +Clang supports the following OpenMP 5.0 features -* #pragma omp distribute [simd]: :good:`Complete`. +* The `reduction`-based clauses in the `task` and `target`-based directives. -* #pragma omp distribute parallel for [simd]: :good:`Complete`. +* Support relational-op != (not-equal) as one of the canonical forms of random + access iterator. -Combined directives -=================== +* Support for mapping of the lambdas in target regions. -* #pragma omp parallel for simd: :good:`Complete`. +* Parsing/sema analysis for the requires directive. -* #pragma omp target parallel: :good:`Complete`. +* Nested declare target directives. -* #pragma omp target parallel for [simd]: :good:`Complete`. +* Make the `this` pointer implicitly mapped as `map(this[:1])`. -* #pragma omp target simd: :good:`Complete`. +* The `close` *map-type-modifier*. -* #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 fully supports OpenMP 4.5. Clang supports offloading to X86_64, AArch64, +PPC64[LE] and has `basic support for Cuda devices`_. -Clang does not support any constructs/updates from upcoming OpenMP 5.0 except -for `reduction`-based clauses in the `task` and `target`-based directives. +* #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. 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. -ows, and mac OS. +Interface (OMPT) on x86, x86_64, AArch64, and PPC64 on Linux, Windows, and macOS. + +General improvements +-------------------- +- New collapse clause scheme to avoid expensive remainder operations. + Compute loop index variables after collapsing a loop nest via the + collapse clause by replacing the expensive remainder operation with + multiplications and additions. + +- The default schedules for the `distribute` and `for` constructs in a + parallel region and in SPMD mode have changed to ensure coalesced + accesses. For the `distribute` construct, a static schedule is used + with a chunk size equal to the number of threads per team (default + value of threads or as specified by the `thread_limit` clause if + present). For the `for` construct, the schedule is static with chunk + size of one. + +- Simplified SPMD code generation for `distribute parallel for` when + the new default schedules are applicable. .. _basic support for Cuda devices: @@ -109,11 +98,19 @@ are stored in the global memory. In `Cuda` mode local variables are not shared between the threads and it is user responsibility to share the required data between the threads in the parallel regions. +Collapsed loop nest counter +--------------------------- + +When using the collapse clause on a loop nest the default behavior is to +automatically extend the representation of the loop counter to 64 bits for +the cases where the sizes of the collapsed loops are not known at compile +time. To prevent this conservative choice and use at most 32 bits, +compile your program with the `-fopenmp-optimistic-collapse`. + + Features not supported or with limited support for Cuda devices --------------------------------------------------------------- -- Reductions across the teams are not supported yet. - - Cancellation constructs are not supported. - Doacross loop nest is not supported. @@ -127,5 +124,8 @@ Features not supported or with limited support for Cuda devices - Automatic translation of math functions in target regions to device-specific math functions is not implemented yet. -- Debug information for OpenMP target regions is not supported yet. +- Debug information for OpenMP target regions is supported, but sometimes it may + be required to manually specify the address class of the inspected variables. + In some cases the local variables are actually allocated in the global memory, + but the debug info may be not aware of it. diff --git a/docs/PCHInternals.rst b/docs/PCHInternals.rst index 109260da9050ef8ecfec7550862a75a5304d5181..079fba16711dca3df56cbe14b4265ca7d611017e 100644 --- a/docs/PCHInternals.rst +++ b/docs/PCHInternals.rst @@ -332,7 +332,7 @@ expression is stored as a separate record (which keeps most records to a fixed size). Within the AST file, the subexpressions of an expression are stored, in reverse order, prior to the expression that owns those expression, using a form of `Reverse Polish Notation -`_. For example, an +`_. For example, an expression ``3 - 4 + 5`` would be represented as follows: +-----------------------+ diff --git a/docs/ReleaseNotes.rst b/docs/ReleaseNotes.rst index 2948812dc061423f2c09a1918b330853d37220f3..578dc1079b366f864c073a157f4b09a1e75b172c 100644 --- a/docs/ReleaseNotes.rst +++ b/docs/ReleaseNotes.rst @@ -1,5 +1,5 @@ ======================================= -Clang 8.0.0 (In-Progress) Release Notes +Clang 9.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 8 release. + These are in-progress notes for the upcoming Clang 9 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 8.0.0. Here we +frontend, part of the LLVM Compiler Infrastructure, release 9.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 8.0.0? +What's New in Clang 9.0.0? ========================== Some of the major new features and improvements to Clang are listed @@ -46,96 +46,22 @@ sections with improvements to Clang's support for those languages. Major New Features ------------------ -- Clang supports use of a profile remapping file, which permits - profile data captured for one version of a program to be applied - when building another version where symbols have changed (for - example, due to renaming a class or namespace). - See the :doc:`UsersManual` for details. +- ... Improvements to Clang's diagnostics ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- ``-Wextra-semi-stmt`` is a new diagnostic that diagnoses extra semicolons, - much like ``-Wextra-semi``. This new diagnostic diagnoses all *unnecessary* - null statements (expression statements without an expression), unless: the - semicolon directly follows a macro that was expanded to nothing or if the - semicolon is within the macro itself. This applies to macros defined in system - headers as well as user-defined macros. - - .. code-block:: c++ - - #define MACRO(x) int x; - #define NULLMACRO(varname) - - void test() { - ; // <- warning: ';' with no preceding expression is a null statement - - while (true) - ; // OK, it is needed. - - switch (my_enum) { - case E1: - // stuff - break; - case E2: - ; // OK, it is needed. - } - - MACRO(v0;) // Extra semicolon, but within macro, so ignored. - - MACRO(v1); // <- warning: ';' with no preceding expression is a null statement - - NULLMACRO(v2); // ignored, NULLMACRO expanded to nothing. - } - -- ``-Wempty-init-stmt`` is a new diagnostic that diagnoses empty init-statements - of ``if``, ``switch``, ``range-based for``, unless: the semicolon directly - follows a macro that was expanded to nothing or if the semicolon is within the - macro itself (both macros from system headers, and normal macros). This - diagnostic is in the ``-Wextra-semi-stmt`` group and is enabled in - ``-Wextra``. - - .. code-block:: c++ - - void test() { - if(; // <- warning: init-statement of 'if' is a null statement - true) - ; - - switch (; // <- warning: init-statement of 'switch' is a null statement - x) { - ... - } - - for (; // <- warning: init-statement of 'range-based for' is a null statement - int y : S()) - ; - } - +- ... Non-comprehensive list of changes in this release ------------------------------------------------- -- The experimental feature Pretokenized Headers (PTH) was removed in its - entirely from Clang. The feature did not properly work with about 1/3 of the - possible tokens available and was unmaintained. +- ... -- The internals of libc++ include directory detection on MacOS have changed. - Instead of running a search based on the ``-resource-dir`` flag, the search - is now based on the path of the compiler in the filesystem. The default - behaviour should not change. However, if you override ``-resource-dir`` - manually and rely on the old behaviour you will need to add appropriate - compiler flags for finding the corresponding libc++ include directory. New Compiler Flags ------------------ -- ``-fprofile-filter-files=[regexes]`` and ``-fprofile-exclude-files=[regexes]``. - - Clang has now options to filter or exclude some files when - instrumenting for gcov-based profiling. - See the :doc:`UsersManual` for details. - - ... Deprecated Compiler Flags @@ -149,17 +75,12 @@ future versions of Clang. Modified Compiler Flags ----------------------- -- As of clang 8, `alignof` and `_Alignof` return the ABI alignment of a type, - as opposed to the preferred alignment. `__alignof` still returns the - preferred alignment. `-fclang-abi-compat=7` (and previous) will make - `alignof` and `_Alignof` return preferred alignment again. - +- ... New Pragmas in Clang -------------------- -- Clang now supports adding multiple `#pragma clang attribute` attributes into - a scope of pushed attributes. +- ... Attribute Changes in Clang -------------------------- @@ -169,16 +90,6 @@ Attribute Changes in Clang Windows Support --------------- -- clang-cl now supports the use of the precompiled header options /Yc and /Yu - without the filename argument. When these options are used without the - filename, a `#pragma hdrstop` inside the source marks the end of the - precompiled code. - -- clang-cl has a new command-line option, ``/Zc:dllexportInlines-``, similar to - ``-fvisibility-inlines-hidden`` on non-Windows, that makes class-level - `dllexport` and `dllimport` attributes not apply to inline member functions. - This can significantly reduce compile and link times. See the `User's Manual - `_ for more info. - ... @@ -217,31 +128,22 @@ OpenCL C Language Changes in Clang ABI Changes in Clang -------------------- -- `_Alignof` and `alignof` now return the ABI alignment of a type, as opposed - to the preferred alignment. - - - This is more in keeping with the language of the standards, as well as - being compatible with gcc - - `__alignof` and `__alignof__` still return the preferred alignment of - a type - - This shouldn't break any ABI except for things that explicitly ask for - `alignas(alignof(T))`. - - If you have interfaces that break with this change, you may wish to switch - to `alignas(__alignof(T))`, instead of using the `-fclang-abi-compat` - switch. +- ... OpenMP Support in Clang ---------------------------------- +- Added emission of the debug information for NVPTX target devices. CUDA Support in Clang --------------------- +- Added emission of the debug information for the device code. Internal API Changes -------------------- -These are major API changes that have happened since the 7.0.0 release of +These are major API changes that have happened since the 8.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. @@ -261,7 +163,11 @@ clang-format libclang -------- -... +- When `CINDEXTEST_INCLUDE_ATTRIBUTED_TYPES` is not provided when making a + CXType, the equivalent type of the AttributedType is returned instead of the + modified type if the user does not want attribute sugar. The equivalent type + represents the minimally-desugared type which the AttributedType is + canonically equivalent to. Static Analyzer @@ -276,32 +182,7 @@ Static Analyzer Undefined Behavior Sanitizer (UBSan) ------------------------------------ -* The Implicit Conversion Sanitizer (``-fsanitize=implicit-conversion``) group - was extended. One more type of issues is caught - implicit integer sign change. - (``-fsanitize=implicit-integer-sign-change``). - This makes the Implicit Conversion Sanitizer feature-complete, - with only missing piece being bitfield handling. - While there is a ``-Wsign-conversion`` diagnostic group that catches this kind - of issues, it is both noisy, and does not catch **all** the cases. - - .. code-block:: c++ - - bool consume(unsigned int val); - - void test(int val) { - (void)consume(val); // If the value was negative, it is now large positive. - (void)consume((unsigned int)val); // OK, the conversion is explicit. - } - - Like some other ``-fsanitize=integer`` checks, these issues are **not** - undefined behaviour. But they are not *always* intentional, and are somewhat - hard to track down. This group is **not** enabled by ``-fsanitize=undefined``, - but the ``-fsanitize=implicit-integer-sign-change`` check - is enabled by ``-fsanitize=integer``. - (as is ``-fsanitize=implicit-integer-truncation`` check) - -* The Implicit Conversion Sanitizer (``-fsanitize=implicit-conversion``) has - learned to sanitize compound assignment operators. +- ... Core Analysis Improvements ========================== diff --git a/docs/SafeStack.rst b/docs/SafeStack.rst index b046aa6168981851bf4a312fe3bfdc470f304ff7..c1e09da93557944df91afe50b30967b4e92fcef6 100644 --- a/docs/SafeStack.rst +++ b/docs/SafeStack.rst @@ -18,14 +18,14 @@ buffer overflows on the unsafe stack cannot be used to overwrite anything on the safe stack. SafeStack is a part of the `Code-Pointer Integrity (CPI) Project -`_. +`_. Performance ----------- The performance overhead of the SafeStack instrumentation is less than 0.1% on average across a variety of benchmarks (see the `Code-Pointer Integrity -`__ paper for details). This is mainly +`__ paper for details). This is mainly because most small functions do not have any variables that require the unsafe stack and, hence, do not need unsafe stack frames to be created. The cost of creating unsafe stack frames for large functions is amortized by the cost of @@ -84,9 +84,9 @@ Known security limitations A complete protection against control-flow hijack attacks requires combining SafeStack with another mechanism that enforces the integrity of code pointers that are stored on the heap or the unsafe stack, such as `CPI -`_, or a forward-edge control flow integrity +`_, or a forward-edge control flow integrity mechanism that enforces correct calling conventions at indirect call sites, -such as `IFCC `_ with arity +such as `IFCC `_ with arity checks. Clang has control-flow integrity protection scheme for :doc:`C++ virtual calls `, but not non-virtual indirect calls. With SafeStack alone, an attacker can overwrite a function pointer on the heap or @@ -106,7 +106,7 @@ prevented by adjusting such functions to either encrypt the stack pointer when storing it in the heap (as already done e.g., by ``setjmp``/``longjmp`` implementation in glibc), or store it in a safe region instead. -The `CPI paper `_ describes two alternative, +The `CPI paper `_ describes two alternative, stronger safe stack protection mechanisms, that rely on software fault isolation, or hardware segmentation (as available on x86-32 and some x86-64 CPUs). @@ -186,14 +186,14 @@ Deprecated: This builtin function is an alias for Design ====== -Please refer to the `Code-Pointer Integrity `__ +Please refer to the `Code-Pointer Integrity `__ project page for more information about the design of the SafeStack and its related technologies. setjmp and exception handling ----------------------------- -The `OSDI'14 paper `_ mentions that +The `OSDI'14 paper `_ mentions that on Linux the instrumentation pass finds calls to setjmp or functions that may throw an exception, and inserts required instrumentation at their call sites. Specifically, the instrumentation pass saves the shadow stack pointer @@ -204,7 +204,7 @@ in the function ``SafeStack::createStackRestorePoints``. Publications ------------ -`Code-Pointer Integrity `__. +`Code-Pointer Integrity `__. Volodymyr Kuznetsov, Laszlo Szekeres, Mathias Payer, George Candea, R. Sekar, Dawn Song. USENIX Symposium on Operating Systems Design and Implementation (`OSDI `_), Broomfield, CO, October 2014 diff --git a/docs/SanitizerCoverage.rst b/docs/SanitizerCoverage.rst index f3f13c83176039a04217cc75ed894c47b621fe76..c7cd853dd66b3c3f8226d1655bed9d084d149cac 100644 --- a/docs/SanitizerCoverage.rst +++ b/docs/SanitizerCoverage.rst @@ -144,6 +144,11 @@ PC-Table **Experimental, may change or disappear in future** +**Note:** this instrumentation might be incompatible with dead code stripping +(``-Wl,-gc-sections``) for linkers other than LLD, thus resulting in a +significant binary size overhead. For more information, see +`Bug 34636 `_. + With ``-fsanitize-coverage=pc-table`` the compiler will create a table of instrumented PCs. Requires either ``-fsanitize-coverage=inline-8bit-counters`` or ``-fsanitize-coverage=trace-pc-guard``. @@ -222,9 +227,9 @@ It contains 3 basic blocks, let's name them A, B, C: If blocks A, B, and C are all covered we know for certain that the edges A=>B and B=>C were executed, but we still don't know if the edge A=>C was executed. Such edges of control flow graph are called -`critical `_. The -edge-level coverage simply splits all critical -edges by introducing new dummy blocks and then instruments those blocks: +`critical `_. +The edge-level coverage simply splits all critical edges by introducing new +dummy blocks and then instruments those blocks: .. code-block:: none @@ -248,6 +253,9 @@ and with ``-fsanitize-coverage=trace-gep`` -- the `LLVM GEP instructions `_ (to capture array indices). +Unless ``no-prune`` option is provided, some of the comparison instructions +will not be instrumented. + .. code-block:: c++ // Called before a comparison instruction. diff --git a/docs/ShadowCallStack.rst b/docs/ShadowCallStack.rst index da609dcd9de47404beda5663b6c39ba52200a2ab..c1284f7c2dea3049e269f367e39066745b9ec062 100644 --- a/docs/ShadowCallStack.rst +++ b/docs/ShadowCallStack.rst @@ -8,28 +8,45 @@ ShadowCallStack Introduction ============ -ShadowCallStack is an **experimental** instrumentation pass, currently only -implemented for x86_64 and aarch64, that protects programs against return -address overwrites (e.g. stack buffer overflows.) It works by saving a -function's return address to a separately allocated 'shadow call stack' -in the function prolog and checking the return address on the stack against -the shadow call stack in the function epilog. +ShadowCallStack is an instrumentation pass, currently only implemented for +aarch64 and x86_64, that protects programs against return address overwrites +(e.g. stack buffer overflows.) It works by saving a function's return address +to a separately allocated 'shadow call stack' in the function prolog in +non-leaf functions and loading the return address from the shadow call stack +in the function epilog. The return address is also stored on the regular stack +for compatibility with unwinders, but is otherwise unused. + +The aarch64 implementation is considered production ready, and +an `implementation of the runtime`_ has been added to Android's libc +(bionic). The x86_64 implementation was evaluated using Chromium and was +found to have critical performance and security deficiencies, and may be +removed in a future release of the compiler. This document only describes +the aarch64 implementation; details on the x86_64 implementation are found +in the `Clang 7.0.1 documentation`_. + +.. _`implementation of the runtime`: https://android.googlesource.com/platform/bionic/+/808d176e7e0dd727c7f929622ec017f6e065c582/libc/bionic/pthread_create.cpp#128 +.. _`Clang 7.0.1 documentation`: https://releases.llvm.org/7.0.1/tools/clang/docs/ShadowCallStack.html Comparison ---------- -To optimize for memory consumption and cache locality, the shadow call stack -stores an index followed by an array of return addresses. This is in contrast -to other schemes, like :doc:`SafeStack`, that mirror the entire stack and -trade-off consuming more memory for shorter function prologs and epilogs with -fewer memory accesses. Similarly, `Return Flow Guard`_ consumes more memory with -shorter function prologs and epilogs than ShadowCallStack but suffers from the -same race conditions (see `Security`_). Intel `Control-flow Enforcement Technology`_ -(CET) is a proposed hardware extension that would add native support to -use a shadow stack to store/check return addresses at call/return time. It -would not suffer from race conditions at calls and returns and not incur the -overhead of function instrumentation, but it does require operating system -support. +To optimize for memory consumption and cache locality, the shadow call +stack stores only an array of return addresses. This is in contrast to other +schemes, like :doc:`SafeStack`, that mirror the entire stack and trade-off +consuming more memory for shorter function prologs and epilogs with fewer +memory accesses. + +`Return Flow Guard`_ is a pure software implementation of shadow call stacks +on x86_64. It is similar to the ShadowCallStack x86_64 implementation but +trades off higher memory usage for a shorter prologue and epilogue. Like +x86_64 ShadowCallStack, it is inherently racy due to the architecture's use +of the stack for calls and returns. + +Intel `Control-flow Enforcement Technology`_ (CET) is a proposed hardware +extension that would add native support to use a shadow stack to store/check +return addresses at call/return time. Being a hardware implementation, it +would not suffer from race conditions and would not incur the overhead of +function instrumentation, but it does require operating system support. .. _`Return Flow Guard`: https://xlab.tencent.com/en/2016/11/02/return-flow-guard/ .. _`Control-flow Enforcement Technology`: https://software.intel.com/sites/default/files/managed/4d/2a/control-flow-enforcement-technology-preview.pdf @@ -37,57 +54,96 @@ support. Compatibility ------------- -ShadowCallStack currently only supports x86_64 and aarch64. A runtime is not -currently provided in compiler-rt so one must be provided by the compiled -application. - -On aarch64, the instrumentation makes use of the platform register ``x18``. -On some platforms, ``x18`` is reserved, and on others, it is designated as -a scratch register. This generally means that any code that may run on the -same thread as code compiled with ShadowCallStack must either target one -of the platforms whose ABI reserves ``x18`` (currently Darwin, Fuchsia and -Windows) or be compiled with the flag ``-ffixed-x18``. +A runtime is not provided in compiler-rt so one must be provided by the +compiled application or the operating system. Integrating the runtime into +the operating system should be preferred since otherwise all thread creation +and destruction would need to be intercepted by the application. + +The instrumentation makes use of the platform register ``x18``. On some +platforms, ``x18`` is reserved, and on others, it is designated as a scratch +register. This generally means that any code that may run on the same thread +as code compiled with ShadowCallStack must either target one of the platforms +whose ABI reserves ``x18`` (currently Android, Darwin, Fuchsia and Windows) +or be compiled with the flag ``-ffixed-x18``. If absolutely necessary, code +compiled without ``-ffixed-x18`` may be run on the same thread as code that +uses ShadowCallStack by saving the register value temporarily on the stack +(`example in Android`_) but this should be done with care since it risks +leaking the shadow call stack address. + +.. _`example in Android`: https://android-review.googlesource.com/c/platform/frameworks/base/+/803717 + +Because of the use of register ``x18``, the ShadowCallStack feature is +incompatible with any other feature that may use ``x18``. However, there +is no inherent reason why ShadowCallStack needs to use register ``x18`` +specifically; in principle, a platform could choose to reserve and use another +register for ShadowCallStack, but this would be incompatible with the AAPCS64. + +Special unwind information is required on functions that are compiled +with ShadowCallStack and that may be unwound, i.e. functions compiled with +``-fexceptions`` (which is the default in C++). Some unwinders (such as the +libgcc 4.9 unwinder) do not understand this unwind info and will segfault +when encountering it. LLVM libunwind processes this unwind info correctly, +however. This means that if exceptions are used together with ShadowCallStack, +the program must use a compatible unwinder. Security ======== ShadowCallStack is intended to be a stronger alternative to ``-fstack-protector``. It protects from non-linear overflows and arbitrary -memory writes to the return address slot; however, similarly to -``-fstack-protector`` this protection suffers from race conditions because of -the call-return semantics on x86_64. There is a short race between the call -instruction and the first instruction in the function that reads the return -address where an attacker could overwrite the return address and bypass -ShadowCallStack. Similarly, there is a time-of-check-to-time-of-use race in the -function epilog where an attacker could overwrite the return address after it -has been checked and before it has been returned to. Modifying the call-return -semantics to fix this on x86_64 would incur an unacceptable performance overhead -due to return branch prediction. - -The instrumentation makes use of the ``gs`` segment register on x86_64, -or the ``x18`` register on aarch64, to reference the shadow call stack -meaning that references to the shadow call stack do not have to be stored in -memory. This makes it possible to implement a runtime that avoids exposing -the address of the shadow call stack to attackers that can read arbitrary -memory. However, attackers could still try to exploit side channels exposed -by the operating system `[1]`_ `[2]`_ or processor `[3]`_ to discover the -address of the shadow call stack. +memory writes to the return address slot. + +The instrumentation makes use of the ``x18`` register to reference the shadow +call stack, meaning that references to the shadow call stack do not have +to be stored in memory. This makes it possible to implement a runtime that +avoids exposing the address of the shadow call stack to attackers that can +read arbitrary memory. However, attackers could still try to exploit side +channels exposed by the operating system `[1]`_ `[2]`_ or processor `[3]`_ +to discover the address of the shadow call stack. .. _`[1]`: https://eyalitkin.wordpress.com/2017/09/01/cartography-lighting-up-the-shadows/ .. _`[2]`: https://www.blackhat.com/docs/eu-16/materials/eu-16-Goktas-Bypassing-Clangs-SafeStack.pdf .. _`[3]`: https://www.vusec.net/projects/anc/ -On x86_64, leaf functions are optimized to store the return address in a -free register and avoid writing to the shadow call stack if a register is -available. Very short leaf functions are uninstrumented if their execution -is judged to be shorter than the race condition window intrinsic to the -instrumentation. - -On aarch64, the architecture's call and return instructions (``bl`` and -``ret``) operate on a register rather than the stack, which means that -leaf functions are generally protected from return address overwrites even -without ShadowCallStack. It also means that ShadowCallStack on aarch64 is not -vulnerable to the same types of time-of-check-to-time-of-use races as x86_64. +Unless care is taken when allocating the shadow call stack, it may be +possible for an attacker to guess its address using the addresses of +other allocations. Therefore, the address should be chosen to make this +difficult. One way to do this is to allocate a large guard region without +read/write permissions, randomly select a small region within it to be +used as the address of the shadow call stack and mark only that region as +read/write. This also mitigates somewhat against processor side channels. +The intent is that the Android runtime `will do this`_, but the platform will +first need to be `changed`_ to avoid using ``setrlimit(RLIMIT_AS)`` to limit +memory allocations in certain processes, as this also limits the number of +guard regions that can be allocated. + +.. _`will do this`: https://android-review.googlesource.com/c/platform/bionic/+/891622 +.. _`changed`: https://android-review.googlesource.com/c/platform/frameworks/av/+/837745 + +The runtime will need the address of the shadow call stack in order to +deallocate it when destroying the thread. If the entire program is compiled +with ``-ffixed-x18``, this is trivial: the address can be derived from the +value stored in ``x18`` (e.g. by masking out the lower bits). If a guard +region is used, the address of the start of the guard region could then be +stored at the start of the shadow call stack itself. But if it is possible +for code compiled without ``-ffixed-x18`` to run on a thread managed by the +runtime, which is the case on Android for example, the address must be stored +somewhere else instead. On Android we store the address of the start of the +guard region in TLS and deallocate the entire guard region including the +shadow call stack at thread exit. This is considered acceptable given that +the address of the start of the guard region is already somewhat guessable. + +One way in which the address of the shadow call stack could leak is in the +``jmp_buf`` data structure used by ``setjmp`` and ``longjmp``. The Android +runtime `avoids this`_ by only storing the low bits of ``x18`` in the +``jmp_buf``, which requires the address of the shadow call stack to be +aligned to its size. + +.. _`avoids this`: https://android.googlesource.com/platform/bionic/+/808d176e7e0dd727c7f929622ec017f6e065c582/libc/arch-arm64/bionic/setjmp.S#49 + +The architecture's call and return instructions (``bl`` and ``ret``) operate on +a register rather than the stack, which means that leaf functions are generally +protected from return address overwrites even without ShadowCallStack. Usage ===== @@ -132,17 +188,7 @@ The following example code: return bar() + 1; } -Generates the following x86_64 assembly when compiled with ``-O2``: - -.. code-block:: gas - - push %rax - callq bar - add $0x1,%eax - pop %rcx - retq - -or the following aarch64 assembly: +Generates the following aarch64 assembly when compiled with ``-O2``: .. code-block:: none @@ -153,33 +199,7 @@ or the following aarch64 assembly: ldp x29, x30, [sp], #16 ret - -Adding ``-fsanitize=shadow-call-stack`` would output the following x86_64 -assembly: - -.. code-block:: gas - - mov (%rsp),%r10 - xor %r11,%r11 - addq $0x8,%gs:(%r11) - mov %gs:(%r11),%r11 - mov %r10,%gs:(%r11) - push %rax - callq bar - add $0x1,%eax - pop %rcx - xor %r11,%r11 - mov %gs:(%r11),%r10 - mov %gs:(%r10),%r10 - subq $0x8,%gs:(%r11) - cmp %r10,(%rsp) - jne trap - retq - - trap: - ud2 - -or the following aarch64 assembly: +Adding ``-fsanitize=shadow-call-stack`` would output the following assembly: .. code-block:: none diff --git a/docs/Toolchain.rst b/docs/Toolchain.rst index 0da20eb046251309dcf14096493f70c9926ec417..da65f14597b17059db163ab8befd1f5ff3673c12 100644 --- a/docs/Toolchain.rst +++ b/docs/Toolchain.rst @@ -100,14 +100,14 @@ currently-supported languages are: In each case, GCC will be invoked to compile the input. -Assember --------- +Assembler +--------- 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 integrated assembler on all targets where it is -supported. If you wish to use the system assember instead, use the +supported. If you wish to use the system assembler instead, use the ``-fno-integrated-as`` option. Linker @@ -117,7 +117,7 @@ Clang can be configured to use one of several different linkers: * GNU ld * GNU gold -* LLVM's `lld `_ +* LLVM's `lld `_ * MSVC's link.exe Link-time optimization is natively supported by lld, and supported via @@ -164,7 +164,7 @@ other targets, compiler-rt is used by default. compiler-rt (LLVM) ^^^^^^^^^^^^^^^^^^ -`LLVM's compiler runtime library `_ provides a +`LLVM's compiler runtime library `_ provides a complete set of runtime library functions containing all functions that Clang will implicitly call, in ``libclang_rt.builtins..a``. @@ -222,21 +222,15 @@ Unwind library The unwind library provides a family of ``_Unwind_*`` functions implementing the language-neutral stack unwinding portion of the Itanium C++ ABI -(`Level I `_). +(`Level I `_). It is a dependency of the C++ ABI library, and sometimes is a dependency of other runtimes. libunwind (LLVM) ^^^^^^^^^^^^^^^^ -LLVM's unwinder library can be obtained from subversion: - -.. code-block:: console - - llvm-src$ svn co https://llvm.org/svn/llvm-project/libunwind/trunk projects/libunwind - -When checked out into projects/libunwind within an LLVM checkout, -it should be automatically picked up by the LLVM build system. +LLVM's unwinder library is part of the llvm-project git repository. To +build it, pass ``-DLLVM_ENABLE_PROJECTS=libunwind`` to the cmake invocation. If using libc++abi, you may need to configure it to use libunwind rather than libgcc_s by passing ``-DLIBCXXABI_USE_LLVM_UNWINDER=YES`` @@ -254,7 +248,7 @@ libunwind (nongnu.org) ^^^^^^^^^^^^^^^^^^^^^^ This is another implementation of the libunwind specification. -See `libunwind (nongnu.org) `_. +See `libunwind (nongnu.org) `_. libunwind (PathScale) ^^^^^^^^^^^^^^^^^^^^^ @@ -279,7 +273,7 @@ C standard library ------------------ Clang supports a wide variety of -`C standard library `_ +`C standard library `_ implementations. C++ ABI library @@ -288,9 +282,9 @@ C++ ABI library The C++ ABI library provides an implementation of the library portion of the Itanium C++ ABI, covering both the `support functionality in the main Itanium C++ ABI document -`_ and +`_ and `Level II of the exception handling support -`_. +`_. References to the functions and objects in this library are implicitly generated by Clang when compiling C++ code. @@ -306,7 +300,7 @@ available: libc++abi (LLVM) ^^^^^^^^^^^^^^^^ -`libc++abi `_ is LLVM's implementation of this +`libc++abi `_ is LLVM's implementation of this specification. libsupc++ (GNU) @@ -332,12 +326,12 @@ C++ standard library -------------------- Clang supports use of either LLVM's libc++ or GCC's libstdc++ implementation -of the `C++ standard library `_. +of the `C++ standard library `_. libc++ (LLVM) ^^^^^^^^^^^^^ -`libc++ `_ is LLVM's implementation of the C++ +`libc++ `_ is LLVM's implementation of the C++ standard library, aimed at being a complete implementation of the C++ standards from C++11 onwards. diff --git a/docs/UndefinedBehaviorSanitizer.rst b/docs/UndefinedBehaviorSanitizer.rst index ddffee85c98d9e6ab77a479019129d217788a975..1e06a181b23185da91af93f0c365591e39f0e8c0 100644 --- a/docs/UndefinedBehaviorSanitizer.rst +++ b/docs/UndefinedBehaviorSanitizer.rst @@ -72,7 +72,7 @@ Available checks Available checks are: - ``-fsanitize=alignment``: Use of a misaligned pointer or creation - of a misaligned reference. + of a misaligned reference. Also sanitizes assume_aligned-like attributes. - ``-fsanitize=bool``: Load of a ``bool`` value which is neither ``true`` nor ``false``. - ``-fsanitize=builtin``: Passing invalid values to compiler builtins. @@ -338,4 +338,4 @@ More Information `_ * From John Regehr's *Embedded in Academia* blog: `A Guide to Undefined Behavior in C and C++ - `_ + `_ diff --git a/docs/UsersManual.rst b/docs/UsersManual.rst index e47a2e402dae370cd9086290c20904f7cb10fadd..f004f20909b0e929df53027bd7c3862b4deba77b 100644 --- a/docs/UsersManual.rst +++ b/docs/UsersManual.rst @@ -15,8 +15,8 @@ programming languages, aiming to be the best in class implementation of these languages. Clang builds on the LLVM optimizer and code generator, allowing it to provide high-quality optimization and code generation support for many targets. For more general information, please see the -`Clang Web Site `_ or the `LLVM Web -Site `_. +`Clang Web Site `_ or the `LLVM Web +Site `_. This document describes important notes about using Clang as a compiler for an end-user, documenting the supported features, command line @@ -994,7 +994,7 @@ information. Precompiled Headers ------------------- -`Precompiled headers `__ +`Precompiled headers `_ are a general approach employed by many compilers to reduce compilation time. The underlying motivation of the approach is that it is common for the same (and often large) header files to be included by multiple @@ -1482,7 +1482,7 @@ usual build cycle when using sample profilers for optimization: 3. Convert the collected profile data to LLVM's sample profile format. This is currently supported via the AutoFDO converter ``create_llvm_prof``. - It is available at http://github.com/google/autofdo. Once built and + It is available at https://github.com/google/autofdo. Once built and installed, you can convert the ``perf.data`` file to LLVM using the command: @@ -1521,12 +1521,12 @@ read by the backend. LLVM supports three different sample profile formats: 2. Binary encoding. This uses a more efficient encoding that yields smaller profile files. This is the format generated by the ``create_llvm_prof`` tool - in http://github.com/google/autofdo. + in https://github.com/google/autofdo. 3. GCC encoding. This is based on the gcov format, which is accepted by GCC. It is only interesting in environments where GCC and Clang co-exist. This encoding is only generated by the ``create_gcov`` tool in - http://github.com/google/autofdo. It can be read by LLVM and + https://github.com/google/autofdo. It can be read by LLVM and ``llvm-profdata``, but it cannot be generated by either. If you are using Linux Perf to generate sampling profiles, you can use the @@ -1831,9 +1831,9 @@ The profile remapping file is a text file containing lines of the form where ``fragmentkind`` is one of ``name``, ``type``, or ``encoding``, indicating whether the following mangled name fragments are -<`name `_>s, -<`type `_>s, or -<`encoding `_>s, +<`name `_>s, +<`type `_>s, or +<`encoding `_>s, respectively. Blank lines and lines starting with ``#`` are ignored. @@ -2829,7 +2829,7 @@ 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. `vcvarsall.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 not part of the installer, but may be installed @@ -2928,20 +2928,23 @@ Execute ``clang-cl /?`` to see a list of supported options: /GA Assume thread-local variables are defined in the executable /Gd Set __cdecl as a default calling convention /GF- Disable string pooling + /GF Enable string pooling (default) /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 - /GS Enable buffer security check - /Gs Set stack probe size - /guard: Enable Control Flow Guard with /guard:cf + /GS Enable buffer security check (default) + /Gs Use stack probes (default) + /Gs Set stack probe size (default 4096) + /guard: Enable Control Flow Guard with /guard:cf, + or only the table with /guard:cf,nochecks /Gv Set __vectorcall as a default calling convention /Gw- Don't put each data item in its own section /Gw Put each data item in its own section /GX- Disable exception handling /GX Enable exception handling - /Gy- Don't put each function in its own section + /Gy- Don't put each function in its own section (default) /Gy Put each function in its own section /Gz Set __stdcall as a default calling convention /help Display available options @@ -2955,16 +2958,28 @@ Execute ``clang-cl /?`` to see a list of supported options: /MD Use DLL run-time /MTd Use static debug run-time /MT Use static run-time + /O0 Disable optimization + /O1 Optimize for size (same as /Og /Os /Oy /Ob2 /GF /Gy) + /O2 Optimize for speed (same as /Og /Oi /Ot /Oy /Ob2 /GF /Gy) + /Ob0 Disable function inlining + /Ob1 Only inline functions which are (explicitly or implicitly) marked inline + /Ob2 Inline functions as deemed beneficial by the compiler /Od Disable optimization + /Og No effect /Oi- Disable use of builtin functions /Oi Enable use of builtin functions /Os Optimize for size /Ot Optimize for speed - /O Optimization level + /Ox Deprecated (same as /Og /Oi /Ot /Oy /Ob2); use /O2 instead + /Oy- Disable frame pointer omission (x86 only, default) + /Oy Enable frame pointer omission (x86 only) + /O Set multiple /O flags at once; e.g. '/O2y-' for '/O2 /Oy-' /o Set output file or directory (ends in / or \) /P Preprocess to file /Qvec- Disable the loop vectorization passes /Qvec Enable the loop vectorization passes + /showFilenames- Don't print the name of each compiled file (default) + /showFilenames Print the name of each compiled file /showIncludes Print info about included files to stderr /source-charset: Source encoding, supports only UTF-8 /std: Language standard to compile for @@ -3049,6 +3064,7 @@ Execute ``clang-cl /?`` to see a list of supported options: -fno-complete-member-pointers Do not require member pointer base types to be complete if they would be significant under the Microsoft ABI -fno-coverage-mapping Disable code coverage analysis + -fno-crash-diagnostics Disable auto-generation of preprocessed source files and a script for reproduction during a clang crash -fno-debug-macro Do not emit macro debug information -fno-delayed-template-parsing Disable delayed template parsing @@ -3056,6 +3072,8 @@ Execute ``clang-cl /?`` to see a list of supported options: Disable poisoning array cookies when using custom operator new[] in AddressSanitizer -fno-sanitize-address-use-after-scope Disable use-after-scope detection in AddressSanitizer + -fno-sanitize-address-use-odr-indicator + Disable ODR indicator globals -fno-sanitize-blacklist Don't use blacklist file for sanitizers -fno-sanitize-cfi-cross-dso Disable control flow integrity (CFI) checks for cross-DSO calls. @@ -3077,6 +3095,11 @@ Execute ``clang-cl /?`` to see a list of supported options: -fno-sanitize-trap= Disable trapping for specified sanitizers -fno-standalone-debug Limit debug information produced to reduce size of debug binary + -fobjc-runtime= Specify the target Objective-C runtime kind and version + -fprofile-exclude-files= + Instrument only functions from files where names don't match all the regexes separated by a semi-colon + -fprofile-filter-files= + Instrument only functions from files where names match any regex separated by a semi-colon -fprofile-instr-generate= Generate instrumented code to collect execution counts into (overridden by LLVM_PROFILE_FILE env var) @@ -3085,16 +3108,18 @@ Execute ``clang-cl /?`` to see a list of supported options: (overridden by '=' form of option or LLVM_PROFILE_FILE env var) -fprofile-instr-use= Use instrumentation data for profile-guided optimization + -fprofile-remapping-file= + Use the remappings described in to match the profile data against names in the program -fsanitize-address-field-padding= Level of field padding for AddressSanitizer -fsanitize-address-globals-dead-stripping Enable linker dead stripping of globals in AddressSanitizer - -fsanitize-address-use-odr-indicator - Enable ODR indicator globals to avoid false ODR violation reports in partially sanitized programs at the cost of an increase in binary size -fsanitize-address-poison-custom-array-cookie Enable poisoning array cookies when using custom operator new[] in AddressSanitizer -fsanitize-address-use-after-scope Enable use-after-scope detection in AddressSanitizer + -fsanitize-address-use-odr-indicator + Enable ODR indicator globals to avoid false ODR violation reports in partially sanitized programs at the cost of an increase in binary size -fsanitize-blacklist= Path to blacklist file for sanitizers -fsanitize-cfi-cross-dso @@ -3103,6 +3128,8 @@ Execute ``clang-cl /?`` to see a list of supported options: Generalize pointers in CFI indirect call type signature checks -fsanitize-coverage= Specify the type of coverage instrumentation for Sanitizers + -fsanitize-hwaddress-abi= + Select the HWAddressSanitizer ABI to target (interceptor or platform, default interceptor) -fsanitize-memory-track-origins= Enable origins tracking in MemorySanitizer -fsanitize-memory-track-origins @@ -3123,9 +3150,12 @@ Execute ``clang-cl /?`` to see a list of supported options: Strip (or keep only, if negative) a given number of path components when emitting check metadata. -fsanitize= Turn on runtime checks for various forms of undefined or suspicious behavior. See user manual for available checks + -fsplit-lto-unit Enables splitting of the LTO unit. -fstandalone-debug Emit full debug info for all types used by the program -fwhole-program-vtables Enables whole-program vtable optimization. Requires -flto + -gcodeview-ghash Emit type record hashes in a .debug$H section -gcodeview Generate CodeView debug information + -gline-directives-only Emit debug line info directives only -gline-tables-only Emit debug line number tables only -miamcu Use Intel MCU ABI -mllvm Additional arguments to forward to LLVM's option processing diff --git a/docs/analyzer/checkers.rst b/docs/analyzer/checkers.rst new file mode 100644 index 0000000000000000000000000000000000000000..16bc36a2c0702625e0e9dbb21d8770119ec2a588 --- /dev/null +++ b/docs/analyzer/checkers.rst @@ -0,0 +1,2014 @@ +================== +Available Checkers +================== + +The analyzer performs checks that are categorized into families or "checkers". + +The default set of checkers covers a variety of checks targeted at finding security and API usage bugs, +dead code, and other logic errors. See the :ref:`default-checkers` checkers list below. + +In addition to these, the analyzer contains a number of :ref:`alpha-checkers` (aka *alpha* checkers). +These checkers are under development and are switched off by default. They may crash or emit a higher number of false positives. + +The :ref:`debug-checkers` package contains checkers for analyzer developers for debugging purposes. + +.. contents:: Table of Contents + :depth: 4 + + +.. _default-checkers: + +Default Checkers +---------------- + +.. _core-checkers: + +core +^^^^ +Models core language features and contains general-purpose checkers such as division by zero, +null pointer dereference, usage of uninitialized values, etc. +*These checkers must be always switched on as other checker rely on them.* + +core.CallAndMessage (C, C++, ObjC) +"""""""""""""""""""""""""""""""""" + Check for logical errors for function calls and Objective-C message expressions (e.g., uninitialized arguments, null function pointers). + +.. literalinclude:: checkers/callandmessage_example.c + :language: objc + +core.DivideZero (C, C++, ObjC) +"""""""""""""""""""""""""""""" + Check for division by zero. + +.. literalinclude:: checkers/dividezero_example.c + :language: c + +core.NonNullParamChecker (C, C++, ObjC) +""""""""""""""""""""""""""""""""""""""" +Check for null pointers passed as arguments to a function whose arguments are references or marked with the 'nonnull' attribute. + +.. code-block:: cpp + + int f(int *p) __attribute__((nonnull)); + + void test(int *p) { + if (!p) + f(p); // warn + } + +core.NullDereference (C, C++, ObjC) +""""""""""""""""""""""""""""""""""" +Check for dereferences of null pointers. + +.. code-block:: objc + + // C + void test(int *p) { + if (p) + return; + + int x = p[0]; // warn + } + + // C + void test(int *p) { + if (!p) + *p = 0; // warn + } + + // C++ + class C { + public: + int x; + }; + + void test() { + C *pc = 0; + int k = pc->x; // warn + } + + // Objective-C + @interface MyClass { + @public + int x; + } + @end + + void test() { + MyClass *obj = 0; + obj->x = 1; // warn + } + +core.StackAddressEscape (C) +""""""""""""""""""""""""""" +Check that addresses to stack memory do not escape the function. + +.. code-block:: c + + char const *p; + + void test() { + char const str[] = "string"; + p = str; // warn + } + + void* test() { + return __builtin_alloca(12); // warn + } + + void test() { + static int *x; + int y; + x = &y; // warn + } + + +core.UndefinedBinaryOperatorResult (C) +"""""""""""""""""""""""""""""""""""""" +Check for undefined results of binary operators. + +.. code-block:: c + + void test() { + int x; + int y = x + 1; // warn: left operand is garbage + } + +core.VLASize (C) +"""""""""""""""" +Check for declarations of Variable Length Arrays of undefined or zero size. + + Check for declarations of VLA of undefined or zero size. + +.. code-block:: c + + void test() { + int x; + int vla1[x]; // warn: garbage as size + } + + void test() { + int x = 0; + int vla2[x]; // warn: zero size + } + +core.uninitialized.ArraySubscript (C) +""""""""""""""""""""""""""""""""""""" +Check for uninitialized values used as array subscripts. + +.. code-block:: c + + void test() { + int i, a[10]; + int x = a[i]; // warn: array subscript is undefined + } + +core.uninitialized.Assign (C) +""""""""""""""""""""""""""""" +Check for assigning uninitialized values. + +.. code-block:: c + + void test() { + int x; + x |= 1; // warn: left expression is uninitialized + } + +core.uninitialized.Branch (C) +""""""""""""""""""""""""""""" +Check for uninitialized values used as branch conditions. + +.. code-block:: c + + void test() { + int x; + if (x) // warn + return; + } + +core.uninitialized.CapturedBlockVariable (C) +"""""""""""""""""""""""""""""""""""""""""""" +Check for blocks that capture uninitialized values. + +.. code-block:: c + + void test() { + int x; + ^{ int y = x; }(); // warn + } + +core.uninitialized.UndefReturn (C) +"""""""""""""""""""""""""""""""""" +Check for uninitialized values being returned to the caller. + +.. code-block:: c + + int test() { + int x; + return x; // warn + } + +.. _cplusplus-checkers: + + +cpluslus +^^^^^^^^ + +C++ Checkers. + +cplusplus.InnerPointer +"""""""""""""""""""""" +Check for inner pointers of C++ containers used after re/deallocation. + +cplusplus.NewDelete (C++) +""""""""""""""""""""""""" +Check for double-free and use-after-free problems. Traces memory managed by new/delete. + +.. literalinclude:: checkers/newdelete_example.cpp + :language: cpp + +cplusplus.NewDeleteLeaks (C++) +"""""""""""""""""""""""""""""" +Check for memory leaks. Traces memory managed by new/delete. + +.. code-block:: cpp + + void test() { + int *p = new int; + } // warn + + +cplusplus.SelfAssignment (C++) +"""""""""""""""""""""""""""""" +Checks C++ copy and move assignment operators for self assignment. + +.. _deadcode-checkers: + +deadcode +^^^^^^^^ + +Dead Code Checkers. + +deadcode.DeadStores (C) +""""""""""""""""""""""" +Check for values stored to variables that are never read afterwards. + +.. code-block:: c + + void test() { + int x; + x = 1; // warn + } + +.. _nullability-checkers: + +nullability +^^^^^^^^^^^ + +Objective C checkers that warn for null pointer passing and dereferencing errors. + +nullability.NullPassedToNonnull (ObjC) +"""""""""""""""""""""""""""""""""""""" +Warns when a null pointer is passed to a pointer which has a _Nonnull type. + +.. code-block:: objc + + if (name != nil) + return; + // Warning: nil passed to a callee that requires a non-null 1st parameter + NSString *greeting = [@"Hello " stringByAppendingString:name]; + +nullability.NullReturnedFromNonnull (ObjC) +"""""""""""""""""""""""""""""""""""""""""" +Warns when a null pointer is returned from a function that has _Nonnull return type. + +.. code-block:: objc + + - (nonnull id)firstChild { + id result = nil; + if ([_children count] > 0) + result = _children[0]; + + // Warning: nil returned from a method that is expected + // to return a non-null value + return result; + } + +nullability.NullableDereferenced (ObjC) +""""""""""""""""""""""""""""""""""""""" +Warns when a nullable pointer is dereferenced. + +.. code-block:: objc + + struct LinkedList { + int data; + struct LinkedList *next; + }; + + struct LinkedList * _Nullable getNext(struct LinkedList *l); + + void updateNextData(struct LinkedList *list, int newData) { + struct LinkedList *next = getNext(list); + // Warning: Nullable pointer is dereferenced + next->data = 7; + } + +nullability.NullablePassedToNonnull (ObjC) +"""""""""""""""""""""""""""""""""""""""""" +Warns when a nullable pointer is passed to a pointer which has a _Nonnull type. + +.. code-block:: objc + + typedef struct Dummy { int val; } Dummy; + Dummy *_Nullable returnsNullable(); + void takesNonnull(Dummy *_Nonnull); + + void test() { + Dummy *p = returnsNullable(); + takesNonnull(p); // warn + } + +nullability.NullableReturnedFromNonnull (ObjC) +"""""""""""""""""""""""""""""""""""""""""""""" +Warns when a nullable pointer is returned from a function that has _Nonnull return type. + +.. _optin-checkers: + +optin +^^^^^ + +Checkers for portability, performance or coding style specific rules. + +optin.cplusplus.VirtualCall (C++) +""""""""""""""""""""""""""""""""" +Check virtual function calls during construction or destruction. + +.. code-block:: cpp + + class A { + public: + A() { + f(); // warn + } + virtual void f(); + }; + + class A { + public: + ~A() { + this->f(); // warn + } + virtual void f(); + }; + +optin.mpi.MPI-Checker (C) +""""""""""""""""""""""""" +Checks MPI code. + +.. code-block:: c + + void test() { + double buf = 0; + MPI_Request sendReq1; + MPI_Ireduce(MPI_IN_PLACE, &buf, 1, MPI_DOUBLE, MPI_SUM, + 0, MPI_COMM_WORLD, &sendReq1); + } // warn: request 'sendReq1' has no matching wait. + + void test() { + double buf = 0; + MPI_Request sendReq; + MPI_Isend(&buf, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, &sendReq); + MPI_Irecv(&buf, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, &sendReq); // warn + MPI_Isend(&buf, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, &sendReq); // warn + MPI_Wait(&sendReq, MPI_STATUS_IGNORE); + } + + void missingNonBlocking() { + int rank = 0; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Request sendReq1[10][10][10]; + MPI_Wait(&sendReq1[1][7][9], MPI_STATUS_IGNORE); // warn + } + +optin.osx.cocoa.localizability.EmptyLocalizationContextChecker (ObjC) +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +Check that NSLocalizedString macros include a comment for context. + +.. code-block:: objc + + - (void)test { + NSString *string = NSLocalizedString(@"LocalizedString", nil); // warn + NSString *string2 = NSLocalizedString(@"LocalizedString", @" "); // warn + NSString *string3 = NSLocalizedStringWithDefaultValue( + @"LocalizedString", nil, [[NSBundle alloc] init], nil,@""); // warn + } + +optin.osx.cocoa.localizability.NonLocalizedStringChecker (ObjC) +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +Warns about uses of non-localized NSStrings passed to UI methods expecting localized NSStrings. + +.. code-block:: objc + + NSString *alarmText = + NSLocalizedString(@"Enabled", @"Indicates alarm is turned on"); + if (!isEnabled) { + alarmText = @"Disabled"; + } + UILabel *alarmStateLabel = [[UILabel alloc] init]; + + // Warning: User-facing text should use localized string macro + [alarmStateLabel setText:alarmText]; + +optin.performance.GCDAntipattern +"""""""""""""""""""""""""""""""" +Check for performance anti-patterns when using Grand Central Dispatch. + +optin.performance.Padding +""""""""""""""""""""""""" +Check for excessively padded structs. + +optin.portability.UnixAPI +""""""""""""""""""""""""" +Finds implementation-defined behavior in UNIX/Posix functions. + + +.. _security-checkers: + +security +^^^^^^^^ + +Security related checkers. + +security.FloatLoopCounter (C) +""""""""""""""""""""""""""""" +Warn on using a floating point value as a loop counter (CERT: FLP30-C, FLP30-CPP). + +.. code-block:: c + + void test() { + for (float x = 0.1f; x <= 1.0f; x += 0.1f) {} // warn + } + +security.insecureAPI.UncheckedReturn (C) +"""""""""""""""""""""""""""""""""""""""" +Warn on uses of functions whose return values must be always checked. + +.. code-block:: c + + void test() { + setuid(1); // warn + } + +security.insecureAPI.bcmp (C) +""""""""""""""""""""""""""""" +Warn on uses of the 'bcmp' function. + +.. code-block:: c + + void test() { + bcmp(ptr0, ptr1, n); // warn + } + +security.insecureAPI.bcopy (C) +"""""""""""""""""""""""""""""" +Warn on uses of the 'bcopy' function. + +.. code-block:: c + + void test() { + bcopy(src, dst, n); // warn + } + +security.insecureAPI.bzero (C) +"""""""""""""""""""""""""""""" +Warn on uses of the 'bzero' function. + +.. code-block:: c + + void test() { + bzero(ptr, n); // warn + } + +security.insecureAPI.getpw (C) +"""""""""""""""""""""""""""""" +Warn on uses of the 'getpw' function. + +.. code-block:: c + + void test() { + char buff[1024]; + getpw(2, buff); // warn + } + +security.insecureAPI.gets (C) +""""""""""""""""""""""""""""" +Warn on uses of the 'gets' function. + +.. code-block:: c + + void test() { + char buff[1024]; + gets(buff); // warn + } + +security.insecureAPI.mkstemp (C) +"""""""""""""""""""""""""""""""" +Warn when 'mkstemp' is passed fewer than 6 X's in the format string. + +.. code-block:: c + + void test() { + mkstemp("XX"); // warn + } + +security.insecureAPI.mktemp (C) +""""""""""""""""""""""""""""""" +Warn on uses of the ``mktemp`` function. + +.. code-block:: c + + void test() { + char *x = mktemp("/tmp/zxcv"); // warn: insecure, use mkstemp + } + +security.insecureAPI.rand (C) +""""""""""""""""""""""""""""" +Warn on uses of inferior random number generating functions (only if arc4random function is available): +``drand48, erand48, jrand48, lcong48, lrand48, mrand48, nrand48, random, rand_r``. + +.. code-block:: c + + void test() { + random(); // warn + } + +security.insecureAPI.strcpy (C) +""""""""""""""""""""""""""""""" +Warn on uses of the ``strcpy`` and ``strcat`` functions. + +.. code-block:: c + + void test() { + char x[4]; + char *y = "abcd"; + + strcpy(x, y); // warn + } + + +security.insecureAPI.vfork (C) +"""""""""""""""""""""""""""""" + Warn on uses of the 'vfork' function. + +.. code-block:: c + + void test() { + vfork(); // warn + } + +security.insecureAPI.DeprecatedOrUnsafeBufferHandling (C) +""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + Warn on occurrences of unsafe or deprecated buffer handling functions, which now have a secure variant: ``sprintf, vsprintf, scanf, wscanf, fscanf, fwscanf, vscanf, vwscanf, vfscanf, vfwscanf, sscanf, swscanf, vsscanf, vswscanf, swprintf, snprintf, vswprintf, vsnprintf, memcpy, memmove, strncpy, strncat, memset`` + +.. code-block:: c + + void test() { + char buf [5]; + strncpy(buf, "a", 1); // warn + } + +.. _unix-checkers: + +unix +^^^^ +POSIX/Unix checkers. + +unix.API (C) +"""""""""""" +Check calls to various UNIX/Posix functions: ``open, pthread_once, calloc, malloc, realloc, alloca``. + +.. literalinclude:: checkers/unix_api_example.c + :language: c + +unix.Malloc (C) +""""""""""""""" +Check for memory leaks, double free, and use-after-free problems. Traces memory managed by malloc()/free(). + +.. literalinclude:: checkers/unix_malloc_example.c + :language: c + +unix.MallocSizeof (C) +""""""""""""""""""""" +Check for dubious ``malloc`` arguments involving ``sizeof``. + +.. code-block:: c + + void test() { + long *p = malloc(sizeof(short)); + // warn: result is converted to 'long *', which is + // incompatible with operand type 'short' + free(p); + } + +unix.MismatchedDeallocator (C, C++) +""""""""""""""""""""""""""""""""""" +Check for mismatched deallocators. + +.. literalinclude:: checkers/mismatched_deallocator_example.cpp + :language: c + +unix.Vfork (C) +"""""""""""""" +Check for proper usage of ``vfork``. + +.. code-block:: c + + int test(int x) { + pid_t pid = vfork(); // warn + if (pid != 0) + return 0; + + switch (x) { + case 0: + pid = 1; + execl("", "", 0); + _exit(1); + break; + case 1: + x = 0; // warn: this assignment is prohibited + break; + case 2: + foo(); // warn: this function call is prohibited + break; + default: + return 0; // warn: return is prohibited + } + + while(1); + } + +unix.cstring.BadSizeArg (C) +""""""""""""""""""""""""""" +Check the size argument passed into C string functions for common erroneous patterns. Use ``-Wno-strncat-size`` compiler option to mute other ``strncat``-related compiler warnings. + +.. code-block:: c + + void test() { + char dest[3]; + strncat(dest, """""""""""""""""""""""""*", sizeof(dest)); + // warn: potential buffer overflow + } + +unix.cstrisng.NullArg (C) +""""""""""""""""""""""""" +Check for null pointers being passed as arguments to C string functions: +``strlen, strnlen, strcpy, strncpy, strcat, strncat, strcmp, strncmp, strcasecmp, strncasecmp``. + +.. code-block:: c + + int test() { + return strlen(0); // warn + } + +.. _osx-checkers: + +osx +^^^ +OS X checkers. + +osx.API (C) +""""""""""" +Check for proper uses of various Apple APIs. + +.. code-block:: objc + + void test() { + dispatch_once_t pred = 0; + dispatch_once(&pred, ^(){}); // warn: dispatch_once uses local + } + +osx.NumberObjectConversion (C, C++, ObjC) +""""""""""""""""""""""""""""""""""""""""" +Check for erroneous conversions of objects representing numbers into numbers. + +.. code-block:: objc + + NSNumber *photoCount = [albumDescriptor objectForKey:@"PhotoCount"]; + // Warning: Comparing a pointer value of type 'NSNumber *' + // to a scalar integer value + if (photoCount > 0) { + [self displayPhotos]; + } + +osx.ObjCProperty (ObjC) +""""""""""""""""""""""" +Check for proper uses of Objective-C properties. + +.. code-block:: objc + + NSNumber *photoCount = [albumDescriptor objectForKey:@"PhotoCount"]; + // Warning: Comparing a pointer value of type 'NSNumber *' + // to a scalar integer value + if (photoCount > 0) { + [self displayPhotos]; + } + + +osx.SecKeychainAPI (C) +"""""""""""""""""""""" +Check for proper uses of Secure Keychain APIs. + +.. literalinclude:: checkers/seckeychainapi_example.m + :language: objc + +osx.cocoa.AtSync (ObjC) +""""""""""""""""""""""" +Check for nil pointers used as mutexes for @synchronized. + +.. code-block:: objc + + void test(id x) { + if (!x) + @synchronized(x) {} // warn: nil value used as mutex + } + + void test() { + id y; + @synchronized(y) {} // warn: uninitialized value used as mutex + } + +osx.cocoa.AutoreleaseWrite +"""""""""""""""""""""""""" +Warn about potentially crashing writes to autoreleasing objects from different autoreleasing pools in Objective-C. + +osx.cocoa.ClassRelease (ObjC) +""""""""""""""""""""""""""""" +Check for sending 'retain', 'release', or 'autorelease' directly to a Class. + +.. code-block:: objc + + @interface MyClass : NSObject + @end + + void test(void) { + [MyClass release]; // warn + } + +osx.cocoa.Dealloc (ObjC) +"""""""""""""""""""""""" +Warn about Objective-C classes that lack a correct implementation of -dealloc + +.. literalinclude:: checkers/dealloc_example.m + :language: objc + +osx.cocoa.IncompatibleMethodTypes (ObjC) +"""""""""""""""""""""""""""""""""""""""" +Warn about Objective-C method signatures with type incompatibilities. + +.. code-block:: objc + + @interface MyClass1 : NSObject + - (int)foo; + @end + + @implementation MyClass1 + - (int)foo { return 1; } + @end + + @interface MyClass2 : MyClass1 + - (float)foo; + @end + + @implementation MyClass2 + - (float)foo { return 1.0; } // warn + @end + +osx.cocoa.Loops +""""""""""""""" +Improved modeling of loops using Cocoa collection types. + +osx.cocoa.MissingSuperCall (ObjC) +""""""""""""""""""""""""""""""""" +Warn about Objective-C methods that lack a necessary call to super. + +.. code-block:: objc + + @interface Test : UIViewController + @end + @implementation test + - (void)viewDidLoad {} // warn + @end + + +osx.cocoa.NSAutoreleasePool (ObjC) +"""""""""""""""""""""""""""""""""" +Warn for suboptimal uses of NSAutoreleasePool in Objective-C GC mode. + +.. code-block:: objc + + void test() { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + [pool release]; // warn + } + +osx.cocoa.NSError (ObjC) +"""""""""""""""""""""""" +Check usage of NSError parameters. + +.. code-block:: objc + + @interface A : NSObject + - (void)foo:(NSError """""""""""""""""""""""")error; + @end + + @implementation A + - (void)foo:(NSError """""""""""""""""""""""")error { + // warn: method accepting NSError"""""""""""""""""""""""" should have a non-void + // return value + } + @end + + @interface A : NSObject + - (BOOL)foo:(NSError """""""""""""""""""""""")error; + @end + + @implementation A + - (BOOL)foo:(NSError """""""""""""""""""""""")error { + *error = 0; // warn: potential null dereference + return 0; + } + @end + +osx.cocoa.NilArg (ObjC) +""""""""""""""""""""""" +Check for prohibited nil arguments to ObjC method calls. + + - caseInsensitiveCompare: + - compare: + - compare:options: + - compare:options:range: + - compare:options:range:locale: + - componentsSeparatedByCharactersInSet: + - initWithFormat: + +.. code-block:: objc + + NSComparisonResult test(NSString *s) { + NSString *aString = nil; + return [s caseInsensitiveCompare:aString]; + // warn: argument to 'NSString' method + // 'caseInsensitiveCompare:' cannot be nil + } + + +osx.cocoa.NonNilReturnValue +""""""""""""""""""""""""""" +Models the APIs that are guaranteed to return a non-nil value. + +osx.cocoa.ObjCGenerics (ObjC) +""""""""""""""""""""""""""""" +Check for type errors when using Objective-C generics. + +.. code-block:: objc + + NSMutableArray *names = [NSMutableArray array]; + NSMutableArray *birthDates = names; + + // Warning: Conversion from value of type 'NSDate *' + // to incompatible type 'NSString *' + [birthDates addObject: [NSDate date]]; + +osx.cocoa.RetainCount (ObjC) +"""""""""""""""""""""""""""" +Check for leaks and improper reference count management + +.. code-block:: objc + + void test() { + NSString *s = [[NSString alloc] init]; // warn + } + + CFStringRef test(char *bytes) { + return CFStringCreateWithCStringNoCopy( + 0, bytes, NSNEXTSTEPStringEncoding, 0); // warn + } + + +osx.cocoa.RunLoopAutoreleaseLeak +"""""""""""""""""""""""""""""""" +Check for leaked memory in autorelease pools that will never be drained. + +osx.cocoa.SelfInit (ObjC) +""""""""""""""""""""""""" +Check that 'self' is properly initialized inside an initializer method. + +.. code-block:: objc + + @interface MyObj : NSObject { + id x; + } + - (id)init; + @end + + @implementation MyObj + - (id)init { + [super init]; + x = 0; // warn: instance variable used while 'self' is not + // initialized + return 0; + } + @end + + @interface MyObj : NSObject + - (id)init; + @end + + @implementation MyObj + - (id)init { + [super init]; + return self; // warn: returning uninitialized 'self' + } + @end + +osx.cocoa.SuperDealloc (ObjC) +""""""""""""""""""""""""""""" +Warn about improper use of '[super dealloc]' in Objective-C. + +.. code-block:: objc + + @interface SuperDeallocThenReleaseIvarClass : NSObject { + NSObject *_ivar; + } + @end + + @implementation SuperDeallocThenReleaseIvarClass + - (void)dealloc { + [super dealloc]; + [_ivar release]; // warn + } + @end + +osx.cocoa.UnusedIvars (ObjC) +"""""""""""""""""""""""""""" +Warn about private ivars that are never used. + +.. code-block:: objc + + @interface MyObj : NSObject { + @private + id x; // warn + } + @end + + @implementation MyObj + @end + +osx.cocoa.VariadicMethodTypes (ObjC) +"""""""""""""""""""""""""""""""""""" +Check for passing non-Objective-C types to variadic collection +initialization methods that expect only Objective-C types. + +.. code-block:: objc + + void test() { + [NSSet setWithObjects:@"Foo", "Bar", nil]; + // warn: argument should be an ObjC pointer type, not 'char *' + } + +osx.coreFoundation.CFError (C) +"""""""""""""""""""""""""""""" +Check usage of CFErrorRef* parameters + +.. code-block:: c + + void test(CFErrorRef *error) { + // warn: function accepting CFErrorRef* should have a + // non-void return + } + + int foo(CFErrorRef *error) { + *error = 0; // warn: potential null dereference + return 0; + } + +osx.coreFoundation.CFNumber (C) +""""""""""""""""""""""""""""""" +Check for proper uses of CFNumber APIs. + +.. code-block:: c + + CFNumberRef test(unsigned char x) { + return CFNumberCreate(0, kCFNumberSInt16Type, &x); + // warn: 8 bit integer is used to initialize a 16 bit integer + } + +osx.coreFoundation.CFRetainRelease (C) +"""""""""""""""""""""""""""""""""""""" +Check for null arguments to CFRetain/CFRelease/CFMakeCollectable. + +.. code-block:: c + + void test(CFTypeRef p) { + if (!p) + CFRetain(p); // warn + } + + void test(int x, CFTypeRef p) { + if (p) + return; + + CFRelease(p); // warn + } + +osx.coreFoundation.containers.OutOfBounds (C) +""""""""""""""""""""""""""""""""""""""""""""" +Checks for index out-of-bounds when using 'CFArray' API. + +.. code-block:: c + + void test() { + CFArrayRef A = CFArrayCreate(0, 0, 0, &kCFTypeArrayCallBacks); + CFArrayGetValueAtIndex(A, 0); // warn + } + +osx.coreFoundation.containers.PointerSizedValues (C) +"""""""""""""""""""""""""""""""""""""""""""""""""""" +Warns if 'CFArray', 'CFDictionary', 'CFSet' are created with non-pointer-size values. + +.. code-block:: c + + void test() { + int x[] = { 1 }; + CFArrayRef A = CFArrayCreate(0, (const void """""""""""""""""""""""")x, 1, + &kCFTypeArrayCallBacks); // warn + } + + +.. _alpha-checkers: + +Experimental Checkers +--------------------- + +*These are checkers with known issues or limitations that keep them from being on by default. They are likely to have false positives. Bug reports and especially patches are welcome.* + +alpha.clone +^^^^^^^^^^^ + +alpha.clone.CloneChecker (C, C++, ObjC) +""""""""""""""""""""""""""""""""""""""" +Reports similar pieces of code. + +.. code-block:: c + + void log(); + + int max(int a, int b) { // warn + log(); + if (a > b) + return a; + return b; + } + + int maxClone(int x, int y) { // similar code here + log(); + if (x > y) + return x; + return y; + } + +alpha.core.BoolAssignment (ObjC) +"""""""""""""""""""""""""""""""" +Warn about assigning non-{0,1} values to boolean variables. + +.. code-block:: objc + + void test() { + BOOL b = -1; // warn + } + +alpha.core +^^^^^^^^^^ + +alpha.core.CallAndMessageUnInitRefArg (C,C++, ObjC) +""""""""""""""""""""""""""""""""""""""""""""""""""" +Check for logical errors for function calls and Objective-C +message expressions (e.g., uninitialized arguments, null function pointers, and pointer to undefined variables). + +.. code-block:: c + + void test(void) { + int t; + int &p = t; + int &s = p; + int &q = s; + foo(q); // warn + } + + void test(void) { + int x; + foo(&x); // warn + } + +alpha.core.CastSize (C) +""""""""""""""""""""""" +Check when casting a malloc'ed type ``T``, whether the size is a multiple of the size of ``T``. + +.. code-block:: c + + void test() { + int *x = (int *) malloc(11); // warn + } + +alpha.core.CastToStruct (C, C++) +"""""""""""""""""""""""""""""""" +Check for cast from non-struct pointer to struct pointer. + +.. code-block:: cpp + + // C + struct s {}; + + void test(int *p) { + struct s *ps = (struct s *) p; // warn + } + + // C++ + class c {}; + + void test(int *p) { + c *pc = (c *) p; // warn + } + +alpha.core.Conversion (C, C++, ObjC) +"""""""""""""""""""""""""""""""""""" +Loss of sign/precision in implicit conversions. + +.. code-block:: c + + void test(unsigned U, signed S) { + if (S > 10) { + if (U < S) { + } + } + if (S < -10) { + if (U < S) { // warn (loss of sign) + } + } + } + + void test() { + long long A = 1LL << 60; + short X = A; // warn (loss of precision) + } + +alpha.core.DynamicTypeChecker (ObjC) +"""""""""""""""""""""""""""""""""""" +Check for cases where the dynamic and the static type of an object are unrelated. + + +.. code-block:: objc + + id date = [NSDate date]; + + // Warning: Object has a dynamic type 'NSDate *' which is + // incompatible with static type 'NSNumber *'" + NSNumber *number = date; + [number doubleValue]; + +alpha.core.FixedAddr (C) +"""""""""""""""""""""""" +Check for assignment of a fixed address to a pointer. + +.. code-block:: c + + void test() { + int *p; + p = (int *) 0x10000; // warn + } + +alpha.core.IdenticalExpr (C, C++) +""""""""""""""""""""""""""""""""" +Warn about unintended use of identical expressions in operators. + +.. code-block:: cpp + + // C + void test() { + int a = 5; + int b = a | 4 | a; // warn: identical expr on both sides + } + + // C++ + bool f(void); + + void test(bool b) { + int i = 10; + if (f()) { // warn: true and false branches are identical + do { + i--; + } while (f()); + } else { + do { + i--; + } while (f()); + } + } + +alpha.core.PointerArithm (C) +"""""""""""""""""""""""""""" +Check for pointer arithmetic on locations other than array elements. + +.. code-block:: c + + void test() { + int x; + int *p; + p = &x + 1; // warn + } + +alpha.core.PointerSub (C) +""""""""""""""""""""""""" +Check for pointer subtractions on two pointers pointing to different memory chunks. + +.. code-block:: c + + void test() { + int x, y; + int d = &y - &x; // warn + } + +alpha.core.SizeofPtr (C) +"""""""""""""""""""""""" +Warn about unintended use of ``sizeof()`` on pointer expressions. + +.. code-block:: c + + struct s {}; + + int test(struct s *p) { + return sizeof(p); + // warn: sizeof(ptr) can produce an unexpected result + } + +alpha.core.StackAddressAsyncEscape (C) +"""""""""""""""""""""""""""""""""""""" +Check that addresses to stack memory do not escape the function that involves dispatch_after or dispatch_async. +This checker is a part of ``core.StackAddressEscape``, but is temporarily disabled until some false positives are fixed. + +.. code-block:: c + + dispatch_block_t test_block_inside_block_async_leak() { + int x = 123; + void (^inner)(void) = ^void(void) { + int y = x; + ++y; + }; + void (^outer)(void) = ^void(void) { + int z = x; + ++z; + inner(); + }; + return outer; // warn: address of stack-allocated block is captured by a + // returned block + } + +alpha.core.TestAfterDivZero (C) +""""""""""""""""""""""""""""""" +Check for division by variable that is later compared against 0. +Either the comparison is useless or there is division by zero. + +.. code-block:: c + + void test(int x) { + var = 77 / x; + if (x == 0) { } // warn + } + +alpha.cplusplus +^^^^^^^^^^^^^^^ + +alpha.cplusplus.DeleteWithNonVirtualDtor (C++) +"""""""""""""""""""""""""""""""""""""""""""""" +Reports destructions of polymorphic objects with a non-virtual destructor in their base class. + +.. code-block:: cpp + + NonVirtual *create() { + NonVirtual *x = new NVDerived(); // note: conversion from derived to base + // happened here + return x; + } + + void sink(NonVirtual *x) { + delete x; // warn: destruction of a polymorphic object with no virtual + // destructor + } + +alpha.cplusplus.EnumCastOutOfRange (C++) +"""""""""""""""""""""""""""""""""""""""" +Check for integer to enumeration casts that could result in undefined values. + +.. code-block:: cpp + + enum TestEnum { + A = 0 + }; + + void foo() { + TestEnum t = static_cast(-1); + // warn: the value provided to the cast expression is not in + the valid range of values for the enum + +alpha.cplusplus.InvalidatedIterator (C++) +""""""""""""""""""""""""""""""""""""""""" +Check for use of invalidated iterators. + +.. code-block:: cpp + + void bad_copy_assign_operator_list1(std::list &L1, + const std::list &L2) { + auto i0 = L1.cbegin(); + L1 = L2; + *i0; // warn: invalidated iterator accessed + } + + +alpha.cplusplus.IteratorRange (C++) +""""""""""""""""""""""""""""""""""" +Check for iterators used outside their valid ranges. + +.. code-block:: cpp + + void simple_bad_end(const std::vector &v) { + auto i = v.end(); + *i; // warn: iterator accessed outside of its range + } + +alpha.cplusplus.MismatchedIterator (C++) +"""""""""""""""""""""""""""""""""""""""" +Check for use of iterators of different containers where iterators of the same container are expected. + +.. code-block:: cpp + + void bad_insert3(std::vector &v1, std::vector &v2) { + v2.insert(v1.cbegin(), v2.cbegin(), v2.cend()); // warn: container accessed + // using foreign + // iterator argument + v1.insert(v1.cbegin(), v1.cbegin(), v2.cend()); // warn: iterators of + // different containers + // used where the same + // container is + // expected + v1.insert(v1.cbegin(), v2.cbegin(), v1.cend()); // warn: iterators of + // different containers + // used where the same + // container is + // expected + } + +alpha.cplusplus.MisusedMovedObject (C++) +"""""""""""""""""""""""""""""""""""""""" +Method calls on a moved-from object and copying a moved-from object will be reported. + + +.. code-block:: cpp + + struct A { + void foo() {} + }; + + void f() { + A a; + A b = std::move(a); // note: 'a' became 'moved-from' here + a.foo(); // warn: method call on a 'moved-from' object 'a' + } + +alpha.cplusplus.UninitializedObject (C++) +""""""""""""""""""""""""""""""""""""""""" + +This checker reports uninitialized fields in objects created after a constructor call. +It doesn't only find direct uninitialized fields, but rather makes a deep inspection +of the object, analyzing all of it's fields subfields. +The checker regards inherited fields as direct fields, so one will +recieve warnings for uninitialized inherited data members as well. + +.. code-block:: cpp + + // With Pedantic and CheckPointeeInitialization set to true + + struct A { + struct B { + int x; // note: uninitialized field 'this->b.x' + // note: uninitialized field 'this->bptr->x' + int y; // note: uninitialized field 'this->b.y' + // note: uninitialized field 'this->bptr->y' + }; + int *iptr; // note: uninitialized pointer 'this->iptr' + B b; + B *bptr; + char *cptr; // note: uninitialized pointee 'this->cptr' + + A (B *bptr, char *cptr) : bptr(bptr), cptr(cptr) {} + }; + + void f() { + A::B b; + char c; + A a(&b, &c); // warning: 6 uninitialized fields + // after the constructor call + } + + // With Pedantic set to false and + // CheckPointeeInitialization set to true + // (every field is uninitialized) + + struct A { + struct B { + int x; + int y; + }; + int *iptr; + B b; + B *bptr; + char *cptr; + + A (B *bptr, char *cptr) : bptr(bptr), cptr(cptr) {} + }; + + void f() { + A::B b; + char c; + A a(&b, &c); // no warning + } + + // With Pedantic set to true and + // CheckPointeeInitialization set to false + // (pointees are regarded as initialized) + + struct A { + struct B { + int x; // note: uninitialized field 'this->b.x' + int y; // note: uninitialized field 'this->b.y' + }; + int *iptr; // note: uninitialized pointer 'this->iptr' + B b; + B *bptr; + char *cptr; + + A (B *bptr, char *cptr) : bptr(bptr), cptr(cptr) {} + }; + + void f() { + A::B b; + char c; + A a(&b, &c); // warning: 3 uninitialized fields + // after the constructor call + } + + +**Options** + +This checker has several options which can be set from command line (e.g. ``-analyzer-config alpha.cplusplus.UninitializedObject:Pedantic=true``): + +* ``Pedantic`` (boolean). If to false, the checker won't emit warnings for objects that don't have at least one initialized field. Defaults to false. + +* ``NotesAsWarnings`` (boolean). If set to true, the checker will emit a warning for each uninitalized field, as opposed to emitting one warning per constructor call, and listing the uninitialized fields that belongs to it in notes. *Defaults to false.*. + +* ``CheckPointeeInitialization`` (boolean). If set to false, the checker will not analyze the pointee of pointer/reference fields, and will only check whether the object itself is initialized. *Defaults to false.*. + +* ``IgnoreRecordsWithField`` (string). If supplied, the checker will not analyze structures that have a field with a name or type name that matches the given pattern. *Defaults to ""*. Can be set with ``-analyzer-config alpha.cplusplus.UninitializedObject:IgnoreRecordsWithField="[Tt]ag|[Kk]ind"``. + + +alpha.deadcode +^^^^^^^^^^^^^^ +alpha.deadcode.UnreachableCode (C, C++) +""""""""""""""""""""""""""""""""""""""" +Check unreachable code. + +.. code-block:: cpp + + // C + int test() { + int x = 1; + while(x); + return x; // warn + } + + // C++ + void test() { + int a = 2; + + while (a > 1) + a--; + + if (a > 1) + a++; // warn + } + + // Objective-C + void test(id x) { + return; + [x retain]; // warn + } + +alpha.llvm +^^^^^^^^^^ + +alpha.llvm.Conventions +"""""""""""""""""""""" + +Check code for LLVM codebase conventions: + +* A StringRef should not be bound to a temporary std::string whose lifetime is shorter than the StringRef's. +* Clang AST nodes should not have fields that can allocate memory. + + +alpha.osx +^^^^^^^^^ + +alpha.osx.cocoa.DirectIvarAssignment (ObjC) +""""""""""""""""""""""""""""""""""""""""""" +Check for direct assignments to instance variables. + + +.. code-block:: objc + + @interface MyClass : NSObject {} + @property (readonly) id A; + - (void) foo; + @end + + @implementation MyClass + - (void) foo { + _A = 0; // warn + } + @end + +alpha.osx.cocoa.DirectIvarAssignmentForAnnotatedFunctions (ObjC) +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +Check for direct assignments to instance variables in +the methods annotated with ``objc_no_direct_instance_variable_assignment``. + +.. code-block:: objc + + @interface MyClass : NSObject {} + @property (readonly) id A; + - (void) fAnnotated __attribute__(( + annotate("objc_no_direct_instance_variable_assignment"))); + - (void) fNotAnnotated; + @end + + @implementation MyClass + - (void) fAnnotated { + _A = 0; // warn + } + - (void) fNotAnnotated { + _A = 0; // no warn + } + @end + + +alpha.osx.cocoa.InstanceVariableInvalidation (ObjC) +""""""""""""""""""""""""""""""""""""""""""""""""""" +Check that the invalidatable instance variables are +invalidated in the methods annotated with objc_instance_variable_invalidator. + +.. code-block:: objc + + @protocol Invalidation + - (void) invalidate + __attribute__((annotate("objc_instance_variable_invalidator"))); + @end + + @interface InvalidationImpObj : NSObject + @end + + @interface SubclassInvalidationImpObj : InvalidationImpObj { + InvalidationImpObj *var; + } + - (void)invalidate; + @end + + @implementation SubclassInvalidationImpObj + - (void) invalidate {} + @end + // warn: var needs to be invalidated or set to nil + +alpha.osx.cocoa.MissingInvalidationMethod (ObjC) +"""""""""""""""""""""""""""""""""""""""""""""""" +Check that the invalidation methods are present in classes that contain invalidatable instance variables. + +.. code-block:: objc + + @protocol Invalidation + - (void)invalidate + __attribute__((annotate("objc_instance_variable_invalidator"))); + @end + + @interface NeedInvalidation : NSObject + @end + + @interface MissingInvalidationMethodDecl : NSObject { + NeedInvalidation *Var; // warn + } + @end + + @implementation MissingInvalidationMethodDecl + @end + +alpha.osx.cocoa.localizability.PluralMisuseChecker (ObjC) +""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +Warns against using one vs. many plural pattern in code when generating localized strings. + +.. code-block:: objc + + NSString *reminderText = + NSLocalizedString(@"None", @"Indicates no reminders"); + if (reminderCount == 1) { + // Warning: Plural cases are not supported across all languages. + // Use a .stringsdict file instead + reminderText = + NSLocalizedString(@"1 Reminder", @"Indicates single reminder"); + } else if (reminderCount >= 2) { + // Warning: Plural cases are not supported across all languages. + // Use a .stringsdict file instead + reminderText = + [NSString stringWithFormat: + NSLocalizedString(@"%@ Reminders", @"Indicates multiple reminders"), + reminderCount]; + } + +alpha.security +^^^^^^^^^^^^^^ +alpha.security.ArrayBound (C) +""""""""""""""""""""""""""""" +Warn about buffer overflows (older checker). + +.. code-block:: c + + void test() { + char *s = ""; + char c = s[1]; // warn + } + + struct seven_words { + int c[7]; + }; + + void test() { + struct seven_words a, *p; + p = &a; + p[0] = a; + p[1] = a; + p[2] = a; // warn + } + + // note: requires unix.Malloc or + // alpha.unix.MallocWithAnnotations checks enabled. + void test() { + int *p = malloc(12); + p[3] = 4; // warn + } + + void test() { + char a[2]; + int *b = (int*)a; + b[1] = 3; // warn + } + +alpha.security.ArrayBoundV2 (C) +""""""""""""""""""""""""""""""" +Warn about buffer overflows (newer checker). + +.. code-block:: c + + void test() { + char *s = ""; + char c = s[1]; // warn + } + + void test() { + int buf[100]; + int *p = buf; + p = p + 99; + p[1] = 1; // warn + } + + // note: compiler has internal check for this. + // Use -Wno-array-bounds to suppress compiler warning. + void test() { + int buf[100][100]; + buf[0][-1] = 1; // warn + } + + // note: requires alpha.security.taint check turned on. + void test() { + char s[] = "abc"; + int x = getchar(); + char c = s[x]; // warn: index is tainted + } + +alpha.security.MallocOverflow (C) +""""""""""""""""""""""""""""""""" +Check for overflows in the arguments to malloc(). + +.. code-block:: c + + void test(int n) { + void *p = malloc(n * sizeof(int)); // warn + } + +alpha.security.MmapWriteExec (C) +"""""""""""""""""""""""""""""""" +Warn on mmap() calls that are both writable and executable. + +.. code-block:: c + + void test(int n) { + void *c = mmap(NULL, 32, PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_PRIVATE | MAP_ANON, -1, 0); + // warn: Both PROT_WRITE and PROT_EXEC flags are set. This can lead to + // exploitable memory regions, which could be overwritten with malicious + // code + } + +alpha.security.ReturnPtrRange (C) +""""""""""""""""""""""""""""""""" +Check for an out-of-bound pointer being returned to callers. + +.. code-block:: c + + static int A[10]; + + int *test() { + int *p = A + 10; + return p; // warn + } + + int test(void) { + int x; + return x; // warn: undefined or garbage returned + } + +alpha.security.taint.TaintPropagation (C, C++) +"""""""""""""""""""""""""""""""""""""""""""""" +Generate taint information used by other checkers. +A data is tainted when it comes from an unreliable source. + +.. code-block:: c + + void test() { + char x = getchar(); // 'x' marked as tainted + system(&x); // warn: untrusted data is passed to a system call + } + + // note: compiler internally checks if the second param to + // sprintf is a string literal or not. + // Use -Wno-format-security to suppress compiler warning. + void test() { + char s[10], buf[10]; + fscanf(stdin, "%s", s); // 's' marked as tainted + + sprintf(buf, s); // warn: untrusted data as a format string + } + + void test() { + size_t ts; + scanf("%zd", &ts); // 'ts' marked as tainted + int *p = (int *)malloc(ts * sizeof(int)); + // warn: untrusted data as buffer size + } + +alpha.unix +^^^^^^^^^^^ + +alpha.unix.BlockInCriticalSection (C) +""""""""""""""""""""""""""""""""""""" +Check for calls to blocking functions inside a critical section. +Applies to: ``lock, unlock, sleep, getc, fgets, read, recv, pthread_mutex_lock,`` +`` pthread_mutex_unlock, mtx_lock, mtx_timedlock, mtx_trylock, mtx_unlock, lock_guard, unique_lock`` + +.. code-block:: c + + void test() { + std::mutex m; + m.lock(); + sleep(3); // warn: a blocking function sleep is called inside a critical + // section + m.unlock(); + } + +alpha.unix.Chroot (C) +""""""""""""""""""""" +Check improper use of chroot. + +.. code-block:: c + + void f(); + + void test() { + chroot("/usr/local"); + f(); // warn: no call of chdir("/") immediately after chroot + } + +alpha.unix.PthreadLock (C) +"""""""""""""""""""""""""" +Simple lock -> unlock checker. +Applies to: ``pthread_mutex_lock, pthread_rwlock_rdlock, pthread_rwlock_wrlock, lck_mtx_lock, lck_rw_lock_exclusive`` +``lck_rw_lock_shared, pthread_mutex_trylock, pthread_rwlock_tryrdlock, pthread_rwlock_tryrwlock, lck_mtx_try_lock, +lck_rw_try_lock_exclusive, lck_rw_try_lock_shared, pthread_mutex_unlock, pthread_rwlock_unlock, lck_mtx_unlock, lck_rw_done``. + + +.. code-block:: c + + pthread_mutex_t mtx; + + void test() { + pthread_mutex_lock(&mtx); + pthread_mutex_lock(&mtx); + // warn: this lock has already been acquired + } + + lck_mtx_t lck1, lck2; + + void test() { + lck_mtx_lock(&lck1); + lck_mtx_lock(&lck2); + lck_mtx_unlock(&lck1); + // warn: this was not the most recently acquired lock + } + + lck_mtx_t lck1, lck2; + + void test() { + if (lck_mtx_try_lock(&lck1) == 0) + return; + + lck_mtx_lock(&lck2); + lck_mtx_unlock(&lck1); + // warn: this was not the most recently acquired lock + } + +alpha.unix.SimpleStream (C) +""""""""""""""""""""""""""" +Check for misuses of stream APIs. Check for misuses of stream APIs: ``fopen, fclose`` +(demo checker, the subject of the demo (`Slides `_ , +`Video `_) by Anna Zaks and Jordan Rose presented at the +`2012 LLVM Developers' Meeting `_). + +.. code-block:: c + + void test() { + FILE *F = fopen("myfile.txt", "w"); + } // warn: opened file is never closed + + void test() { + FILE *F = fopen("myfile.txt", "w"); + + if (F) + fclose(F); + + fclose(F); // warn: closing a previously closed file stream + } + +alpha.unix.Stream (C) +""""""""""""""""""""" +Check stream handling functions: ``fopen, tmpfile, fclose, fread, fwrite, fseek, ftell, rewind, fgetpos,`` +``fsetpos, clearerr, feof, ferror, fileno``. + +.. code-block:: c + + void test() { + FILE *p = fopen("foo", "r"); + } // warn: opened file is never closed + + void test() { + FILE *p = fopen("foo", "r"); + fseek(p, 1, SEEK_SET); // warn: stream pointer might be NULL + fclose(p); + } + + void test() { + FILE *p = fopen("foo", "r"); + + if (p) + fseek(p, 1, 3); + // warn: third arg should be SEEK_SET, SEEK_END, or SEEK_CUR + + fclose(p); + } + + void test() { + FILE *p = fopen("foo", "r"); + fclose(p); + fclose(p); // warn: already closed + } + + void test() { + FILE *p = tmpfile(); + ftell(p); // warn: stream pointer might be NULL + fclose(p); + } + + +alpha.unix.cstring.BufferOverlap (C) +"""""""""""""""""""""""""""""""""""" +Checks for overlap in two buffer arguments. Applies to: ``memcpy, mempcpy``. + +.. code-block:: c + + void test() { + int a[4] = {0}; + memcpy(a + 2, a + 1, 8); // warn + } + +alpha.unix.cstring.NotNullTerminated (C) +"""""""""""""""""""""""""""""""""""""""" +Check for arguments which are not null-terminated strings; applies to: ``strlen, strnlen, strcpy, strncpy, strcat, strncat``. + +.. code-block:: c + + void test() { + int y = strlen((char *)&test); // warn + } + +alpha.unix.cstring.OutOfBounds (C) +"""""""""""""""""""""""""""""""""" +Check for out-of-bounds access in string functions; applies to:`` strncopy, strncat``. + + +.. code-block:: c + + void test() { + int y = strlen((char *)&test); // warn + } + + +Debug Checkers +--------------- + +.. _debug-checkers: + + +debug +^^^^^ + +Checkers used for debugging the analyzer. +:doc:`developer-docs/DebugChecks` page contains a detailed description. + +debug.AnalysisOrder +""""""""""""""""""" +Print callbacks that are called during analysis in order. + +debug.ConfigDumper +"""""""""""""""""" +Dump config table. + +debug.DumpCFG Display +""""""""""""""""""""" +Control-Flow Graphs. + +debug.DumpCallGraph +""""""""""""""""""" +Display Call Graph. + +debug.DumpCalls +""""""""""""""" +Print calls as they are traversed by the engine. + +debug.DumpDominators +"""""""""""""""""""" +Print the dominance tree for a given CFG. + +debug.DumpLiveVars +"""""""""""""""""" +Print results of live variable analysis. + +debug.DumpTraversal +""""""""""""""""""" +Print branch conditions as they are traversed by the engine. + +debug.ExprInspection +"""""""""""""""""""" +Check the analyzer's understanding of expressions. + +debug.Stats +""""""""""" +Emit warnings with analyzer statistics. + +debug.TaintTest +""""""""""""""" +Mark tainted symbols as such. + +debug.ViewCFG +""""""""""""" +View Control-Flow Graphs using GraphViz. + +debug.ViewCallGraph +""""""""""""""""""" +View Call Graph using GraphViz. + +debug.ViewExplodedGraph +""""""""""""""""""""""" +View Exploded Graphs using GraphViz. + diff --git a/docs/analyzer/checkers/callandmessage_example.c b/docs/analyzer/checkers/callandmessage_example.c new file mode 100644 index 0000000000000000000000000000000000000000..7e14fbe464fcb8726c29c01207bb9fe0fb497dca --- /dev/null +++ b/docs/analyzer/checkers/callandmessage_example.c @@ -0,0 +1,66 @@ +//C +void test() { + void (*foo)(void); + foo = 0; + foo(); // warn: function pointer is null + } + + // C++ + class C { + public: + void f(); + }; + + void test() { + C *pc; + pc->f(); // warn: object pointer is uninitialized + } + + // C++ + class C { + public: + void f(); + }; + + void test() { + C *pc = 0; + pc->f(); // warn: object pointer is null + } + + // Objective-C + @interface MyClass : NSObject + @property (readwrite,assign) id x; + - (long double)longDoubleM; + @end + + void test() { + MyClass *obj1; + long double ld1 = [obj1 longDoubleM]; + // warn: receiver is uninitialized + } + + // Objective-C + @interface MyClass : NSObject + @property (readwrite,assign) id x; + - (long double)longDoubleM; + @end + + void test() { + MyClass *obj1; + id i = obj1.x; // warn: uninitialized object pointer + } + + // Objective-C + @interface Subscriptable : NSObject + - (id)objectAtIndexedSubscript:(unsigned int)index; + @end + + @interface MyClass : Subscriptable + @property (readwrite,assign) id x; + - (long double)longDoubleM; + @end + + void test() { + MyClass *obj1; + id i = obj1[0]; // warn: uninitialized object pointer + } diff --git a/docs/analyzer/checkers/dealloc_example.m b/docs/analyzer/checkers/dealloc_example.m new file mode 100644 index 0000000000000000000000000000000000000000..ac51911aff16b4ceb9a2b679a34ab8e02e0f2163 --- /dev/null +++ b/docs/analyzer/checkers/dealloc_example.m @@ -0,0 +1,49 @@ + + +@interface MyObject : NSObject { + id _myproperty; +} +@end + +@implementation MyObject // warn: lacks 'dealloc' +@end + +@interface MyObject : NSObject {} +@property(assign) id myproperty; +@end + +@implementation MyObject // warn: does not send 'dealloc' to super +- (void)dealloc { + self.myproperty = 0; +} +@end + +@interface MyObject : NSObject { + id _myproperty; +} +@property(retain) id myproperty; +@end + +@implementation MyObject +@synthesize myproperty = _myproperty; + // warn: var was retained but wasn't released +- (void)dealloc { + [super dealloc]; +} +@end + +@interface MyObject : NSObject { + id _myproperty; +} +@property(assign) id myproperty; +@end + +@implementation MyObject +@synthesize myproperty = _myproperty; + // warn: var wasn't retained but was released +- (void)dealloc { + [_myproperty release]; + [super dealloc]; +} +@end + diff --git a/docs/analyzer/checkers/dividezero_example.c b/docs/analyzer/checkers/dividezero_example.c new file mode 100644 index 0000000000000000000000000000000000000000..00ffaac491e50ef62b31100c0127291405815aac --- /dev/null +++ b/docs/analyzer/checkers/dividezero_example.c @@ -0,0 +1,9 @@ +void test(int z) { + if (z == 0) + int x = 1 / z; // warn +} + +void test() { + int x = 1; + int y = x % 0; // warn +} diff --git a/docs/analyzer/checkers/mismatched_deallocator_example.cpp b/docs/analyzer/checkers/mismatched_deallocator_example.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2a4103240fe81ac19bbe5cd13d014ef01793dba5 --- /dev/null +++ b/docs/analyzer/checkers/mismatched_deallocator_example.cpp @@ -0,0 +1,56 @@ +// C, C++ +void test() { + int *p = (int *)malloc(sizeof(int)); + delete p; // warn +} + +// C, C++ +void __attribute((ownership_returns(malloc))) *user_malloc(size_t); + +void test() { + int *p = (int *)user_malloc(sizeof(int)); + delete p; // warn +} + +// C, C++ +void test() { + int *p = new int; + free(p); // warn +} + +// C, C++ +void test() { + int *p = new int[1]; + realloc(p, sizeof(long)); // warn +} + +// C, C++ +template +struct SimpleSmartPointer { + T *ptr; + + explicit SimpleSmartPointer(T *p = 0) : ptr(p) {} + ~SimpleSmartPointer() { + delete ptr; // warn + } +}; + +void test() { + SimpleSmartPointer a((int *)malloc(4)); +} + +// C++ +void test() { + int *p = (int *)operator new(0); + delete[] p; // warn +} + +// Objective-C, C++ +void test(NSUInteger dataLength) { + int *p = new int; + NSData *d = [NSData dataWithBytesNoCopy:p + length:sizeof(int) freeWhenDone:1]; + // warn +dataWithBytesNoCopy:length:freeWhenDone: cannot take + // ownership of memory allocated by 'new' +} + diff --git a/docs/analyzer/checkers/newdelete_example.cpp b/docs/analyzer/checkers/newdelete_example.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b26ddcb3d964e8d99fffc28dc69263cec359bd4c --- /dev/null +++ b/docs/analyzer/checkers/newdelete_example.cpp @@ -0,0 +1,41 @@ +void f(int *p); + +void testUseMiddleArgAfterDelete(int *p) { + delete p; + f(p); // warn: use after free +} + +class SomeClass { +public: + void f(); +}; + +void test() { + SomeClass *c = new SomeClass; + delete c; + c->f(); // warn: use after free +} + +void test() { + int *p = (int *)__builtin_alloca(sizeof(int)); + delete p; // warn: deleting memory allocated by alloca +} + +void test() { + int *p = new int; + delete p; + delete p; // warn: attempt to free released +} + +void test() { + int i; + delete &i; // warn: delete address of local +} + +void test() { + int *p = new int[1]; + delete[] (++p); + // warn: argument to 'delete[]' is offset by 4 bytes + // from the start of memory allocated by 'new[]' +} + diff --git a/docs/analyzer/checkers/seckeychainapi_example.m b/docs/analyzer/checkers/seckeychainapi_example.m new file mode 100644 index 0000000000000000000000000000000000000000..979a5d97c7704171e58127b12e72fc765c0d0293 --- /dev/null +++ b/docs/analyzer/checkers/seckeychainapi_example.m @@ -0,0 +1,64 @@ + + +void test() { + unsigned int *ptr = 0; + UInt32 length; + + SecKeychainItemFreeContent(ptr, &length); + // warn: trying to free data which has not been allocated +} + +void test() { + unsigned int *ptr = 0; + UInt32 *length = 0; + void *outData; + + OSStatus st = + SecKeychainItemCopyContent(2, ptr, ptr, length, outData); + // warn: data is not released +} + +void test() { + unsigned int *ptr = 0; + UInt32 *length = 0; + void *outData; + + OSStatus st = + SecKeychainItemCopyContent(2, ptr, ptr, length, &outData); + + SecKeychainItemFreeContent(ptr, outData); + // warn: only call free if a non-NULL buffer was returned +} + +void test() { + unsigned int *ptr = 0; + UInt32 *length = 0; + void *outData; + + OSStatus st = + SecKeychainItemCopyContent(2, ptr, ptr, length, &outData); + + st = SecKeychainItemCopyContent(2, ptr, ptr, length, &outData); + // warn: release data before another call to the allocator + + if (st == noErr) + SecKeychainItemFreeContent(ptr, outData); +} + +void test() { + SecKeychainItemRef itemRef = 0; + SecKeychainAttributeInfo *info = 0; + SecItemClass *itemClass = 0; + SecKeychainAttributeList *attrList = 0; + UInt32 *length = 0; + void *outData = 0; + + OSStatus st = + SecKeychainItemCopyAttributesAndData(itemRef, info, + itemClass, &attrList, + length, &outData); + + SecKeychainItemFreeContent(attrList, outData); + // warn: deallocator doesn't match the allocator +} + diff --git a/docs/analyzer/checkers/unix_api_example.c b/docs/analyzer/checkers/unix_api_example.c new file mode 100644 index 0000000000000000000000000000000000000000..66ed56fd8663b7f3b10413f7883575366e028a68 --- /dev/null +++ b/docs/analyzer/checkers/unix_api_example.c @@ -0,0 +1,37 @@ + +// Currently the check is performed for apple targets only. +void test(const char *path) { + int fd = open(path, O_CREAT); + // warn: call to 'open' requires a third argument when the + // 'O_CREAT' flag is set +} + +void f(); + +void test() { + pthread_once_t pred = {0x30B1BCBA, {0}}; + pthread_once(&pred, f); + // warn: call to 'pthread_once' uses the local variable +} + +void test() { + void *p = malloc(0); // warn: allocation size of 0 bytes +} + +void test() { + void *p = calloc(0, 42); // warn: allocation size of 0 bytes +} + +void test() { + void *p = malloc(1); + p = realloc(p, 0); // warn: allocation size of 0 bytes +} + +void test() { + void *p = alloca(0); // warn: allocation size of 0 bytes +} + +void test() { + void *p = valloc(0); // warn: allocation size of 0 bytes +} + diff --git a/docs/analyzer/checkers/unix_malloc_example.c b/docs/analyzer/checkers/unix_malloc_example.c new file mode 100644 index 0000000000000000000000000000000000000000..68c5a4a8f1c5fdc158d5f52946cd32923daf0ea6 --- /dev/null +++ b/docs/analyzer/checkers/unix_malloc_example.c @@ -0,0 +1,30 @@ + +void test() { + int *p = malloc(1); + free(p); + free(p); // warn: attempt to free released memory +} + +void test() { + int *p = malloc(sizeof(int)); + free(p); + *p = 1; // warn: use after free +} + +void test() { + int *p = malloc(1); + if (p) + return; // warn: memory is never released +} + +void test() { + int a[] = { 1 }; + free(a); // warn: argument is not allocated by malloc +} + +void test() { + int *p = malloc(sizeof(char)); + p = p - 1; + free(p); // warn: argument to free() is offset by -4 bytes +} + diff --git a/docs/analyzer/developer-docs.rst b/docs/analyzer/developer-docs.rst new file mode 100644 index 0000000000000000000000000000000000000000..a3d74a765f933d9d4dcd7a2a3b52faf153f7fc14 --- /dev/null +++ b/docs/analyzer/developer-docs.rst @@ -0,0 +1,14 @@ +Developer Docs +============== + +Contents: + +.. toctree:: + :maxdepth: 2 + + developer-docs/DebugChecks + developer-docs/IPA + developer-docs/InitializerLists + developer-docs/nullability + developer-docs/RegionStore + \ No newline at end of file diff --git a/docs/analyzer/DebugChecks.rst b/docs/analyzer/developer-docs/DebugChecks.rst similarity index 100% rename from docs/analyzer/DebugChecks.rst rename to docs/analyzer/developer-docs/DebugChecks.rst diff --git a/docs/analyzer/IPA.txt b/docs/analyzer/developer-docs/IPA.rst similarity index 87% rename from docs/analyzer/IPA.txt rename to docs/analyzer/developer-docs/IPA.rst index 3842075fcd6a40c0054fe56b9613db02bbdb53a3..2e8fe37055b332096db383f6dd0c953e7655c9b2 100644 --- a/docs/analyzer/IPA.txt +++ b/docs/analyzer/developer-docs/IPA.rst @@ -2,45 +2,46 @@ Inlining ======== There are several options that control which calls the analyzer will consider for -inlining. The major one is -analyzer-config ipa: +inlining. The major one is ``-analyzer-config ipa``: - -analyzer-config ipa=none - All inlining is disabled. This is the only mode - available in LLVM 3.1 and earlier and in Xcode 4.3 and earlier. +* ``analyzer-config ipa=none`` - All inlining is disabled. This is the only mode + available in LLVM 3.1 and earlier and in Xcode 4.3 and earlier. - -analyzer-config ipa=basic-inlining - Turns on inlining for C functions, C++ - static member functions, and blocks -- essentially, the calls that behave - like simple C function calls. This is essentially the mode used in - Xcode 4.4. +* ``analyzer-config ipa=basic-inlining`` - Turns on inlining for C functions, C++ + static member functions, and blocks -- essentially, the calls that behave + like simple C function calls. This is essentially the mode used in + Xcode 4.4. - -analyzer-config ipa=inlining - Turns on inlining when we can confidently find +* ``analyzer-config ipa=inlining`` - Turns on inlining when we can confidently find the function/method body corresponding to the call. (C functions, static functions, devirtualized C++ methods, Objective-C class methods, Objective-C instance methods when ExprEngine is confident about the dynamic type of the instance). - -analyzer-config ipa=dynamic - Inline instance methods for which the type is +* ``analyzer-config ipa=dynamic`` - Inline instance methods for which the type is determined at runtime and we are not 100% sure that our type info is correct. For virtual calls, inline the most plausible definition. - -analyzer-config ipa=dynamic-bifurcate - Same as -analyzer-config ipa=dynamic, +* ``analyzer-config ipa=dynamic-bifurcate`` - Same as -analyzer-config ipa=dynamic, but the path is split. We inline on one branch and do not inline on the other. This mode does not drop the coverage in cases when the parent class has code that is only exercised when some of its methods are overridden. -Currently, -analyzer-config ipa=dynamic-bifurcate is the default mode. +Currently, ``-analyzer-config ipa=dynamic-bifurcate`` is the default mode. -While -analyzer-config ipa determines in general how aggressively the analyzer +While ``-analyzer-config ipa`` determines in general how aggressively the analyzer will try to inline functions, several additional options control which types of functions can inlined, in an all-or-nothing way. These options use the analyzer's configuration table, so they are all specified as follows: - -analyzer-config OPTION=VALUE + ``-analyzer-config OPTION=VALUE`` -### c++-inlining ### +c++-inlining +------------ This option controls which C++ member functions may be inlined. - -analyzer-config c++-inlining=[none | methods | constructors | destructors] + ``-analyzer-config c++-inlining=[none | methods | constructors | destructors]`` Each of these modes implies that all the previous member function kinds will be inlined as well; it doesn't make sense to inline destructors without inlining @@ -55,11 +56,12 @@ destructors will not be inlined. Additionally, no C++ member functions will be inlined under -analyzer-config ipa=none or -analyzer-config ipa=basic-inlining, regardless of the setting of the c++-inlining mode. -### c++-template-inlining ### +c++-template-inlining +^^^^^^^^^^^^^^^^^^^^^ This option controls whether C++ templated functions may be inlined. - -analyzer-config c++-template-inlining=[true | false] + ``-analyzer-config c++-template-inlining=[true | false]`` Currently, template functions are considered for inlining by default. @@ -68,13 +70,14 @@ of false positives, either by considering paths that the caller considers impossible (by some unstated precondition), or by inlining some but not all of a deep implementation of a function. -### c++-stdlib-inlining ### +c++-stdlib-inlining +^^^^^^^^^^^^^^^^^^^ This option controls whether functions from the C++ standard library, including methods of the container classes in the Standard Template Library, should be considered for inlining. - -analyzer-config c++-stdlib-inlining=[true | false] + ``-analyzer-config c++-stdlib-inlining=[true | false]`` Currently, C++ standard library functions are considered for inlining by default. @@ -85,12 +88,13 @@ positive due to poor modeling of the STL leads to a poor user experience, since most users would not be comfortable adding assertions to system headers in order to silence analyzer warnings. -### c++-container-inlining ### +c++-container-inlining +^^^^^^^^^^^^^^^^^^^^^^ This option controls whether constructors and destructors of "container" types should be considered for inlining. - -analyzer-config c++-container-inlining=[true | false] + ``-analyzer-config c++-container-inlining=[true | false]`` Currently, these constructors and destructors are NOT considered for inlining by default. @@ -101,9 +105,12 @@ with the latter specified in the C++11 standard. The analyzer currently does a fairly poor job of modeling certain data structure invariants of container-like objects. For example, these three expressions should be equivalent: - std::distance(c.begin(), c.end()) == 0 - c.begin() == c.end() - c.empty()) + +.. code-block:: cpp + + std::distance(c.begin(), c.end()) == 0 + c.begin() == c.end() + c.empty() Many of these issues are avoided if containers always have unknown, symbolic state, which is what happens when their constructors are treated as opaque. @@ -112,7 +119,7 @@ inlining, or choose to model them directly using checkers instead. Basics of Implementation ------------------------ +------------------------ The low-level mechanism of inlining a function is handled in ExprEngine::inlineCall and ExprEngine::processCallExit. @@ -144,7 +151,7 @@ reasonable steps: onto the work list, so that evaluation of the caller can continue. Retry Without Inlining ----------------------- +^^^^^^^^^^^^^^^^^^^^^^ In some cases, we would like to retry analysis without inlining a particular call. @@ -159,7 +166,7 @@ ReplayWithoutInlining bit added to it (ExprEngine::replayWithoutInlining). The path is then re-analyzed from that point without inlining that particular call. Deciding When to Inline ------------------------ +^^^^^^^^^^^^^^^^^^^^^^^ In general, the analyzer attempts to inline as much as possible, since it provides a better summary of what actually happens in the program. There are @@ -202,7 +209,7 @@ some cases, however, where the analyzer chooses not to inline: Dynamic Calls and Devirtualization ----------------------------------- +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ "Dynamic" calls are those that are resolved at runtime, such as C++ virtual method calls and Objective-C message sends. Due to the path-sensitive nature of @@ -214,7 +221,8 @@ method would actually be called at runtime. This is possible when the type information is constrained enough for a simulated C++/Objective-C object that the analyzer can make such a decision. - == DynamicTypeInfo == +DynamicTypeInfo +^^^^^^^^^^^^^^^ As the analyzer analyzes a path, it may accrue information to refine the knowledge about the type of an object. This can then be used to make better @@ -241,7 +249,8 @@ information for a region. off, but sometimes the information provided by casts can be useful. - == RuntimeDefinition == +RuntimeDefinition +^^^^^^^^^^^^^^^^^ The basis of devirtualization is CallEvent's getRuntimeDefinition() method, which returns a RuntimeDefinition object. When asked to provide a definition, @@ -258,7 +267,8 @@ corresponding to the object being called (i.e., the "receiver" in Objective-C parlance), which ExprEngine uses to decide whether or not the call should be inlined. - == Inlining Dynamic Calls == +Inlining Dynamic Calls +^^^^^^^^^^^^^^^^^^^^^^ The -analyzer-config ipa option has five different modes: none, basic-inlining, inlining, dynamic, and dynamic-bifurcate. Under -analyzer-config ipa=dynamic, @@ -282,9 +292,9 @@ can be safely devirtualized. Bifurcation ------------ +^^^^^^^^^^^ -ExprEngine::BifurcateCall implements the -analyzer-config ipa=dynamic-bifurcate +ExprEngine::BifurcateCall implements the ``-analyzer-config ipa=dynamic-bifurcate`` mode. When a call is made on an object with imprecise dynamic type information @@ -294,14 +304,14 @@ RuntimeDefinition object) with a path-sensitive "mode" in the ProgramState. Currently, there are 2 modes: - DynamicDispatchModeInlined - Models the case where the dynamic type information +* ``DynamicDispatchModeInlined`` - Models the case where the dynamic type information of the receiver (MemoryRegion) is assumed to be perfectly constrained so that a given definition of a method is expected to be the code actually called. When this mode is set, ExprEngine uses the Decl from RuntimeDefinition to inline any dynamically dispatched call sent to this receiver because the function definition is considered to be fully resolved. - DynamicDispatchModeConservative - Models the case where the dynamic type +* ``DynamicDispatchModeConservative`` - Models the case where the dynamic type information is assumed to be incorrect, for example, implies that the method definition is overridden in a subclass. In such cases, ExprEngine does not inline the methods sent to the receiver (MemoryRegion), even if a candidate @@ -319,7 +329,7 @@ performance hit and the possibility of false positives on the path where the conservative mode is used. Objective-C Message Heuristics ------------------------------- +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ExprEngine relies on a set of heuristics to partition the set of Objective-C method calls into those that require bifurcation and those that do not. Below @@ -340,7 +350,7 @@ are the cases when the DynamicTypeInfo of the object is considered precise receiver's class or by any superclasses. C++ Caveats --------------------- +^^^^^^^^^^^ C++11 [class.cdtor]p4 describes how the vtable of an object is modified as it is being constructed or destructed; that is, the type of the object depends on @@ -349,21 +359,21 @@ DynamicTypeInfo in the DynamicTypePropagation checker. There are several limitations in the current implementation: -- Temporaries are poorly modeled right now because we're not confident in the +* Temporaries are poorly modeled right now because we're not confident in the placement of their destructors in the CFG. We currently won't inline their constructors unless the destructor is trivial, and don't process their destructors at all, not even to invalidate the region. -- 'new' is poorly modeled due to some nasty CFG/design issues. This is tracked +* 'new' is poorly modeled due to some nasty CFG/design issues. This is tracked in PR12014. 'delete' is not modeled at all. -- Arrays of objects are modeled very poorly right now. ExprEngine currently +* Arrays of objects are modeled very poorly right now. ExprEngine currently only simulates the first constructor and first destructor. Because of this, ExprEngine does not inline any constructors or destructors for arrays. CallEvent -========= +^^^^^^^^^ A CallEvent represents a specific call to a function, method, or other body of code. It is path-sensitive, containing both the current state (ProgramStateRef) diff --git a/docs/analyzer/DesignDiscussions/InitializerLists.rst b/docs/analyzer/developer-docs/InitializerLists.rst similarity index 71% rename from docs/analyzer/DesignDiscussions/InitializerLists.rst rename to docs/analyzer/developer-docs/InitializerLists.rst index af41e4ec8f0ace23aa97ecb30303c404612a8ecf..c9dc7a048921eb84b3504bf636bdc2834285db02 100644 --- a/docs/analyzer/DesignDiscussions/InitializerLists.rst +++ b/docs/analyzer/developer-docs/InitializerLists.rst @@ -1,3 +1,6 @@ +================ +Initializer List +================ This discussion took place in https://reviews.llvm.org/D35216 "Escape symbols when creating std::initializer_list". @@ -20,11 +23,11 @@ passed into initializer list expressions to immediately escape. This fix is overly conservative though. So i did a bit of investigation as to how model std::initializer_list better. -According to the standard, std::initializer_list is an object that has -methods begin(), end(), and size(), where begin() returns a pointer to continuous -array of size() objects of type T, and end() is equal to begin() plus size(). +According to the standard, ``std::initializer_list`` is an object that has +methods ``begin(), end(), and size()``, where ``begin()`` returns a pointer to continuous +array of ``size()`` objects of type T, and end() is equal to begin() plus size(). The standard does hint that it should be possible to implement -std::initializer_list as a pair of pointers, or as a pointer and a size +``std::initializer_list`` as a pair of pointers, or as a pointer and a size integer, however specific fields that the object would contain are an implementation detail. @@ -33,21 +36,21 @@ Or, at least, it should be possible to explain to the analyzer that the list somehow "takes hold" of the values put into it. Initializer lists can also be copied, which is a separate story that i'm not trying to address here. -The obvious approach to modeling std::initializer_list in a checker would be to +The obvious approach to modeling ``std::initializer_list`` in a checker would be to construct a SymbolMetadata for the memory region of the initializer list object, -which would be of type T* and represent begin(), so we'd trivially model begin() +which would be of type ``T*`` and represent ``begin()``, so we'd trivially model ``begin()`` as a function that returns this symbol. The array pointed to by that symbol -would be bindLoc()ed to contain the list's contents (probably as a CompoundVal +would be ``bindLoc()``ed to contain the list's contents (probably as a ``CompoundVal`` to produce less bindings in the store). Extent of this array would represent -size() and would be equal to the length of the list as written. +``size()`` and would be equal to the length of the list as written. So this sounds good, however apparently it does nothing to address our false -positives: when the list escapes, our RegionStoreManager is not magically +positives: when the list escapes, our ``RegionStoreManager`` is not magically guessing that the metadata symbol attached to it, together with its contents, should also escape. In fact, it's impossible to trigger a pointer escape from within the checker. -Approach (1): If only we enabled ProgramState::bindLoc(..., notifyChanges=true) +Approach (1): If only we enabled ``ProgramState::bindLoc(..., notifyChanges=true)`` to cause pointer escapes (not only region changes) (which sounds like the right thing to do anyway) such checker would be able to solve the false positives by triggering escapes when binding list elements to the list. However, it'd be as @@ -71,7 +74,7 @@ to escape. This puts a stress on the checkers, but with a smart data map it wouldn't be a problem. Approach (4): We could allow checkers to trigger pointer escapes in arbitrary -moments. If we allow doing this within checkPointerEscape callback itself, we +moments. If we allow doing this within ``checkPointerEscape`` callback itself, we would be able to express facts like "when this region escapes, that metadata symbol attached to it should also escape". This sounds like an ultimate freedom, with maximum stress on the checkers - still not too much stress when we have @@ -84,11 +87,10 @@ performance overhead, and clarity seems nice. At this point, I am a bit wondering about two questions. -- When should something belong to a checker and when should something belong -to the engine? Sometimes we model library aspects in the engine and model -language constructs in checkers. -- What is the checker programming model that we are aiming for? Maximum -freedom or more easy checker development? +* When should something belong to a checker and when should something belong to the engine? + Sometimes we model library aspects in the engine and model language constructs in checkers. + +* What is the checker programming model that we are aiming for? Maximum freedom or more easy checker development? I think if we aim for maximum freedom, we do not need to worry about the potential stress on checkers, and we can introduce abstractions to mitigate that @@ -100,36 +102,37 @@ of complicating the API. Right now I have no preference or objections between the alternatives but there are some random thoughts: -- Maybe it would be great to have a guideline how to evolve the analyzer and -follow it, so it can help us to decide in similar situations -- I do care about performance in this case. The reason is that we have a -limited performance budget. And I think we should not expect most of the checker -writers to add modeling of language constructs. So, in my opinion, it is ok to -have less nice/more verbose API for language modeling if we can have better -performance this way, since it only needs to be done once, and is done by the -framework developers. +* Maybe it would be great to have a guideline how to evolve the analyzer and + follow it, so it can help us to decide in similar situations + +* I do care about performance in this case. The reason is that we have a + limited performance budget. And I think we should not expect most of the checker + writers to add modeling of language constructs. So, in my opinion, it is ok to + have less nice/more verbose API for language modeling if we can have better + performance this way, since it only needs to be done once, and is done by the + framework developers. **Artem:** These are some great questions, i guess it'd be better to discuss them more openly. As a quick dump of my current mood: -- To me it seems obvious that we need to aim for a checker API that is both -simple and powerful. This can probably by keeping the API as powerful as -necessary while providing a layer of simple ready-made solutions on top of it. -Probably a few reusable components for assembling checkers. And this layer -should ideally be pleasant enough to work with, so that people would prefer to -extend it when something is lacking, instead of falling back to the complex -omnipotent API. I'm thinking of AST matchers vs. AST visitors as a roughly -similar situation: matchers are not omnipotent, but they're so nice. - -- Separation between core and checkers is usually quite strange. Once we have -shared state traits, i generally wouldn't mind having region store or range -constraint manager as checkers (though it's probably not worth it to transform -them - just a mood). The main thing to avoid here would be the situation when -the checker overwrites stuff written by the core because it thinks it has a -better idea what's going on, so the core should provide a good default behavior. - -- Yeah, i totally care about performance as well, and if i try to implement -approach, i'd make sure it's good. +* To me it seems obvious that we need to aim for a checker API that is both + simple and powerful. This can probably by keeping the API as powerful as + necessary while providing a layer of simple ready-made solutions on top of it. + Probably a few reusable components for assembling checkers. And this layer + should ideally be pleasant enough to work with, so that people would prefer to + extend it when something is lacking, instead of falling back to the complex + omnipotent API. I'm thinking of AST matchers vs. AST visitors as a roughly + similar situation: matchers are not omnipotent, but they're so nice. + +* Separation between core and checkers is usually quite strange. Once we have + shared state traits, i generally wouldn't mind having region store or range + constraint manager as checkers (though it's probably not worth it to transform + them - just a mood). The main thing to avoid here would be the situation when + the checker overwrites stuff written by the core because it thinks it has a + better idea what's going on, so the core should provide a good default behavior. + +* Yeah, i totally care about performance as well, and if i try to implement + approach, i'd make sure it's good. **Artem:** @@ -145,7 +148,7 @@ value in different moments of time, but at most one of them represents the actual metadata value. So we'd be escaping more stuff than necessary. If only we had "ghost fields" -(http://lists.llvm.org/pipermail/cfe-dev/2016-May/049000.html), it would have +(https://lists.llvm.org/pipermail/cfe-dev/2016-May/049000.html), it would have been much easier, because the ghost field would only contain the actual metadata, and the Store would always know about it. This example adds to my belief that ghost fields are exactly what we need for most C++ checkers. @@ -159,7 +162,7 @@ with different identifiers. This wouldn't specify how the memory is reachable, but it would allow for transfer functions to get at those regions and it would allow for invalidation. -For std::initializer_list this reachable region would the region for the backing +For ``std::initializer_list`` this reachable region would the region for the backing array and the transfer functions for begin() and end() yield the beginning and end element regions for it. @@ -185,7 +188,7 @@ invalidation for free. **Artem:** -> In this case, I would be fine with some sort of AbstractStorageMemoryRegion +> In this case, I would be fine with some sort of ``AbstractStorageMemoryRegion`` > that meant "here is a memory region and somewhere reachable from here exists > another region of type T". Or even multiple regions with different > identifiers. This wouldn't specify how the memory is reachable, but it would @@ -196,7 +199,7 @@ Yeah, this is what we can easily implement now as a symbolic-region-based-on-a-metadata-symbol (though we can make a new region class for that if we eg. want it typed). The problem is that the relation between such storage region and its parent object region is essentially -immaterial, similarly to the relation between SymbolRegionValue and its parent +immaterial, similarly to the relation between ``SymbolRegionValue`` and its parent region. Region contents are mutable: today the abstract storage is reachable from its parent object, tomorrow it's not, and maybe something else becomes reachable, something that isn't even abstract. So the parent region for the @@ -213,28 +216,31 @@ change the data after the object is constructed - so this region's contents are essentially immutable. For the future, i feel as if it is a dead end. I'd like to consider another funny example. Suppose we're trying to model -std::unique_ptr. Consider:: - - void bar(const std::unique_ptr &x); - - void foo(std::unique_ptr &x) { - int *a = x.get(); // (a, 0, direct): &AbstractStorageRegion - *a = 1; // (AbstractStorageRegion, 0, direct): 1 S32b - int *b = new int; - *b = 2; // (SymRegion{conj_$0}, 0 ,direct): 2 S32b - x.reset(b); // Checker map: x -> SymRegion{conj_$0} - bar(x); // 'a' doesn't escape (the pointer was unique), 'b' does. - clang_analyzer_eval(*a == 1); // Making this true is up to the checker. - clang_analyzer_eval(*b == 2); // Making this unknown is up to the checker. - } - -The checker doesn't totally need to ensure that *a == 1 passes - even though the -pointer was unique, it could theoretically have .get()-ed above and the code + +.. code-block:: cpp + + std::unique_ptr. Consider:: + + void bar(const std::unique_ptr &x); + + void foo(std::unique_ptr &x) { + int *a = x.get(); // (a, 0, direct): &AbstractStorageRegion + *a = 1; // (AbstractStorageRegion, 0, direct): 1 S32b + int *b = new int; + *b = 2; // (SymRegion{conj_$0}, 0 ,direct): 2 S32b + x.reset(b); // Checker map: x -> SymRegion{conj_$0} + bar(x); // 'a' doesn't escape (the pointer was unique), 'b' does. + clang_analyzer_eval(*a == 1); // Making this true is up to the checker. + clang_analyzer_eval(*b == 2); // Making this unknown is up to the checker. + } + +The checker doesn't totally need to ensure that ``*a == 1`` passes - even though the +pointer was unique, it could theoretically have ``.get()``-ed above and the code could of course break the uniqueness invariant (though we'd probably want it). -The checker can say that "even if *a did escape, it was not because it was +The checker can say that "even if ``*a`` did escape, it was not because it was stuffed directly into bar()". -The checker's direct responsibility, however, is to solve the *b == 2 thing +The checker's direct responsibility, however, is to solve the ``*b == 2`` thing (which is in fact the problem we're dealing with in this patch - escaping the storage region of the object). @@ -293,7 +299,7 @@ FunctionDecl's body in a body farm to have a local variable, even if such variable doesn't actually exist, even if it cannot be seen from outside the function call. I'm not seeing immediate practical difference between "it does actually exist" and "it doesn't actually exist, just a handy abstraction". -Similarly, i think it's fine if we have a CXXRecordDecl with +Similarly, i think it's fine if we have a ``CXXRecordDecl`` with implementation-defined contents, and try to farm up a member variable as a handy abstraction (we don't even need to know its name or offset, only that it's there somewhere). @@ -303,18 +309,18 @@ somewhere). We've discussed it in person with Devin, and he provided more points to think about: -- If the initializer list consists of non-POD data, constructors of list's -objects need to take the sub-region of the list's region as this-region In the -current (v2) version of this patch, these objects are constructed elsewhere and -then trivial-copied into the list's metadata pointer region, which may be -incorrect. This is our overall problem with C++ constructors, which manifests in -this case as well. Additionally, objects would need to be constructed in the -analyzer's core, which would not be able to predict that it needs to take a -checker-specific region as this-region, which makes it harder, though it might -be mitigated by sharing the checker state traits. - -- Because "ghost variables" are not material to the user, we need to somehow -make super sure that they don't make it into the diagnostic messages. +* If the initializer list consists of non-POD data, constructors of list's + objects need to take the sub-region of the list's region as this-region In the + current (v2) version of this patch, these objects are constructed elsewhere and + then trivial-copied into the list's metadata pointer region, which may be + incorrect. This is our overall problem with C++ constructors, which manifests in + this case as well. Additionally, objects would need to be constructed in the + analyzer's core, which would not be able to predict that it needs to take a + checker-specific region as this-region, which makes it harder, though it might + be mitigated by sharing the checker state traits. + +* Because "ghost variables" are not material to the user, we need to somehow + make super sure that they don't make it into the diagnostic messages. So, because this needs further digging into overall C++ support and rises too many questions, i'm delaying a better approach to this problem and will fall diff --git a/docs/analyzer/RegionStore.txt b/docs/analyzer/developer-docs/RegionStore.rst similarity index 72% rename from docs/analyzer/RegionStore.txt rename to docs/analyzer/developer-docs/RegionStore.rst index ef994b6401e26964577c2d532bc70ba6afe1d903..c963e5b720fe65e878df1fe22a0cf67d70417611 100644 --- a/docs/analyzer/RegionStore.txt +++ b/docs/analyzer/developer-docs/RegionStore.rst @@ -1,11 +1,14 @@ +============ +Region Store +============ The analyzer "Store" represents the contents of memory regions. It is an opaque -functional data structure stored in each ProgramState; the only class that can -modify the store is its associated StoreManager. +functional data structure stored in each ``ProgramState``; the only class that +can modify the store is its associated StoreManager. Currently (Feb. 2013), the only StoreManager implementation being used is -RegionStoreManager. This store records bindings to memory regions using a "base -region + offset" key. (This allows `*p` and `p[0]` to map to the same location, -among other benefits.) +``RegionStoreManager``. This store records bindings to memory regions using a +"base region + offset" key. (This allows ``*p`` and ``p[0]`` to map to the same +location, among other benefits.) Regions are grouped into "clusters", which roughly correspond to "regions with the same base region". This allows certain operations to be more efficient, @@ -14,50 +17,55 @@ such as invalidation. Regions that do not have a known offset use a special "symbolic" offset. These keys store both the original region, and the "concrete offset region" -- the last region whose offset is entirely concrete. (For example, in the expression -`foo.bar[1][i].baz`, the concrete offset region is the array `foo.bar[1]`, -since that has a known offset from the start of the top-level `foo` struct.) +``foo.bar[1][i].baz``, the concrete offset region is the array ``foo.bar[1]``, +since that has a known offset from the start of the top-level ``foo`` struct.) Binding Invalidation -==================== +-------------------- Supporting both concrete and symbolic offsets makes things a bit tricky. Here's an example: - foo[0] = 0; - foo[1] = 1; - foo[i] = i; +.. code-block:: cpp -After the third assignment, nothing can be said about the value of `foo[0]`, -because `foo[i]` may have overwritten it! Thus, *binding to a region with a + foo[0] = 0; + foo[1] = 1; + foo[i] = i; + +After the third assignment, nothing can be said about the value of ``foo[0]``, +because ``foo[i]`` may have overwritten it! Thus, *binding to a region with a symbolic offset invalidates the entire concrete offset region.* We know -`foo[i]` is somewhere within `foo`, so we don't have to invalidate anything -else, but we do have to be conservative about all other bindings within `foo`. +``foo[i]`` is somewhere within ``foo``, so we don't have to invalidate +anything else, but we do have to be conservative about all other bindings within +``foo``. Continuing the example: - foo[i] = i; - foo[0] = 0; +.. code-block:: cpp + + foo[i] = i; + foo[0] = 0; -After this latest assignment, nothing can be said about the value of `foo[i]`, -because `foo[0]` may have overwritten it! *Binding to a region R with a +After this latest assignment, nothing can be said about the value of ``foo[i]``, +because ``foo[0]`` may have overwritten it! *Binding to a region R with a concrete offset invalidates any symbolic offset bindings whose concrete offset -region is a super-region **or** sub-region of R.* All we know about `foo[i]` is -that it is somewhere within `foo`, so changing *anything* within `foo` might -change `foo[i]`, and changing *all* of `foo` (or its base region) will -*definitely* change `foo[i]`. +region is a super-region **or** sub-region of R.* All we know about ``foo[i]`` +is that it is somewhere within ``foo``, so changing *anything* within ``foo`` +might change ``foo[i]``, and changing *all* of ``foo`` (or its base region) will +*definitely* change ``foo[i]``. -This logic could be improved by using the current constraints on `i`, at the +This logic could be improved by using the current constraints on ``i``, at the cost of speed. The latter case could also be improved by matching region kinds, -i.e. changing `foo[0].a` is unlikely to affect `foo[i].b`, no matter what `i` -is. +i.e. changing ``foo[0].a`` is unlikely to affect ``foo[i].b``, no matter what +``i`` is. -For more detail, read through RegionStoreManager::removeSubRegionBindings in +For more detail, read through ``RegionStoreManager::removeSubRegionBindings`` in RegionStore.cpp. ObjCIvarRegions -=============== +--------------- Objective-C instance variables require a bit of special handling. Like struct fields, they are not base regions, and when their parent object region is @@ -76,7 +84,7 @@ offsets start from the base region! Region Invalidation -=================== +------------------- Unlike binding invalidation, region invalidation occurs when the entire contents of a region may have changed---say, because it has been passed to a @@ -89,8 +97,8 @@ arithmetic. Region invalidation typically does even more than this, however. Because it usually represents the complete escape of a region from the analyzer's model, its *contents* must also be transitively invalidated. (For example, if a region -'p' of type 'int **' is invalidated, the contents of '*p' and '**p' may have -changed as well.) The algorithm that traverses this transitive closure of +``p`` of type ``int **`` is invalidated, the contents of ``*p`` and ``**p`` may +have changed as well.) The algorithm that traverses this transitive closure of accessible regions is known as ClusterAnalysis, and is also used for finding all live bindings in the store (in order to throw away the dead ones). The name "ClusterAnalysis" predates the cluster-based organization of bindings, but @@ -100,7 +108,7 @@ model of program behavior. Default Bindings -================ +---------------- Most bindings in RegionStore are simple scalar values -- integers and pointers. These are known as "Direct" bindings. However, RegionStore supports a second @@ -115,6 +123,8 @@ the base region is reached, at which point the RegionStore will pick an appropriate default value for the region (usually a symbolic value, but sometimes zero, for static data, or "uninitialized", for stack variables). +.. code-block:: cpp + int manyInts[10]; manyInts[1] = 42; // Creates a Direct binding for manyInts[1]. print(manyInts[1]); // Retrieves the Direct binding for manyInts[1]; @@ -132,7 +142,7 @@ for the sub-aggregate at offset 0. Lazy Bindings (LazyCompoundVal) -=============================== +------------------------------- RegionStore implements an optimization for copying aggregates (structs and arrays) called "lazy bindings", implemented using a special SVal called @@ -158,14 +168,16 @@ LazyCompoundVal region, and look up *that* region in the previous store. Here's a concrete example: - CGPoint p; - p.x = 42; // A Direct binding is made to the FieldRegion 'p.x'. - CGPoint p2 = p; // A LazyCompoundVal is created for 'p', along with a - // snapshot of the current store state. This value is then - // used as a Default binding for the VarRegion 'p2'. - return p2.x; // The binding for FieldRegion 'p2.x' is requested. - // There is no Direct binding, so we look for a Default - // binding to 'p2' and find the LCV. - // Because it's a LCV, we look at our requested region - // and see that it's the '.x' field. We ask for the value - // of 'p.x' within the snapshot, and get back 42. +.. code-block:: cpp + + CGPoint p; + p.x = 42; // A Direct binding is made to the FieldRegion 'p.x'. + CGPoint p2 = p; // A LazyCompoundVal is created for 'p', along with a + // snapshot of the current store state. This value is then + // used as a Default binding for the VarRegion 'p2'. + return p2.x; // The binding for FieldRegion 'p2.x' is requested. + // There is no Direct binding, so we look for a Default + // binding to 'p2' and find the LCV. + // Because it's a LCV, we look at our requested region + // and see that it's the '.x' field. We ask for the value + // of 'p.x' within the snapshot, and get back 42. diff --git a/docs/analyzer/nullability.rst b/docs/analyzer/developer-docs/nullability.rst similarity index 55% rename from docs/analyzer/nullability.rst rename to docs/analyzer/developer-docs/nullability.rst index 93909d0f25dee43e56ad90ebb91e51acceb59386..be6f473dbdf69024adfa5d4e785f62e9bc13290d 100644 --- a/docs/analyzer/nullability.rst +++ b/docs/analyzer/developer-docs/nullability.rst @@ -1,6 +1,6 @@ -============ +================== Nullability Checks -============ +================== This document is a high level description of the nullablility checks. These checks intended to use the annotations that is described in this @@ -8,85 +8,100 @@ RFC: http://lists.cs.uiuc.edu/pipermail/cfe-dev/2015-March/041798.html. Let's consider the following 2 categories: -1) nullable -============ +**1) nullable** -If a pointer 'p' has a nullable annotation and no explicit null check or assert, we should warn in the following cases: -- 'p' gets implicitly converted into nonnull pointer, for example, we are passing it to a function that takes a nonnull parameter. -- 'p' gets dereferenced +If a pointer ``p`` has a nullable annotation and no explicit null check or assert, we should warn in the following cases: + +* ``p`` gets implicitly converted into nonnull pointer, for example, we are passing it to a function that takes a nonnull parameter. +* ``p`` gets dereferenced Taking a branch on nullable pointers are the same like taking branch on null unspecified pointers. -Explicit cast from nullable to nonnul:: +Explicit cast from nullable to nonnul: + +.. code-block:: cpp - __nullable id foo; - id bar = foo; - takesNonNull((_nonnull) bar); <— should not warn here (backward compatibility hack) - anotherTakesNonNull(bar); <— would be great to warn here, but not necessary(*) + __nullable id foo; + id bar = foo; + takesNonNull((_nonnull) bar); // should not warn here (backward compatibility hack) + anotherTakesNonNull(bar); // would be great to warn here, but not necessary(*) Because bar corresponds to the same symbol all the time it is not easy to implement the checker that way the cast only suppress the first call but not the second. For this reason in the first implementation after a contradictory cast happens, I will treat bar as nullable unspecified, this way all of the warnings will be suppressed. Treating the symbol as nullable unspecified also has an advantage that in case the takesNonNull function body is being inlined, the will be no warning, when the symbol is dereferenced. In case I have time after the initial version I might spend additional time to try to find a more sophisticated solution, in which we would produce the second warning (*). -2) nonnull -============ - -- Dereferencing a nonnull, or sending message to it is ok. -- Converting nonnull to nullable is Ok. -- When there is an explicit cast from nonnull to nullable I will trust the cast (it is probable there for a reason, because this cast does not suppress any warnings or errors). -- But what should we do about null checks?:: - - __nonnull id takesNonnull(__nonnull id x) { - if (x == nil) { - // Defensive backward compatible code: - .... - return nil; <- Should the analyzer cover this piece of code? Should we require the cast (__nonnull)nil? - } - .... - } +**2) nonnull** + +* Dereferencing a nonnull, or sending message to it is ok. +* Converting nonnull to nullable is Ok. +* When there is an explicit cast from nonnull to nullable I will trust the cast (it is probable there for a reason, because this cast does not suppress any warnings or errors). +* But what should we do about null checks?: + +.. code-block:: cpp + + __nonnull id takesNonnull(__nonnull id x) { + if (x == nil) { + // Defensive backward compatible code: + .... + return nil; // Should the analyzer cover this piece of code? Should we require the cast (__nonnull)nil? + } + .... + } There are these directions: -- We can either take the branch; this way the branch is analyzed - - Should we not warn about any nullability issues in that branch? Probably not, it is ok to break the nullability postconditions when the nullability preconditions are violated. -- We can assume that these pointers are not null and we lose coverage with the analyzer. (This can be implemented either in constraint solver or in the checker itself.) + +* We can either take the branch; this way the branch is analyzed +* Should we not warn about any nullability issues in that branch? Probably not, it is ok to break the nullability postconditions when the nullability preconditions are violated. +* We can assume that these pointers are not null and we lose coverage with the analyzer. (This can be implemented either in constraint solver or in the checker itself.) Other Issues to keep in mind/take care of: -Messaging: -- Sending a message to a nullable pointer - - Even though the method might return a nonnull pointer, when it was sent to a nullable pointer the return type will be nullable. - - The result is nullable unless the receiver is known to be non null. -- Sending a message to a unspecified or nonnull pointer - - If the pointer is not assumed to be nil, we should be optimistic and use the nullability implied by the method. - - This will not happen automatically, since the AST will have null unspecified in this case. + +* Messaging: + + * Sending a message to a nullable pointer + + * Even though the method might return a nonnull pointer, when it was sent to a nullable pointer the return type will be nullable. + * The result is nullable unless the receiver is known to be non null. + + * Sending a message to a unspecified or nonnull pointer + + * If the pointer is not assumed to be nil, we should be optimistic and use the nullability implied by the method. + + * This will not happen automatically, since the AST will have null unspecified in this case. Inlining -============ +-------- -A symbol may need to be treated differently inside an inlined body. For example, consider these conversions from nonnull to nullable in presence of inlining:: +A symbol may need to be treated differently inside an inlined body. For example, consider these conversions from nonnull to nullable in presence of inlining: - id obj = getNonnull(); - takesNullable(obj); - takesNonnull(obj); - - void takesNullable(nullable id obj) { - obj->ivar // we should assume obj is nullable and warn here - } +.. code-block:: cpp + + id obj = getNonnull(); + takesNullable(obj); + takesNonnull(obj); + + void takesNullable(nullable id obj) { + obj->ivar // we should assume obj is nullable and warn here + } With no special treatment, when the takesNullable is inlined the analyzer will not warn when the obj symbol is dereferenced. One solution for this is to reanalyze takesNullable as a top level function to get possible violations. The alternative method, deducing nullability information from the arguments after inlining is not robust enough (for example there might be more parameters with different nullability, but in the given path the two parameters might end up being the same symbol or there can be nested functions that take different view of the nullability of the same symbol). So the symbol will remain nonnull to avoid false positives but the functions that takes nullable parameters will be analyzed separately as well without inlining. Annotations on multi level pointers -============ +----------------------------------- + +Tracking multiple levels of annotations for pointers pointing to pointers would make the checker more complicated, because this way a vector of nullability qualifiers would be needed to be tracked for each symbol. This is not a big caveat, since once the top level pointer is dereferenced, the symvol for the inner pointer will have the nullability information. The lack of multi level annotation tracking only observable, when multiple levels of pointers are passed to a function which has a parameter with multiple levels of annotations. So for now the checker support the top level nullability qualifiers only.: -Tracking multiple levels of annotations for pointers pointing to pointers would make the checker more complicated, because this way a vector of nullability qualifiers would be needed to be tracked for each symbol. This is not a big caveat, since once the top level pointer is dereferenced, the symvol for the inner pointer will have the nullability information. The lack of multi level annotation tracking only observable, when multiple levels of pointers are passed to a function which has a parameter with multiple levels of annotations. So for now the checker support the top level nullability qualifiers only.:: +.. code-block:: cpp - int * __nonnull * __nullable p; - int ** q = p; - takesStarNullableStarNullable(q); + int * __nonnull * __nullable p; + int ** q = p; + takesStarNullableStarNullable(q); Implementation notes -============ +-------------------- What to track? -- The checker would track memory regions, and to each relevant region a qualifier information would be attached which is either nullable, nonnull or null unspecified (or contradicted to suppress warnings for a specific region). -- On a branch, where a nullable pointer is known to be non null, the checker treat it as a same way as a pointer annotated as nonnull. -- When there is an explicit cast from a null unspecified to either nonnull or nullable I will trust the cast. -- Unannotated pointers are treated the same way as pointers annotated with nullability unspecified qualifier, unless the region is wrapped in ASSUME_NONNULL macros. -- We might want to implement a callback for entry points to top level functions, where the pointer nullability assumptions would be made. + +* The checker would track memory regions, and to each relevant region a qualifier information would be attached which is either nullable, nonnull or null unspecified (or contradicted to suppress warnings for a specific region). +* On a branch, where a nullable pointer is known to be non null, the checker treat it as a same way as a pointer annotated as nonnull. +* When there is an explicit cast from a null unspecified to either nonnull or nullable I will trust the cast. +* Unannotated pointers are treated the same way as pointers annotated with nullability unspecified qualifier, unless the region is wrapped in ASSUME_NONNULL macros. +* We might want to implement a callback for entry points to top level functions, where the pointer nullability assumptions would be made. diff --git a/docs/analyzer/index.rst b/docs/analyzer/index.rst deleted file mode 100644 index 767567f22fdc87377f09e320e73cf69c9abc9696..0000000000000000000000000000000000000000 --- a/docs/analyzer/index.rst +++ /dev/null @@ -1,23 +0,0 @@ -.. Clang Static Analyzer documentation master file, created by - sphinx-quickstart on Wed Jan 2 15:54:28 2013. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - -Welcome to Clang Static Analyzer's documentation! -================================================= - -Contents: - -.. toctree:: - :maxdepth: 2 - - DebugChecks - - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` - diff --git a/docs/conf.py b/docs/conf.py index 19113d0d5a70fb078c3767675786ac4879ce1dbe..dab70266d9d95bd947c7eb749c41135f14fa4db0 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -50,9 +50,9 @@ copyright = u'2007-%d, The Clang Team' % date.today().year # built documents. # # The short version. -version = '8' +version = '9' # The full version, including alpha/beta/rc tags. -release = '8' +release = '9' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. @@ -66,7 +66,7 @@ release = '8' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. -exclude_patterns = ['_build', 'analyzer'] +exclude_patterns = ['_build'] # The reST default role (used for this markup: `text`) to use for all documents. #default_role = None diff --git a/docs/index.rst b/docs/index.rst index 3eb1d160c756a3492535cd32af6ffab2b7d6a4b8..73468705bcf7bb57f46fe45027b5237d89fc1e57 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -23,6 +23,7 @@ Using Clang as a Compiler AttributeReference DiagnosticsReference CrossCompilation + ClangStaticAnalyzer ThreadSafetyAnalysis AddressSanitizer ThreadSanitizer diff --git a/docs/tools/dump_ast_matchers.py b/docs/tools/dump_ast_matchers.py index cae27b20a9705b834f2866b289f4e3588f8dce7c..c96c1ca27acb67d2e148488924ec698011eaedb9 100755 --- a/docs/tools/dump_ast_matchers.py +++ b/docs/tools/dump_ast_matchers.py @@ -5,7 +5,10 @@ import collections import re -import urllib2 +try: + from urllib.request import urlopen +except ImportError: + from urllib2 import urlopen MATCHERS_FILE = '../../include/clang/ASTMatchers/ASTMatchers.h' @@ -42,7 +45,7 @@ def esc(text): if url not in doxygen_probes: try: print('Probing %s...' % url) - urllib2.urlopen(url) + urlopen(url) doxygen_probes[url] = True except: doxygen_probes[url] = False diff --git a/docs/tools/dump_format_style.py b/docs/tools/dump_format_style.py index f2682edc7773718e0d559c5a2226317a1073a56f..5feb793a4d705178790a7f2d079a235a27c1b5ca 100755 --- a/docs/tools/dump_format_style.py +++ b/docs/tools/dump_format_style.py @@ -6,7 +6,6 @@ import collections import os import re -import urllib2 CLANG_DIR = os.path.join(os.path.dirname(__file__), '../..') FORMAT_STYLE_FILE = os.path.join(CLANG_DIR, 'include/clang/Format/Format.h') diff --git a/examples/AnnotateFunctions/AnnotateFunctions.cpp b/examples/AnnotateFunctions/AnnotateFunctions.cpp index 375f18f8e09ae0d8985b0e9190a93676a4217def..1ed7e9eda4816a1af2e751f994d6c473d99d5d0b 100644 --- a/examples/AnnotateFunctions/AnnotateFunctions.cpp +++ b/examples/AnnotateFunctions/AnnotateFunctions.cpp @@ -1,9 +1,8 @@ //===- AnnotateFunctions.cpp ----------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/examples/AnnotateFunctions/CMakeLists.txt b/examples/AnnotateFunctions/CMakeLists.txt index 5684abf2380d14ccea063a5629737560fc36cd36..44b6317e72afcb5507cdb234b7f9484750ea6cd7 100644 --- a/examples/AnnotateFunctions/CMakeLists.txt +++ b/examples/AnnotateFunctions/CMakeLists.txt @@ -1,4 +1,4 @@ -add_llvm_loadable_module(AnnotateFunctions AnnotateFunctions.cpp PLUGIN_TOOL clang) +add_llvm_library(AnnotateFunctions MODULE AnnotateFunctions.cpp PLUGIN_TOOL clang) if(LLVM_ENABLE_PLUGINS AND (WIN32 OR CYGWIN)) target_link_libraries(AnnotateFunctions PRIVATE diff --git a/examples/PrintFunctionNames/CMakeLists.txt b/examples/PrintFunctionNames/CMakeLists.txt index e582b2c45a8615f7d81f41bd149c22f5aee7a02b..68c6f76dff0544677679888a5b446b1c7eb586d6 100644 --- a/examples/PrintFunctionNames/CMakeLists.txt +++ b/examples/PrintFunctionNames/CMakeLists.txt @@ -9,7 +9,7 @@ if( NOT MSVC ) # MSVC mangles symbols differently, and endif() endif() -add_llvm_loadable_module(PrintFunctionNames PrintFunctionNames.cpp PLUGIN_TOOL clang) +add_llvm_library(PrintFunctionNames MODULE PrintFunctionNames.cpp PLUGIN_TOOL clang) if(LLVM_ENABLE_PLUGINS AND (WIN32 OR CYGWIN)) target_link_libraries(PrintFunctionNames PRIVATE diff --git a/examples/PrintFunctionNames/PrintFunctionNames.cpp b/examples/PrintFunctionNames/PrintFunctionNames.cpp index 9f6d495caec73bed3b71eb52f7ec62f7a0076ed6..e573ac93eb3eba4acb2c1dd28d7c006870142306 100644 --- a/examples/PrintFunctionNames/PrintFunctionNames.cpp +++ b/examples/PrintFunctionNames/PrintFunctionNames.cpp @@ -1,9 +1,8 @@ //===- PrintFunctionNames.cpp ---------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/examples/analyzer-plugin/CMakeLists.txt b/examples/analyzer-plugin/CMakeLists.txt index 0d5b2754cafec4c664175fae58cee1929d4b88f1..7c7b2aec1988ddb790956cf01f73e1209424bb36 100644 --- a/examples/analyzer-plugin/CMakeLists.txt +++ b/examples/analyzer-plugin/CMakeLists.txt @@ -1,5 +1,5 @@ set(LLVM_EXPORTED_SYMBOL_FILE ${CMAKE_CURRENT_SOURCE_DIR}/SampleAnalyzerPlugin.exports) -add_llvm_loadable_module(SampleAnalyzerPlugin MainCallChecker.cpp PLUGIN_TOOL clang) +add_llvm_library(SampleAnalyzerPlugin MODULE MainCallChecker.cpp PLUGIN_TOOL clang) if(LLVM_ENABLE_PLUGINS AND (WIN32 OR CYGWIN)) target_link_libraries(SampleAnalyzerPlugin PRIVATE diff --git a/examples/analyzer-plugin/MainCallChecker.cpp b/examples/analyzer-plugin/MainCallChecker.cpp index adb4e7da30ca0cd684737edbef70414838e239b0..77316d696de3074a5ffe6ff444b4ccac94ec8651 100644 --- a/examples/analyzer-plugin/MainCallChecker.cpp +++ b/examples/analyzer-plugin/MainCallChecker.cpp @@ -45,7 +45,9 @@ void MainCallChecker::checkPreStmt(const CallExpr *CE, CheckerContext &C) const // Register plugin! extern "C" void clang_registerCheckers (CheckerRegistry ®istry) { - registry.addChecker("example.MainCallChecker", "Disallows calls to functions called main"); + registry.addChecker( + "example.MainCallChecker", "Disallows calls to functions called main", + ""); } extern "C" diff --git a/examples/clang-interpreter/Test.cxx b/examples/clang-interpreter/Test.cxx index d39249214dc5ab2923e3aca547d7d757e89c3464..ed7fc86f9e5fcc945031091e60a7d1b215cc179e 100644 --- a/examples/clang-interpreter/Test.cxx +++ b/examples/clang-interpreter/Test.cxx @@ -1,9 +1,8 @@ //===-- examples/clang-interpreter/Test.cxx - Clang C Interpreter Example -===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/examples/clang-interpreter/main.cpp b/examples/clang-interpreter/main.cpp index 1c83b1d3e75fe47f0b5ee9dc1fde1dfb1084cf27..8fb52700a757ebeb16754a56045db56ac0e3b2ed 100644 --- a/examples/clang-interpreter/main.cpp +++ b/examples/clang-interpreter/main.cpp @@ -1,9 +1,8 @@ //===-- examples/clang-interpreter/main.cpp - Clang C Interpreter Example -===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/include/clang-c/BuildSystem.h b/include/clang-c/BuildSystem.h index 3cfec388308c1fb6878252cbbf80925ac1414de1..8f26a8611719fd0f5b1ba02edf4c06e6dd609645 100644 --- a/include/clang-c/BuildSystem.h +++ b/include/clang-c/BuildSystem.h @@ -1,9 +1,9 @@ /*==-- clang-c/BuildSystem.h - Utilities for use by build systems -*- C -*-===*\ |* *| -|* The LLVM Compiler Infrastructure *| -|* *| -|* This file is distributed under the University of Illinois Open Source *| -|* License. See LICENSE.TXT for details. *| +|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| +|* Exceptions. *| +|* See https://llvm.org/LICENSE.txt for license information. *| +|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| |* *| |*===----------------------------------------------------------------------===*| |* *| diff --git a/include/clang-c/CXCompilationDatabase.h b/include/clang-c/CXCompilationDatabase.h index 6f483ee28b567342748766c9c68b1a8e5440fe7b..2669c1a792c1199d988f07b17bc37995681b7912 100644 --- a/include/clang-c/CXCompilationDatabase.h +++ b/include/clang-c/CXCompilationDatabase.h @@ -1,9 +1,9 @@ /*===-- clang-c/CXCompilationDatabase.h - Compilation database ---*- C -*-===*\ |* *| -|* The LLVM Compiler Infrastructure *| -|* *| -|* This file is distributed under the University of Illinois Open Source *| -|* License. See LICENSE.TXT for details. *| +|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| +|* Exceptions. *| +|* See https://llvm.org/LICENSE.txt for license information. *| +|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| |* *| |*===----------------------------------------------------------------------===*| |* *| diff --git a/include/clang-c/CXErrorCode.h b/include/clang-c/CXErrorCode.h index caee48d7683233277a0dbf4c1fd8cea65ce75ee5..fed195ec1f33db240ce5ecd7cf4fbb8bf99fa652 100644 --- a/include/clang-c/CXErrorCode.h +++ b/include/clang-c/CXErrorCode.h @@ -1,9 +1,9 @@ /*===-- clang-c/CXErrorCode.h - C Index Error Codes --------------*- C -*-===*\ |* *| -|* The LLVM Compiler Infrastructure *| -|* *| -|* This file is distributed under the University of Illinois Open Source *| -|* License. See LICENSE.TXT for details. *| +|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| +|* Exceptions. *| +|* See https://llvm.org/LICENSE.txt for license information. *| +|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| |* *| |*===----------------------------------------------------------------------===*| |* *| diff --git a/include/clang-c/CXString.h b/include/clang-c/CXString.h index 76eeda180109bff086ec844b7ab47d8daa8edcab..1eb3442ccb24a4d100545f6e634e68599f8478bc 100644 --- a/include/clang-c/CXString.h +++ b/include/clang-c/CXString.h @@ -1,9 +1,9 @@ /*===-- clang-c/CXString.h - C Index strings --------------------*- C -*-===*\ |* *| -|* The LLVM Compiler Infrastructure *| -|* *| -|* This file is distributed under the University of Illinois Open Source *| -|* License. See LICENSE.TXT for details. *| +|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| +|* Exceptions. *| +|* See https://llvm.org/LICENSE.txt for license information. *| +|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| |* *| |*===----------------------------------------------------------------------===*| |* *| diff --git a/include/clang-c/Documentation.h b/include/clang-c/Documentation.h index 58c8af5aa47cf60966a35564acbbcb0781863bea..4af8c93a367ed07aeaada140f683d54be82c6458 100644 --- a/include/clang-c/Documentation.h +++ b/include/clang-c/Documentation.h @@ -1,9 +1,9 @@ /*==-- clang-c/Documentation.h - Utilities for comment processing -*- C -*-===*\ |* *| -|* The LLVM Compiler Infrastructure *| -|* *| -|* This file is distributed under the University of Illinois Open Source *| -|* License. See LICENSE.TXT for details. *| +|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| +|* Exceptions. *| +|* See https://llvm.org/LICENSE.txt for license information. *| +|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| |* *| |*===----------------------------------------------------------------------===*| |* *| diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h index c51dfb1598b99955e4a1c3c22ddaed70b332bc6f..38af8aa6d8b6c3783df76a6446d52452bff789f0 100644 --- a/include/clang-c/Index.h +++ b/include/clang-c/Index.h @@ -1,9 +1,9 @@ /*===-- clang-c/Index.h - Indexing Public C Interface -------------*- C -*-===*\ |* *| -|* The LLVM Compiler Infrastructure *| -|* *| -|* This file is distributed under the University of Illinois Open Source *| -|* License. See LICENSE.TXT for details. *| +|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| +|* Exceptions. *| +|* See https://llvm.org/LICENSE.txt for license information. *| +|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| |* *| |*===----------------------------------------------------------------------===*| |* *| @@ -32,7 +32,7 @@ * compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable. */ #define CINDEX_VERSION_MAJOR 0 -#define CINDEX_VERSION_MINOR 50 +#define CINDEX_VERSION_MINOR 51 #define CINDEX_VERSION_ENCODE(major, minor) ( \ ((major) * 10000) \ @@ -2586,7 +2586,8 @@ enum CXCursorKind { CXCursor_ObjCRuntimeVisible = 435, CXCursor_ObjCBoxable = 436, CXCursor_FlagEnum = 437, - CXCursor_LastAttr = CXCursor_FlagEnum, + CXCursor_ConvergentAttr = 438, + CXCursor_LastAttr = CXCursor_ConvergentAttr, /* Preprocessing */ CXCursor_PreprocessingDirective = 500, diff --git a/include/clang-c/Platform.h b/include/clang-c/Platform.h index e2a4dccbdaf086ab775fb0daa1397fa9563823b3..5284b533253d02a95136160e50f1b399e446a5a2 100644 --- a/include/clang-c/Platform.h +++ b/include/clang-c/Platform.h @@ -1,9 +1,9 @@ /*===-- clang-c/Platform.h - C Index platform decls -------------*- C -*-===*\ |* *| -|* The LLVM Compiler Infrastructure *| -|* *| -|* This file is distributed under the University of Illinois Open Source *| -|* License. See LICENSE.TXT for details. *| +|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| +|* Exceptions. *| +|* See https://llvm.org/LICENSE.txt for license information. *| +|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| |* *| |*===----------------------------------------------------------------------===*| |* *| diff --git a/include/clang/ARCMigrate/ARCMT.h b/include/clang/ARCMigrate/ARCMT.h index 30c24f1cdb10e4cc09cc2d5c302ddb5d111baeaa..49e94a92cd0bc1fcaac2c38db0aa79c3c13868bc 100644 --- a/include/clang/ARCMigrate/ARCMT.h +++ b/include/clang/ARCMigrate/ARCMT.h @@ -1,9 +1,8 @@ //===-- ARCMT.h - ARC Migration Rewriter ------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/include/clang/ARCMigrate/ARCMTActions.h b/include/clang/ARCMigrate/ARCMTActions.h index 2571ca75be515996cf63a0c729035e5a5ea0724b..641c259b3867725c14f9a52843ab617d45320a7a 100644 --- a/include/clang/ARCMigrate/ARCMTActions.h +++ b/include/clang/ARCMigrate/ARCMTActions.h @@ -1,9 +1,8 @@ //===--- ARCMTActions.h - ARC Migrate Tool Frontend Actions -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/include/clang/ARCMigrate/FileRemapper.h b/include/clang/ARCMigrate/FileRemapper.h index 731307f24e224faa5f25574f313b4d7d0f6b3aeb..76b65b2f6884c911601964e74d08c59978914aad 100644 --- a/include/clang/ARCMigrate/FileRemapper.h +++ b/include/clang/ARCMigrate/FileRemapper.h @@ -1,9 +1,8 @@ //===-- FileRemapper.h - File Remapping Helper ------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/include/clang/AST/APValue.h b/include/clang/AST/APValue.h index d4057c9da5f381dad331ceae47253aef101c4723..5d26a11177c072aa5dfe59dd6be4e6dbe4c3b92d 100644 --- a/include/clang/AST/APValue.h +++ b/include/clang/AST/APValue.h @@ -1,9 +1,8 @@ //===--- APValue.h - Union class for APFloat/APSInt/Complex -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -14,6 +13,7 @@ #ifndef LLVM_CLANG_AST_APVALUE_H #define LLVM_CLANG_AST_APVALUE_H +#include "clang/Basic/FixedPoint.h" #include "clang/Basic/LLVM.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/APSInt.h" @@ -43,6 +43,7 @@ public: Uninitialized, Int, Float, + FixedPoint, ComplexInt, ComplexFloat, LValue, @@ -175,6 +176,9 @@ public: explicit APValue(APFloat F) : Kind(Uninitialized) { MakeFloat(); setFloat(std::move(F)); } + explicit APValue(APFixedPoint FX) : Kind(Uninitialized) { + MakeFixedPoint(std::move(FX)); + } explicit APValue(const APValue *E, unsigned N) : Kind(Uninitialized) { MakeVector(); setVector(E, N); } @@ -233,6 +237,7 @@ public: bool isUninit() const { return Kind == Uninitialized; } bool isInt() const { return Kind == Int; } bool isFloat() const { return Kind == Float; } + bool isFixedPoint() const { return Kind == FixedPoint; } bool isComplexInt() const { return Kind == ComplexInt; } bool isComplexFloat() const { return Kind == ComplexFloat; } bool isLValue() const { return Kind == LValue; } @@ -265,6 +270,14 @@ public: return const_cast(this)->getFloat(); } + APFixedPoint &getFixedPoint() { + assert(isFixedPoint() && "Invalid accessor"); + return *(APFixedPoint *)(char *)Data.buffer; + } + const APFixedPoint &getFixedPoint() const { + return const_cast(this)->getFixedPoint(); + } + APSInt &getComplexIntReal() { assert(isComplexInt() && "Invalid accessor"); return ((ComplexAPSInt*)(char*)Data.buffer)->Real; @@ -406,6 +419,10 @@ public: assert(isFloat() && "Invalid accessor"); *(APFloat *)(char *)Data.buffer = std::move(F); } + void setFixedPoint(APFixedPoint FX) { + assert(isFixedPoint() && "Invalid accessor"); + *(APFixedPoint *)(char *)Data.buffer = std::move(FX); + } void setVector(const APValue *E, unsigned N) { assert(isVector() && "Invalid accessor"); ((Vec*)(char*)Data.buffer)->Elts = new APValue[N]; @@ -465,6 +482,11 @@ private: new ((void*)(char*)Data.buffer) APFloat(0.0); Kind = Float; } + void MakeFixedPoint(APFixedPoint &&FX) { + assert(isUninit() && "Bad state change"); + new ((void *)(char *)Data.buffer) APFixedPoint(std::move(FX)); + Kind = FixedPoint; + } void MakeVector() { assert(isUninit() && "Bad state change"); new ((void*)(char*)Data.buffer) Vec(); diff --git a/include/clang/AST/AST.h b/include/clang/AST/AST.h index 6db351d1064b66dec7ae9232bd5638ae467903ce..6d0f274121b25024c3d8db907fc65b54dfe9fc17 100644 --- a/include/clang/AST/AST.h +++ b/include/clang/AST/AST.h @@ -1,9 +1,8 @@ //===--- AST.h - "Umbrella" header for AST library --------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/include/clang/AST/ASTConsumer.h b/include/clang/AST/ASTConsumer.h index 1167c566a35f3e59867cdbb493b9c643716c42fd..dc216a89c205f7d5e61bf91ff2f8f78b1ed9c990 100644 --- a/include/clang/AST/ASTConsumer.h +++ b/include/clang/AST/ASTConsumer.h @@ -1,9 +1,8 @@ //===--- ASTConsumer.h - Abstract interface for reading ASTs ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 7edf3b3fed74164daa637564015cb639736acae1..fe52f818ea40213cd9f65e92a1b706634b9f977b 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -1,9 +1,8 @@ //===- ASTContext.h - Context to hold long-lived AST nodes ------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -15,6 +14,7 @@ #ifndef LLVM_CLANG_AST_ASTCONTEXT_H #define LLVM_CLANG_AST_ASTCONTEXT_H +#include "clang/AST/ASTContextAllocate.h" #include "clang/AST/ASTTypeTraits.h" #include "clang/AST/CanonicalType.h" #include "clang/AST/CommentCommandTraits.h" @@ -2002,6 +2002,9 @@ public: /// No error GE_None, + /// Missing a type + GE_Missing_type, + /// Missing a type from GE_Missing_stdio, @@ -2085,6 +2088,16 @@ public: CharUnits getTypeSizeInChars(QualType T) const; CharUnits getTypeSizeInChars(const Type *T) const; + Optional getTypeSizeInCharsIfKnown(QualType Ty) const { + if (Ty->isIncompleteType() || Ty->isDependentType()) + return None; + return getTypeSizeInChars(Ty); + } + + Optional getTypeSizeInCharsIfKnown(const Type *Ty) const { + return getTypeSizeInCharsIfKnown(QualType(Ty, 0)); + } + /// Return the ABI-specified alignment of a (complete) type \p T, in /// bits. unsigned getTypeAlign(QualType T) const { return getTypeInfo(T).Align; } @@ -2623,6 +2636,12 @@ public: // corresponding saturated type for a given fixed point type. QualType getCorrespondingSaturatedType(QualType Ty) const; + // This method accepts fixed point types and returns the corresponding signed + // type. Unlike getCorrespondingUnsignedType(), this only accepts unsigned + // fixed point types because there are unsigned integer types like bool and + // char8_t that don't have signed equivalents. + QualType getCorrespondingSignedFixedPointType(QualType Ty) const; + //===--------------------------------------------------------------------===// // Integer Values //===--------------------------------------------------------------------===// @@ -2969,8 +2988,8 @@ inline Selector GetUnarySelector(StringRef name, ASTContext &Ctx) { /// This placement form of operator new uses the ASTContext's allocator for /// obtaining memory. /// -/// IMPORTANT: These are also declared in clang/AST/AttrIterator.h! Any changes -/// here need to also be made there. +/// IMPORTANT: These are also declared in clang/AST/ASTContextAllocate.h! +/// Any changes here need to also be made there. /// /// We intentionally avoid using a nothrow specification here so that the calls /// to this operator will not perform a null check on the result -- the @@ -2993,7 +3012,7 @@ inline Selector GetUnarySelector(StringRef name, ASTContext &Ctx) { /// allocator supports it). /// @return The allocated memory. Could be nullptr. inline void *operator new(size_t Bytes, const clang::ASTContext &C, - size_t Alignment) { + size_t Alignment /* = 8 */) { return C.Allocate(Bytes, Alignment); } @@ -3031,7 +3050,7 @@ inline void operator delete(void *Ptr, const clang::ASTContext &C, size_t) { /// allocator supports it). /// @return The allocated memory. Could be nullptr. inline void *operator new[](size_t Bytes, const clang::ASTContext& C, - size_t Alignment = 8) { + size_t Alignment /* = 8 */) { return C.Allocate(Bytes, Alignment); } diff --git a/include/clang/AST/ASTContextAllocate.h b/include/clang/AST/ASTContextAllocate.h new file mode 100644 index 0000000000000000000000000000000000000000..70c8e24f9185bf791604e35d1ffe6a6775a0bb3f --- /dev/null +++ b/include/clang/AST/ASTContextAllocate.h @@ -0,0 +1,37 @@ +//===- ASTContextAllocate.h - ASTContext allocate functions -----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file declares ASTContext allocation functions separate from the main +// code in ASTContext.h. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_ASTCONTEXTALLOCATE_H +#define LLVM_CLANG_AST_ASTCONTEXTALLOCATE_H + +#include + +namespace clang { + +class ASTContext; + +} // namespace clang + +// Defined in ASTContext.h +void *operator new(size_t Bytes, const clang::ASTContext &C, + size_t Alignment = 8); +void *operator new[](size_t Bytes, const clang::ASTContext &C, + size_t Alignment = 8); + +// It is good practice to pair new/delete operators. Also, MSVC gives many +// warnings if a matching delete overload is not declared, even though the +// throw() spec guarantees it will not be implicitly called. +void operator delete(void *Ptr, const clang::ASTContext &C, size_t); +void operator delete[](void *Ptr, const clang::ASTContext &C, size_t); + +#endif // LLVM_CLANG_AST_ASTCONTEXTALLOCATE_H diff --git a/include/clang/AST/ASTDiagnostic.h b/include/clang/AST/ASTDiagnostic.h index fe92604587ef72892fee3f7d1a939561a860c98d..d6549e12d92acfe362f740598defbc5718e595f0 100644 --- a/include/clang/AST/ASTDiagnostic.h +++ b/include/clang/AST/ASTDiagnostic.h @@ -1,9 +1,8 @@ //===--- ASTDiagnostic.h - Diagnostics for the AST library ------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/include/clang/AST/ASTDumperUtils.h b/include/clang/AST/ASTDumperUtils.h index 129c40ce3e148b6559363cd03fe0d276ea5adfe0..3e263dfae174c03559d654fe2d4a62ae268770fa 100644 --- a/include/clang/AST/ASTDumperUtils.h +++ b/include/clang/AST/ASTDumperUtils.h @@ -1,9 +1,8 @@ //===--- ASTDumperUtils.h - Printing of AST nodes -------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -14,7 +13,6 @@ #ifndef LLVM_CLANG_AST_ASTDUMPERUTILS_H #define LLVM_CLANG_AST_ASTDUMPERUTILS_H -#include "clang/AST/ASTContext.h" #include "llvm/Support/raw_ostream.h" namespace clang { @@ -23,7 +21,7 @@ namespace clang { // Do not use bold yellow for any text. It is hard to read on white screens. struct TerminalColor { - raw_ostream::Colors Color; + llvm::raw_ostream::Colors Color; bool Bold; }; @@ -38,50 +36,51 @@ struct TerminalColor { // Bold Cyan - ValueColor, DeclNameColor // Decl kind names (VarDecl, FunctionDecl, etc) -static const TerminalColor DeclKindNameColor = {raw_ostream::GREEN, true}; +static const TerminalColor DeclKindNameColor = {llvm::raw_ostream::GREEN, true}; // Attr names (CleanupAttr, GuardedByAttr, etc) -static const TerminalColor AttrColor = {raw_ostream::BLUE, true}; +static const TerminalColor AttrColor = {llvm::raw_ostream::BLUE, true}; // Statement names (DeclStmt, ImplicitCastExpr, etc) -static const TerminalColor StmtColor = {raw_ostream::MAGENTA, true}; +static const TerminalColor StmtColor = {llvm::raw_ostream::MAGENTA, true}; // Comment names (FullComment, ParagraphComment, TextComment, etc) -static const TerminalColor CommentColor = {raw_ostream::BLUE, false}; +static const TerminalColor CommentColor = {llvm::raw_ostream::BLUE, false}; // Type names (int, float, etc, plus user defined types) -static const TerminalColor TypeColor = {raw_ostream::GREEN, false}; +static const TerminalColor TypeColor = {llvm::raw_ostream::GREEN, false}; // Pointer address -static const TerminalColor AddressColor = {raw_ostream::YELLOW, false}; +static const TerminalColor AddressColor = {llvm::raw_ostream::YELLOW, false}; // Source locations -static const TerminalColor LocationColor = {raw_ostream::YELLOW, false}; +static const TerminalColor LocationColor = {llvm::raw_ostream::YELLOW, false}; // lvalue/xvalue -static const TerminalColor ValueKindColor = {raw_ostream::CYAN, false}; +static const TerminalColor ValueKindColor = {llvm::raw_ostream::CYAN, false}; // bitfield/objcproperty/objcsubscript/vectorcomponent -static const TerminalColor ObjectKindColor = {raw_ostream::CYAN, false}; +static const TerminalColor ObjectKindColor = {llvm::raw_ostream::CYAN, false}; // Null statements -static const TerminalColor NullColor = {raw_ostream::BLUE, false}; +static const TerminalColor NullColor = {llvm::raw_ostream::BLUE, false}; // Undeserialized entities -static const TerminalColor UndeserializedColor = {raw_ostream::GREEN, true}; +static const TerminalColor UndeserializedColor = {llvm::raw_ostream::GREEN, + true}; // CastKind from CastExpr's -static const TerminalColor CastColor = {raw_ostream::RED, false}; +static const TerminalColor CastColor = {llvm::raw_ostream::RED, false}; // Value of the statement -static const TerminalColor ValueColor = {raw_ostream::CYAN, true}; +static const TerminalColor ValueColor = {llvm::raw_ostream::CYAN, true}; // Decl names -static const TerminalColor DeclNameColor = {raw_ostream::CYAN, true}; +static const TerminalColor DeclNameColor = {llvm::raw_ostream::CYAN, true}; // Indents ( `, -. | ) -static const TerminalColor IndentColor = {raw_ostream::BLUE, false}; +static const TerminalColor IndentColor = {llvm::raw_ostream::BLUE, false}; class ColorScope { - raw_ostream &OS; + llvm::raw_ostream &OS; const bool ShowColors; public: - ColorScope(raw_ostream &OS, bool ShowColors, TerminalColor Color) + ColorScope(llvm::raw_ostream &OS, bool ShowColors, TerminalColor Color) : OS(OS), ShowColors(ShowColors) { if (ShowColors) OS.changeColor(Color.Color, Color.Bold); @@ -92,90 +91,6 @@ public: } }; -class TextTreeStructure { - raw_ostream &OS; - const bool ShowColors; - - /// Pending[i] is an action to dump an entity at level i. - llvm::SmallVector, 32> Pending; - - /// Indicates whether we're at the top level. - bool TopLevel = true; - - /// Indicates if we're handling the first child after entering a new depth. - bool FirstChild = true; - - /// Prefix for currently-being-dumped entity. - std::string Prefix; - -public: - /// Add a child of the current node. Calls doAddChild without arguments - template void addChild(Fn doAddChild) { - // If we're at the top level, there's nothing interesting to do; just - // run the dumper. - if (TopLevel) { - TopLevel = false; - doAddChild(); - while (!Pending.empty()) { - Pending.back()(true); - Pending.pop_back(); - } - Prefix.clear(); - OS << "\n"; - TopLevel = true; - return; - } - - auto dumpWithIndent = [this, doAddChild](bool isLastChild) { - // Print out the appropriate tree structure and work out the prefix for - // children of this node. For instance: - // - // A Prefix = "" - // |-B Prefix = "| " - // | `-C Prefix = "| " - // `-D Prefix = " " - // |-E Prefix = " | " - // `-F Prefix = " " - // G Prefix = "" - // - // Note that the first level gets no prefix. - { - OS << '\n'; - ColorScope Color(OS, ShowColors, IndentColor); - OS << Prefix << (isLastChild ? '`' : '|') << '-'; - this->Prefix.push_back(isLastChild ? ' ' : '|'); - this->Prefix.push_back(' '); - } - - FirstChild = true; - unsigned Depth = Pending.size(); - - doAddChild(); - - // If any children are left, they're the last at their nesting level. - // Dump those ones out now. - while (Depth < Pending.size()) { - Pending.back()(true); - this->Pending.pop_back(); - } - - // Restore the old prefix. - this->Prefix.resize(Prefix.size() - 2); - }; - - if (FirstChild) { - Pending.push_back(std::move(dumpWithIndent)); - } else { - Pending.back()(false); - Pending.back() = std::move(dumpWithIndent); - } - FirstChild = false; - } - - TextTreeStructure(raw_ostream &OS, bool ShowColors) - : OS(OS), ShowColors(ShowColors) {} -}; - } // namespace clang #endif // LLVM_CLANG_AST_ASTDUMPERUTILS_H diff --git a/include/clang/AST/ASTFwd.h b/include/clang/AST/ASTFwd.h index 038d5c3d3611569ae5bc428dfc43deafaf762c87..93919bbdd52f5c5e6878df6cc31ae7ffeb83c617 100644 --- a/include/clang/AST/ASTFwd.h +++ b/include/clang/AST/ASTFwd.h @@ -1,9 +1,8 @@ //===--- ASTFwd.h ----------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===--------------------------------------------------------------===// /// diff --git a/include/clang/AST/ASTImporter.h b/include/clang/AST/ASTImporter.h index dbb9cf35ddead643abd74f1867ad56262bad04e0..dd872b1123bfe9abb2460cbc1ba211557c8f8410 100644 --- a/include/clang/AST/ASTImporter.h +++ b/include/clang/AST/ASTImporter.h @@ -1,9 +1,8 @@ //===- ASTImporter.h - Importing ASTs from other Contexts -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/include/clang/AST/ASTImporterLookupTable.h b/include/clang/AST/ASTImporterLookupTable.h index 14cafe817ddc8275b5725459271298140f1a60d0..407478a51058d523c352634a8d317fb356af1a9b 100644 --- a/include/clang/AST/ASTImporterLookupTable.h +++ b/include/clang/AST/ASTImporterLookupTable.h @@ -1,9 +1,8 @@ //===- ASTImporterLookupTable.h - ASTImporter specific lookup--*- C++ -*---===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/include/clang/AST/ASTLambda.h b/include/clang/AST/ASTLambda.h index 6fedcb8d3801115b8e90352406c8ef2b930d7935..c1153168e41bb8ad5bf8ed68000e190da00b50b2 100644 --- a/include/clang/AST/ASTLambda.h +++ b/include/clang/AST/ASTLambda.h @@ -1,9 +1,8 @@ //===--- ASTLambda.h - Lambda Helper Functions --------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /// diff --git a/include/clang/AST/ASTMutationListener.h b/include/clang/AST/ASTMutationListener.h index 80184e1cc7402af1ce7f05fe02cbb1b61867fadc..ac115d4efcd8dac8e17f3d68a4166828b4b7cfae 100644 --- a/include/clang/AST/ASTMutationListener.h +++ b/include/clang/AST/ASTMutationListener.h @@ -1,9 +1,8 @@ //===--- ASTMutationListener.h - AST Mutation Interface --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/include/clang/AST/ASTNodeTraverser.h b/include/clang/AST/ASTNodeTraverser.h new file mode 100644 index 0000000000000000000000000000000000000000..44c6f54e246d7e0a4848930e79aeff5bad13d466 --- /dev/null +++ b/include/clang/AST/ASTNodeTraverser.h @@ -0,0 +1,621 @@ +//===--- ASTNodeTraverser.h - Traversal of AST nodes ----------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements the AST traversal facilities. Other users +// of this class may make use of the same traversal logic by inheriting it, +// similar to RecursiveASTVisitor. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_ASTNODETRAVERSER_H +#define LLVM_CLANG_AST_ASTNODETRAVERSER_H + +#include "clang/AST/AttrVisitor.h" +#include "clang/AST/CommentVisitor.h" +#include "clang/AST/DeclVisitor.h" +#include "clang/AST/LocInfoType.h" +#include "clang/AST/StmtVisitor.h" +#include "clang/AST/TemplateArgumentVisitor.h" +#include "clang/AST/TypeVisitor.h" + +namespace clang { + +/** + +ASTNodeTraverser traverses the Clang AST for dumping purposes. + +The `Derived::doGetNodeDelegate()` method is required to be an accessible member +which returns a reference of type `NodeDelegateType &` which implements the +following interface: + +struct { + template void AddChild(Fn DoAddChild); + template void AddChild(StringRef Label, Fn DoAddChild); + + void Visit(const comments::Comment *C, const comments::FullComment *FC); + void Visit(const Attr *A); + void Visit(const TemplateArgument &TA, SourceRange R = {}, + const Decl *From = nullptr, StringRef Label = {}); + void Visit(const Stmt *Node); + void Visit(const Type *T); + void Visit(QualType T); + void Visit(const Decl *D); + void Visit(const CXXCtorInitializer *Init); + void Visit(const OMPClause *C); + void Visit(const BlockDecl::Capture &C); + void Visit(const GenericSelectionExpr::ConstAssociation &A); +}; +*/ +template +class ASTNodeTraverser + : public ConstDeclVisitor, + public ConstStmtVisitor, + public comments::ConstCommentVisitor, + public TypeVisitor, + public ConstAttrVisitor, + public ConstTemplateArgumentVisitor { + + /// Indicates whether we should trigger deserialization of nodes that had + /// not already been loaded. + bool Deserialize = false; + + NodeDelegateType &getNodeDelegate() { + return getDerived().doGetNodeDelegate(); + } + Derived &getDerived() { return *static_cast(this); } + +public: + void setDeserialize(bool D) { Deserialize = D; } + bool getDeserialize() const { return Deserialize; } + + void Visit(const Decl *D) { + getNodeDelegate().AddChild([=] { + getNodeDelegate().Visit(D); + if (!D) + return; + + ConstDeclVisitor::Visit(D); + + for (const auto &A : D->attrs()) + Visit(A); + + if (const comments::FullComment *Comment = + D->getASTContext().getLocalCommentForDeclUncached(D)) + Visit(Comment, Comment); + + // Decls within functions are visited by the body. + if (!isa(*D) && !isa(*D)) { + if (const auto *DC = dyn_cast(D)) + dumpDeclContext(DC); + } + }); + } + + void Visit(const Stmt *S, StringRef Label = {}) { + getNodeDelegate().AddChild(Label, [=] { + getNodeDelegate().Visit(S); + + if (!S) { + return; + } + + ConstStmtVisitor::Visit(S); + + // Some statements have custom mechanisms for dumping their children. + if (isa(S) || isa(S)) { + return; + } + + for (const Stmt *SubStmt : S->children()) + Visit(SubStmt); + }); + } + + void Visit(QualType T) { + SplitQualType SQT = T.split(); + if (!SQT.Quals.hasQualifiers()) + return Visit(SQT.Ty); + + getNodeDelegate().AddChild([=] { + getNodeDelegate().Visit(T); + Visit(T.split().Ty); + }); + } + + void Visit(const Type *T) { + getNodeDelegate().AddChild([=] { + getNodeDelegate().Visit(T); + if (!T) + return; + TypeVisitor::Visit(T); + + QualType SingleStepDesugar = + T->getLocallyUnqualifiedSingleStepDesugaredType(); + if (SingleStepDesugar != QualType(T, 0)) + Visit(SingleStepDesugar); + }); + } + + void Visit(const Attr *A) { + getNodeDelegate().AddChild([=] { + getNodeDelegate().Visit(A); + ConstAttrVisitor::Visit(A); + }); + } + + void Visit(const CXXCtorInitializer *Init) { + getNodeDelegate().AddChild([=] { + getNodeDelegate().Visit(Init); + Visit(Init->getInit()); + }); + } + + void Visit(const TemplateArgument &A, SourceRange R = {}, + const Decl *From = nullptr, const char *Label = nullptr) { + getNodeDelegate().AddChild([=] { + getNodeDelegate().Visit(A, R, From, Label); + ConstTemplateArgumentVisitor::Visit(A); + }); + } + + void Visit(const BlockDecl::Capture &C) { + getNodeDelegate().AddChild([=] { + getNodeDelegate().Visit(C); + if (C.hasCopyExpr()) + Visit(C.getCopyExpr()); + }); + } + + void Visit(const OMPClause *C) { + getNodeDelegate().AddChild([=] { + getNodeDelegate().Visit(C); + for (const auto *S : C->children()) + Visit(S); + }); + } + + void Visit(const GenericSelectionExpr::ConstAssociation &A) { + getNodeDelegate().AddChild([=] { + getNodeDelegate().Visit(A); + if (const TypeSourceInfo *TSI = A.getTypeSourceInfo()) + Visit(TSI->getType()); + Visit(A.getAssociationExpr()); + }); + } + + void Visit(const comments::Comment *C, const comments::FullComment *FC) { + getNodeDelegate().AddChild([=] { + getNodeDelegate().Visit(C, FC); + if (!C) { + return; + } + comments::ConstCommentVisitor::visit(C, + FC); + for (comments::Comment::child_iterator I = C->child_begin(), + E = C->child_end(); + I != E; ++I) + Visit(*I, FC); + }); + } + + void dumpDeclContext(const DeclContext *DC) { + if (!DC) + return; + + for (const auto *D : (Deserialize ? DC->decls() : DC->noload_decls())) + Visit(D); + } + + void dumpTemplateParameters(const TemplateParameterList *TPL) { + if (!TPL) + return; + + for (const auto &TP : *TPL) + Visit(TP); + } + + void dumpTemplateArgumentListInfo(const TemplateArgumentListInfo &TALI) { + for (const auto &TA : TALI.arguments()) + dumpTemplateArgumentLoc(TA); + } + + void dumpTemplateArgumentLoc(const TemplateArgumentLoc &A, + const Decl *From = nullptr, + const char *Label = nullptr) { + Visit(A.getArgument(), A.getSourceRange(), From, Label); + } + + void dumpTemplateArgumentList(const TemplateArgumentList &TAL) { + for (unsigned i = 0, e = TAL.size(); i < e; ++i) + Visit(TAL[i]); + } + + void dumpObjCTypeParamList(const ObjCTypeParamList *typeParams) { + if (!typeParams) + return; + + for (const auto &typeParam : *typeParams) { + Visit(typeParam); + } + } + + void VisitComplexType(const ComplexType *T) { Visit(T->getElementType()); } + void VisitLocInfoType(const LocInfoType *T) { + Visit(T->getTypeSourceInfo()->getType()); + } + void VisitPointerType(const PointerType *T) { Visit(T->getPointeeType()); } + void VisitBlockPointerType(const BlockPointerType *T) { + Visit(T->getPointeeType()); + } + void VisitReferenceType(const ReferenceType *T) { + Visit(T->getPointeeType()); + } + void VisitMemberPointerType(const MemberPointerType *T) { + Visit(T->getClass()); + Visit(T->getPointeeType()); + } + void VisitArrayType(const ArrayType *T) { Visit(T->getElementType()); } + void VisitVariableArrayType(const VariableArrayType *T) { + VisitArrayType(T); + Visit(T->getSizeExpr()); + } + void VisitDependentSizedArrayType(const DependentSizedArrayType *T) { + Visit(T->getElementType()); + Visit(T->getSizeExpr()); + } + void VisitDependentSizedExtVectorType(const DependentSizedExtVectorType *T) { + Visit(T->getElementType()); + Visit(T->getSizeExpr()); + } + void VisitVectorType(const VectorType *T) { Visit(T->getElementType()); } + void VisitFunctionType(const FunctionType *T) { Visit(T->getReturnType()); } + void VisitFunctionProtoType(const FunctionProtoType *T) { + VisitFunctionType(T); + for (const QualType &PT : T->getParamTypes()) + Visit(PT); + } + void VisitTypeOfExprType(const TypeOfExprType *T) { + Visit(T->getUnderlyingExpr()); + } + void VisitDecltypeType(const DecltypeType *T) { + Visit(T->getUnderlyingExpr()); + } + void VisitUnaryTransformType(const UnaryTransformType *T) { + Visit(T->getBaseType()); + } + void VisitAttributedType(const AttributedType *T) { + // FIXME: AttrKind + Visit(T->getModifiedType()); + } + void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T) { + Visit(T->getReplacedParameter()); + } + void + VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType *T) { + Visit(T->getReplacedParameter()); + Visit(T->getArgumentPack()); + } + void VisitTemplateSpecializationType(const TemplateSpecializationType *T) { + for (const auto &Arg : *T) + Visit(Arg); + if (T->isTypeAlias()) + Visit(T->getAliasedType()); + } + void VisitObjCObjectPointerType(const ObjCObjectPointerType *T) { + Visit(T->getPointeeType()); + } + void VisitAtomicType(const AtomicType *T) { Visit(T->getValueType()); } + void VisitPipeType(const PipeType *T) { Visit(T->getElementType()); } + void VisitAdjustedType(const AdjustedType *T) { Visit(T->getOriginalType()); } + void VisitPackExpansionType(const PackExpansionType *T) { + if (!T->isSugared()) + Visit(T->getPattern()); + } + // FIXME: ElaboratedType, DependentNameType, + // DependentTemplateSpecializationType, ObjCObjectType + + void VisitTypedefDecl(const TypedefDecl *D) { Visit(D->getUnderlyingType()); } + + void VisitEnumConstantDecl(const EnumConstantDecl *D) { + if (const Expr *Init = D->getInitExpr()) + Visit(Init); + } + + void VisitFunctionDecl(const FunctionDecl *D) { + if (const auto *FTSI = D->getTemplateSpecializationInfo()) + dumpTemplateArgumentList(*FTSI->TemplateArguments); + + if (D->param_begin()) + for (const auto *Parameter : D->parameters()) + Visit(Parameter); + + if (const auto *C = dyn_cast(D)) + for (const auto *I : C->inits()) + Visit(I); + + if (D->doesThisDeclarationHaveABody()) + Visit(D->getBody()); + } + + void VisitFieldDecl(const FieldDecl *D) { + if (D->isBitField()) + Visit(D->getBitWidth()); + if (Expr *Init = D->getInClassInitializer()) + Visit(Init); + } + + void VisitVarDecl(const VarDecl *D) { + if (D->hasInit()) + Visit(D->getInit()); + } + + void VisitDecompositionDecl(const DecompositionDecl *D) { + VisitVarDecl(D); + for (const auto *B : D->bindings()) + Visit(B); + } + + void VisitBindingDecl(const BindingDecl *D) { + if (const auto *E = D->getBinding()) + Visit(E); + } + + void VisitFileScopeAsmDecl(const FileScopeAsmDecl *D) { + Visit(D->getAsmString()); + } + + void VisitCapturedDecl(const CapturedDecl *D) { Visit(D->getBody()); } + + void VisitOMPThreadPrivateDecl(const OMPThreadPrivateDecl *D) { + for (const auto *E : D->varlists()) + Visit(E); + } + + void VisitOMPDeclareReductionDecl(const OMPDeclareReductionDecl *D) { + Visit(D->getCombiner()); + if (const auto *Initializer = D->getInitializer()) + Visit(Initializer); + } + + void VisitOMPDeclareMapperDecl(const OMPDeclareMapperDecl *D) { + for (const auto *C : D->clauselists()) + Visit(C); + } + + void VisitOMPCapturedExprDecl(const OMPCapturedExprDecl *D) { + Visit(D->getInit()); + } + + template + void dumpTemplateDeclSpecialization(const SpecializationDecl *D) { + for (const auto *RedeclWithBadType : D->redecls()) { + // FIXME: The redecls() range sometimes has elements of a less-specific + // type. (In particular, ClassTemplateSpecializationDecl::redecls() gives + // us TagDecls, and should give CXXRecordDecls). + auto *Redecl = dyn_cast(RedeclWithBadType); + if (!Redecl) { + // Found the injected-class-name for a class template. This will be + // dumped as part of its surrounding class so we don't need to dump it + // here. + assert(isa(RedeclWithBadType) && + "expected an injected-class-name"); + continue; + } + Visit(Redecl); + } + } + + template + void dumpTemplateDecl(const TemplateDecl *D) { + dumpTemplateParameters(D->getTemplateParameters()); + + Visit(D->getTemplatedDecl()); + + for (const auto *Child : D->specializations()) + dumpTemplateDeclSpecialization(Child); + } + + void VisitTypeAliasDecl(const TypeAliasDecl *D) { + Visit(D->getUnderlyingType()); + } + + void VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl *D) { + dumpTemplateParameters(D->getTemplateParameters()); + Visit(D->getTemplatedDecl()); + } + + void VisitStaticAssertDecl(const StaticAssertDecl *D) { + Visit(D->getAssertExpr()); + Visit(D->getMessage()); + } + + void VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) { + dumpTemplateDecl(D); + } + + void VisitClassTemplateDecl(const ClassTemplateDecl *D) { + dumpTemplateDecl(D); + } + + void VisitClassTemplateSpecializationDecl( + const ClassTemplateSpecializationDecl *D) { + dumpTemplateArgumentList(D->getTemplateArgs()); + } + + void VisitClassTemplatePartialSpecializationDecl( + const ClassTemplatePartialSpecializationDecl *D) { + VisitClassTemplateSpecializationDecl(D); + dumpTemplateParameters(D->getTemplateParameters()); + } + + void VisitClassScopeFunctionSpecializationDecl( + const ClassScopeFunctionSpecializationDecl *D) { + Visit(D->getSpecialization()); + if (D->hasExplicitTemplateArgs()) + dumpTemplateArgumentListInfo(D->templateArgs()); + } + void VisitVarTemplateDecl(const VarTemplateDecl *D) { dumpTemplateDecl(D); } + + void VisitBuiltinTemplateDecl(const BuiltinTemplateDecl *D) { + dumpTemplateParameters(D->getTemplateParameters()); + } + + void + VisitVarTemplateSpecializationDecl(const VarTemplateSpecializationDecl *D) { + dumpTemplateArgumentList(D->getTemplateArgs()); + VisitVarDecl(D); + } + + void VisitVarTemplatePartialSpecializationDecl( + const VarTemplatePartialSpecializationDecl *D) { + dumpTemplateParameters(D->getTemplateParameters()); + VisitVarTemplateSpecializationDecl(D); + } + + void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) { + if (D->hasDefaultArgument()) + Visit(D->getDefaultArgument(), SourceRange(), + D->getDefaultArgStorage().getInheritedFrom(), + D->defaultArgumentWasInherited() ? "inherited from" : "previous"); + } + + void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D) { + if (D->hasDefaultArgument()) + Visit(D->getDefaultArgument(), SourceRange(), + D->getDefaultArgStorage().getInheritedFrom(), + D->defaultArgumentWasInherited() ? "inherited from" : "previous"); + } + + void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D) { + dumpTemplateParameters(D->getTemplateParameters()); + if (D->hasDefaultArgument()) + dumpTemplateArgumentLoc( + D->getDefaultArgument(), D->getDefaultArgStorage().getInheritedFrom(), + D->defaultArgumentWasInherited() ? "inherited from" : "previous"); + } + + void VisitUsingShadowDecl(const UsingShadowDecl *D) { + if (auto *TD = dyn_cast(D->getUnderlyingDecl())) + Visit(TD->getTypeForDecl()); + } + + void VisitFriendDecl(const FriendDecl *D) { + if (!D->getFriendType()) + Visit(D->getFriendDecl()); + } + + void VisitObjCMethodDecl(const ObjCMethodDecl *D) { + if (D->isThisDeclarationADefinition()) + dumpDeclContext(D); + else + for (const ParmVarDecl *Parameter : D->parameters()) + Visit(Parameter); + + if (D->hasBody()) + Visit(D->getBody()); + } + + void VisitObjCCategoryDecl(const ObjCCategoryDecl *D) { + dumpObjCTypeParamList(D->getTypeParamList()); + } + + void VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) { + dumpObjCTypeParamList(D->getTypeParamListAsWritten()); + } + + void VisitObjCImplementationDecl(const ObjCImplementationDecl *D) { + for (const auto &I : D->inits()) + Visit(I); + } + + void VisitBlockDecl(const BlockDecl *D) { + for (const auto &I : D->parameters()) + Visit(I); + + for (const auto &I : D->captures()) + Visit(I); + Visit(D->getBody()); + } + + void VisitDeclStmt(const DeclStmt *Node) { + for (const auto &D : Node->decls()) + Visit(D); + } + + void VisitAttributedStmt(const AttributedStmt *Node) { + for (const auto *A : Node->getAttrs()) + Visit(A); + } + + void VisitCXXCatchStmt(const CXXCatchStmt *Node) { + Visit(Node->getExceptionDecl()); + } + + void VisitCapturedStmt(const CapturedStmt *Node) { + Visit(Node->getCapturedDecl()); + } + + void VisitOMPExecutableDirective(const OMPExecutableDirective *Node) { + for (const auto *C : Node->clauses()) + Visit(C); + } + + void VisitInitListExpr(const InitListExpr *ILE) { + if (auto *Filler = ILE->getArrayFiller()) { + Visit(Filler, "array_filler"); + } + } + + void VisitBlockExpr(const BlockExpr *Node) { Visit(Node->getBlockDecl()); } + + void VisitOpaqueValueExpr(const OpaqueValueExpr *Node) { + if (Expr *Source = Node->getSourceExpr()) + Visit(Source); + } + + void VisitGenericSelectionExpr(const GenericSelectionExpr *E) { + Visit(E->getControllingExpr()); + Visit(E->getControllingExpr()->getType()); // FIXME: remove + + for (const auto &Assoc : E->associations()) { + Visit(Assoc); + } + } + + void VisitLambdaExpr(const LambdaExpr *Node) { + Visit(Node->getLambdaClass()); + } + + void VisitSizeOfPackExpr(const SizeOfPackExpr *Node) { + if (Node->isPartiallySubstituted()) + for (const auto &A : Node->getPartialArguments()) + Visit(A); + } + + void VisitObjCAtCatchStmt(const ObjCAtCatchStmt *Node) { + if (const VarDecl *CatchParam = Node->getCatchParamDecl()) + Visit(CatchParam); + } + + void VisitExpressionTemplateArgument(const TemplateArgument &TA) { + Visit(TA.getAsExpr()); + } + void VisitPackTemplateArgument(const TemplateArgument &TA) { + for (const auto &TArg : TA.pack_elements()) + Visit(TArg); + } + + // Implements Visit methods for Attrs. +#include "clang/AST/AttrNodeTraverse.inc" +}; + +} // namespace clang + +#endif // LLVM_CLANG_AST_ASTNODETRAVERSER_H diff --git a/include/clang/AST/ASTStructuralEquivalence.h b/include/clang/AST/ASTStructuralEquivalence.h index 2037796cd5526132451bade4ddcc0da0ecd920e8..2fcc0eaeeccc1d6f84d796c978c5caa9188f5c6c 100644 --- a/include/clang/AST/ASTStructuralEquivalence.h +++ b/include/clang/AST/ASTStructuralEquivalence.h @@ -1,9 +1,8 @@ //===- ASTStructuralEquivalence.h -------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -15,6 +14,7 @@ #ifndef LLVM_CLANG_AST_ASTSTRUCTURALEQUIVALENCE_H #define LLVM_CLANG_AST_ASTSTRUCTURALEQUIVALENCE_H +#include "clang/AST/DeclBase.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/Optional.h" diff --git a/include/clang/AST/ASTTypeTraits.h b/include/clang/AST/ASTTypeTraits.h index 9df9793370c4a3cee42d71299b0e0b9b695343b8..71c0ec4c2a854a0c571f74edb710ef1458698ee8 100644 --- a/include/clang/AST/ASTTypeTraits.h +++ b/include/clang/AST/ASTTypeTraits.h @@ -1,9 +1,8 @@ //===--- ASTTypeTraits.h ----------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/include/clang/AST/ASTUnresolvedSet.h b/include/clang/AST/ASTUnresolvedSet.h index 9bf63bb6e2d7d14278a54db1912e3301af209ec3..8d2b23b3539a24c57c5c40b7a86affe17ee9f754 100644 --- a/include/clang/AST/ASTUnresolvedSet.h +++ b/include/clang/AST/ASTUnresolvedSet.h @@ -1,9 +1,8 @@ //===- ASTUnresolvedSet.h - Unresolved sets of declarations -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/include/clang/AST/ASTVector.h b/include/clang/AST/ASTVector.h index 80cd6b7007a6dad33bc958a2867b79e71fdf792a..d5a04767ca1334017eac40865da8731e94201693 100644 --- a/include/clang/AST/ASTVector.h +++ b/include/clang/AST/ASTVector.h @@ -1,9 +1,8 @@ //===- ASTVector.h - Vector that uses ASTContext for allocation ---*- C++ -*-=// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -18,6 +17,7 @@ #ifndef LLVM_CLANG_AST_ASTVECTOR_H #define LLVM_CLANG_AST_ASTVECTOR_H +#include "clang/AST/ASTContextAllocate.h" #include "llvm/ADT/PointerIntPair.h" #include #include diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h index 4ee083934c6413aafb863872c1af52658024f61e..1fbed7ceebfad40577ad5d772b7b5b23c1f921de 100644 --- a/include/clang/AST/Attr.h +++ b/include/clang/AST/Attr.h @@ -1,9 +1,8 @@ //===--- Attr.h - Classes for representing attributes ----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -14,6 +13,7 @@ #ifndef LLVM_CLANG_AST_ATTR_H #define LLVM_CLANG_AST_ATTR_H +#include "clang/AST/ASTContextAllocate.h" // For Attrs.inc #include "clang/AST/AttrIterator.h" #include "clang/AST/Decl.h" #include "clang/AST/Expr.h" diff --git a/include/clang/AST/AttrIterator.h b/include/clang/AST/AttrIterator.h index 2087ecc0e70c751d2ffef8032f0f851f87519253..78ce9314a2bbaae71e88b079907a8640fc7e9dfd 100644 --- a/include/clang/AST/AttrIterator.h +++ b/include/clang/AST/AttrIterator.h @@ -1,9 +1,8 @@ //===- AttrIterator.h - Classes for attribute iteration ---------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -26,25 +25,6 @@ namespace clang { 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, - size_t Alignment); - -// It is good practice to pair new/delete operators. Also, MSVC gives many -// warnings if a matching delete overload is not declared, even though the -// throw() spec guarantees it will not be implicitly called. -void operator delete(void *Ptr, const clang::ASTContext &C, size_t); -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. using AttrVec = SmallVector; diff --git a/include/clang/AST/AttrVisitor.h b/include/clang/AST/AttrVisitor.h new file mode 100644 index 0000000000000000000000000000000000000000..d271db010ed1c80f27c76fb097ea9acf8198239b --- /dev/null +++ b/include/clang/AST/AttrVisitor.h @@ -0,0 +1,75 @@ +//===- AttrVisitor.h - Visitor for Attr subclasses --------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the AttrVisitor interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_ATTRVISITOR_H +#define LLVM_CLANG_AST_ATTRVISITOR_H + +#include "clang/AST/Attr.h" + +namespace clang { + +namespace attrvisitor { + +/// A simple visitor class that helps create attribute visitors. +template