diff --git a/.clang-tidy b/.clang-tidy index 2cfcc2ac22b..849c26987ef 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 3ea38b6e005..9ee83231d37 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/CMakeLists.txt b/CMakeLists.txt index 63e3ba94e1e..3a5f9349678 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -75,6 +75,11 @@ if( CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR ) set(LIBRARY_DIR ${LLVM_LIBRARY_DIR}) set(INCLUDE_DIR ${LLVM_INCLUDE_DIR}) set(LLVM_OBJ_DIR ${LLVM_BINARY_DIR}) + # The LLVM_CMAKE_PATH variable is set when doing non-standalone builds and + # used in this project, so we need to make sure we set this value. + # FIXME: LLVM_CMAKE_DIR comes from LLVMConfig.cmake. We should rename + # LLVM_CMAKE_PATH to LLVM_CMAKE_DIR throughout the project. + set(LLVM_CMAKE_PATH ${LLVM_CMAKE_DIR}) endif() set(LLVM_TOOLS_BINARY_DIR ${TOOLS_BINARY_DIR} CACHE PATH "Path to llvm/bin") @@ -261,6 +266,25 @@ if (NOT(CLANG_DEFAULT_RTLIB STREQUAL "" OR "Default runtime library to use (\"libgcc\" or \"compiler-rt\", empty for platform default)" FORCE) endif() +set(CLANG_DEFAULT_UNWINDLIB "" CACHE STRING + "Default unwind library to use (\"none\" \"libgcc\" or \"libunwind\", empty to match runtime library.)") +if (CLANG_DEFAULT_UNWINDLIB STREQUAL "") + if (CLANG_DEFAULT_RTLIB STREQUAL "libgcc") + set (CLANG_DEFAULT_UNWINDLIB "libgcc" CACHE STRING "" FORCE) + elseif (CLANG_DEFAULT_RTLIBS STREQUAL "libunwind") + set (CLANG_DEFAULT_UNWINDLIB "none" CACHE STRING "" FORCE) + endif() +endif() + +if (NOT(CLANG_DEFAULT_UNWINDLIB STREQUAL "" OR + CLANG_DEFAULT_UNWINDLIB STREQUAL "none" OR + CLANG_DEFAULT_UNWINDLIB STREQUAL "libgcc" OR + CLANG_DEFAULT_UNWINDLIB STREQUAL "libunwind")) + message(WARNING "Resetting default unwindlib to use platform default") + set(CLANG_DEFAULT_UNWINDLIB "" CACHE STRING + "Default unwind library to use (\"none\" \"libgcc\" or \"libunwind\", empty for none)" FORCE) +endif() + set(CLANG_DEFAULT_OBJCOPY "objcopy" CACHE STRING "Default objcopy executable to use.") @@ -383,6 +407,7 @@ include_directories(BEFORE if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY) install(DIRECTORY include/clang include/clang-c DESTINATION include + COMPONENT clang-headers FILES_MATCHING PATTERN "*.def" PATTERN "*.h" @@ -392,12 +417,23 @@ if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY) install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/include/clang DESTINATION include + COMPONENT clang-headers FILES_MATCHING PATTERN "CMakeFiles" EXCLUDE PATTERN "*.inc" PATTERN "*.h" ) + # Installing the headers needs to depend on generating any public + # tablegen'd headers. + add_custom_target(clang-headers DEPENDS clang-tablegen-targets) + set_target_properties(clang-headers PROPERTIES FOLDER "Misc") + if(NOT LLVM_ENABLE_IDE) + add_llvm_install_targets(install-clang-headers + DEPENDS clang-headers + COMPONENT clang-headers) + endif() + install(PROGRAMS utils/bash-autocomplete.sh DESTINATION share/clang ) @@ -411,34 +447,9 @@ option(CLANG_BUILD_TOOLS option(CLANG_ENABLE_ARCMT "Build ARCMT." ON) option(CLANG_ENABLE_STATIC_ANALYZER "Build static analyzer." ON) -set(CLANG_ANALYZER_Z3_INSTALL_DIR "" CACHE STRING "Install directory of the Z3 solver.") - -find_package(Z3 4.7.1) - -if (CLANG_ANALYZER_Z3_INSTALL_DIR) - if (NOT Z3_FOUND) - message(FATAL_ERROR "Z3 4.7.1 has not been found in CLANG_ANALYZER_Z3_INSTALL_DIR: ${CLANG_ANALYZER_Z3_INSTALL_DIR}.") - endif() -endif() - -set(CLANG_ANALYZER_ENABLE_Z3_SOLVER_DEFAULT "${Z3_FOUND}") - -option(CLANG_ANALYZER_ENABLE_Z3_SOLVER - "Enable Support for the Z3 constraint solver in the Clang Static Analyzer." - ${CLANG_ANALYZER_ENABLE_Z3_SOLVER_DEFAULT} -) - -if (CLANG_ANALYZER_ENABLE_Z3_SOLVER) - if (NOT Z3_FOUND) - message(FATAL_ERROR "CLANG_ANALYZER_ENABLE_Z3_SOLVER cannot be enabled when Z3 is not available.") - endif() - - set(CLANG_ANALYZER_WITH_Z3 1) -endif() - option(CLANG_ENABLE_PROTO_FUZZER "Build Clang protobuf fuzzer." OFF) -if(NOT CLANG_ENABLE_STATIC_ANALYZER AND (CLANG_ENABLE_ARCMT OR CLANG_ANALYZER_ENABLE_Z3_SOLVER)) +if(NOT CLANG_ENABLE_STATIC_ANALYZER AND CLANG_ENABLE_ARCMT) message(FATAL_ERROR "Cannot disable static analyzer while enabling ARCMT or Z3") endif() @@ -543,6 +554,27 @@ if( CLANG_INCLUDE_DOCS ) add_subdirectory(docs) endif() +# Custom target to install all clang libraries. +add_custom_target(clang-libraries) +set_target_properties(clang-libraries PROPERTIES FOLDER "Misc") + +if(NOT LLVM_ENABLE_IDE) + add_llvm_install_targets(install-clang-libraries + DEPENDS clang-libraries + COMPONENT clang-libraries) +endif() + +get_property(CLANG_LIBS GLOBAL PROPERTY CLANG_LIBS) +if(CLANG_LIBS) + list(REMOVE_DUPLICATES CLANG_LIBS) + foreach(lib ${CLANG_LIBS}) + add_dependencies(clang-libraries ${lib}) + if(NOT LLVM_ENABLE_IDE) + add_dependencies(install-clang-libraries install-${lib}) + endif() + endforeach() +endif() + add_subdirectory(cmake/modules) if(CLANG_STAGE) diff --git a/LICENSE.TXT b/LICENSE.TXT index 547f6a48938..24806ab4c9e 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/README.txt b/README.txt index b5f33bb66dd..91527b09485 100644 --- a/README.txt +++ b/README.txt @@ -24,4 +24,3 @@ on the Clang development mailing list: If you find a bug in Clang, please file it in the LLVM bug tracker: http://llvm.org/bugs/ - diff --git a/bindings/python/clang/__init__.py b/bindings/python/clang/__init__.py index 88f30812383..14944b63e6d 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 54514b8daef..8e5a9fe0068 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 @@ # o implement additional SourceLocation, SourceRange, and File methods. from ctypes import * -import collections import clang.enumerations @@ -123,6 +121,14 @@ def _to_python_string(x, *args): 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,10 @@ def __repr__(self): CursorKind.DLLEXPORT_ATTR = CursorKind(418) CursorKind.DLLIMPORT_ATTR = CursorKind(419) +CursorKind.CONVERGENT_ATTR = CursorKind(438) +CursorKind.WARN_UNUSED_ATTR = CursorKind(439) +CursorKind.WARN_UNUSED_RESULT_ATTR = CursorKind(440) +CursorKind.ALIGNED_ATTR = CursorKind(441) ### # Preprocessing @@ -2111,6 +2121,8 @@ def __repr__(self): TypeKind.OCLQUEUE = TypeKind(159) TypeKind.OCLRESERVEID = TypeKind(160) +TypeKind.EXTVECTOR = TypeKind(176) + class RefQualifierKind(BaseEnumeration): """Describes a specific ref-qualifier of a type.""" @@ -2181,7 +2193,7 @@ def argument_types(self): 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 +2820,9 @@ def from_source(cls, filename, args=None, unsaved_files=None, options=0, 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 +2999,13 @@ def reparse(self, unsaved_files=None, options=0): 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 +3059,13 @@ def codeComplete(self, path, line, column, unsaved_files=None, 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 a86a48ade3b..520e1346d3e 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 acec7e0e005..46073b285cb 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 17500227a34..ec1fbc0c3ed 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 3386e6428c2..3f5ac957f81 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. @@ -27,11 +32,11 @@ if(WIN32) set(RUN_PYTHON_TESTS FALSE) endif() -# AArch64 and Hexagon have known test failures that need to be +# AArch64, Hexagon, and Sparc have known test failures that need to be # addressed. # SystemZ has broken Python/FFI interface: # https://reviews.llvm.org/D52840#1265716 -if(${LLVM_NATIVE_ARCH} MATCHES "^(AArch64|Hexagon|SystemZ)$") +if(${LLVM_NATIVE_ARCH} MATCHES "^(AArch64|Hexagon|Sparc|SystemZ)$") set(RUN_PYTHON_TESTS FALSE) endif() diff --git a/bindings/python/tests/cindex/test_cdb.py b/bindings/python/tests/cindex/test_cdb.py index 589fc72856b..e2a48f14cde 100644 --- a/bindings/python/tests/cindex/test_cdb.py +++ b/bindings/python/tests/cindex/test_cdb.py @@ -23,8 +23,17 @@ class TestCDB(unittest.TestCase): def test_create_fail(self): """Check we fail loading a database with an assertion""" path = os.path.dirname(__file__) + + # clang_CompilationDatabase_fromDirectory calls fprintf(stderr, ...) + # Suppress its output. + stderr = os.dup(2) + with open(os.devnull, 'wb') as null: + os.dup2(null.fileno(), 2) with self.assertRaises(CompilationDatabaseError) as cm: cdb = CompilationDatabase.fromDirectory(path) + os.dup2(stderr, 2) + os.close(stderr) + e = cm.exception self.assertEqual(e.cdb_error, CompilationDatabaseError.ERROR_CANNOTLOADDATABASE) diff --git a/bindings/python/tests/cindex/test_code_completion.py b/bindings/python/tests/cindex/test_code_completion.py index e0b41577aeb..1603d3dfc17 100644 --- a/bindings/python/tests/cindex/test_code_completion.py +++ b/bindings/python/tests/cindex/test_code_completion.py @@ -41,7 +41,7 @@ def test_code_complete(self): expected = [ "{'int', ResultType} | {'test1', TypedText} || Priority: 50 || Availability: Available || Brief comment: Aaa.", "{'void', ResultType} | {'test2', TypedText} | {'(', LeftParen} | {')', RightParen} || Priority: 50 || Availability: Available || Brief comment: Bbb.", - "{'return', TypedText} || Priority: 40 || Availability: Available || Brief comment: None" + "{'return', TypedText} | {';', SemiColon} || Priority: 40 || Availability: Available || Brief comment: None" ] self.check_completion_results(cr, expected) @@ -67,7 +67,7 @@ def test_code_complete_pathlike(self): expected = [ "{'int', ResultType} | {'test1', TypedText} || Priority: 50 || Availability: Available || Brief comment: Aaa.", "{'void', ResultType} | {'test2', TypedText} | {'(', LeftParen} | {')', RightParen} || Priority: 50 || Availability: Available || Brief comment: Bbb.", - "{'return', TypedText} || Priority: 40 || Availability: Available || Brief comment: None" + "{'return', TypedText} | {';', SemiColon} || Priority: 40 || Availability: Available || Brief comment: None" ] self.check_completion_results(cr, expected) diff --git a/bindings/python/tests/cindex/test_diagnostics.py b/bindings/python/tests/cindex/test_diagnostics.py index 79d7a5fd411..c17d5b28efe 100644 --- a/bindings/python/tests/cindex/test_diagnostics.py +++ b/bindings/python/tests/cindex/test_diagnostics.py @@ -51,7 +51,7 @@ def test_diagnostic_fixit(self): 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 @@ def test_diagnostic_range(self): 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/cmake/caches/Apple-stage1.cmake b/cmake/caches/Apple-stage1.cmake index 51808880131..4b11342086a 100644 --- a/cmake/caches/Apple-stage1.cmake +++ b/cmake/caches/Apple-stage1.cmake @@ -33,6 +33,9 @@ set(COMPILER_RT_ENABLE_TVOS OFF CACHE BOOL "") set(BOOTSTRAP_LLVM_ENABLE_LTO ON CACHE BOOL "") set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "") +set(LIBCXX_ENABLE_NEW_DELETE_DEFINITIONS OFF CACHE BOOL "") +set(LIBCXXABI_ENABLE_NEW_DELETE_DEFINITIONS ON CACHE BOOL "") + set(CLANG_BOOTSTRAP_TARGETS generate-order-file check-all diff --git a/cmake/caches/Apple-stage2.cmake b/cmake/caches/Apple-stage2.cmake index c7f3f04b420..eb482700201 100644 --- a/cmake/caches/Apple-stage2.cmake +++ b/cmake/caches/Apple-stage2.cmake @@ -38,6 +38,7 @@ set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "") set(LIBCXX_INSTALL_LIBRARY OFF CACHE BOOL "") set(LIBCXX_INSTALL_HEADERS ON CACHE BOOL "") set(LIBCXX_INCLUDE_TESTS OFF CACHE BOOL "") +set(LIBCXX_USE_COMPILER_RT ON CACHE BOOL "") set(LLVM_LTO_VERSION_OFFSET 3000 CACHE STRING "") # Generating Xcode toolchains is useful for developers wanting to build and use @@ -60,8 +61,9 @@ set(LLVM_DISTRIBUTION_COMPONENTS clang LTO clang-format - clang-headers + clang-resource-headers cxx-headers + Remarks ${LLVM_TOOLCHAIN_TOOLS} CACHE STRING "") diff --git a/cmake/caches/BaremetalARM.cmake b/cmake/caches/BaremetalARM.cmake index d9d2efcbb4b..85295d9db39 100644 --- a/cmake/caches/BaremetalARM.cmake +++ b/cmake/caches/BaremetalARM.cmake @@ -41,7 +41,7 @@ set(LLVM_TOOLCHAIN_TOOLS set(LLVM_DISTRIBUTION_COMPONENTS clang lld - clang-headers + clang-resource-headers builtins-armv6m-none-eabi builtins-armv7m-none-eabi builtins-armv7em-none-eabi diff --git a/cmake/caches/DistributionExample-stage2.cmake b/cmake/caches/DistributionExample-stage2.cmake index 600ba56e456..99d5dc0fd2f 100644 --- a/cmake/caches/DistributionExample-stage2.cmake +++ b/cmake/caches/DistributionExample-stage2.cmake @@ -1,6 +1,9 @@ # This file sets up a CMakeCache for the second stage of a simple distribution # bootstrap build. +set(LLVM_ENABLE_PROJECTS "clang;clang-tools-extra;lld" CACHE STRING "") +set(LLVM_ENABLE_RUNTIMES "compiler-rt;libcxx;libcxxabi" CACHE STRING "") + set(LLVM_TARGETS_TO_BUILD X86;ARM;AArch64 CACHE STRING "") set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "") @@ -23,7 +26,7 @@ set(LLVM_DISTRIBUTION_COMPONENTS clang LTO clang-format - clang-headers + clang-resource-headers builtins runtimes ${LLVM_TOOLCHAIN_TOOLS} diff --git a/cmake/caches/DistributionExample.cmake b/cmake/caches/DistributionExample.cmake index 551f4ee07ea..50fcc09cf07 100644 --- a/cmake/caches/DistributionExample.cmake +++ b/cmake/caches/DistributionExample.cmake @@ -1,5 +1,9 @@ # This file sets up a CMakeCache for a simple distribution bootstrap build. +#Enable LLVM projects and runtimes +set(LLVM_ENABLE_PROJECTS "clang;clang-tools-extra;lld" CACHE STRING "") +set(LLVM_ENABLE_RUNTIMES "compiler-rt;libcxx;libcxxabi" CACHE STRING "") + # Only build the native target in stage1 since it is a throwaway build. set(LLVM_TARGETS_TO_BUILD Native CACHE STRING "") @@ -13,6 +17,11 @@ set(PACKAGE_VENDOR LLVM.org CACHE STRING "") # the proper LTO library dependencies can be connected. set(BOOTSTRAP_LLVM_ENABLE_LTO ON CACHE BOOL "") +if (NOT APPLE) + # Since LLVM_ENABLE_LTO is ON we need a LTO capable linker + set(BOOTSTRAP_LLVM_ENABLE_LLD ON CACHE BOOL "") +endif() + # Expose stage2 targets through the stage1 build configuration. set(CLANG_BOOTSTRAP_TARGETS check-all diff --git a/cmake/caches/Fuchsia-stage2.cmake b/cmake/caches/Fuchsia-stage2.cmake index 9413c79dc3d..100a9b164e5 100644 --- a/cmake/caches/Fuchsia-stage2.cmake +++ b/cmake/caches/Fuchsia-stage2.cmake @@ -1,39 +1,59 @@ -# 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_USE_RELATIVE_PATHS_IN_DEBUG_INFO ON 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 "") + + set(LIBUNWIND_ENABLE_SHARED OFF CACHE BOOL "") + set(LIBUNWIND_INSTALL_LIBRARY OFF CACHE BOOL "") + set(LIBUNWIND_USE_COMPILER_RT ON CACHE BOOL "") + set(LIBCXXABI_ENABLE_SHARED OFF CACHE BOOL "") + set(LIBCXXABI_ENABLE_STATIC_UNWINDER ON CACHE BOOL "") + set(LIBCXXABI_INSTALL_LIBRARY OFF CACHE BOOL "") + set(LIBCXXABI_USE_COMPILER_RT ON CACHE BOOL "") + set(LIBCXXABI_USE_LLVM_UNWINDER ON CACHE BOOL "") + set(LIBCXX_USE_COMPILER_RT ON CACHE BOOL "") + set(LIBCXX_ENABLE_SHARED OFF CACHE BOOL "") + set(LIBCXX_ENABLE_STATIC_ABI_LIBRARY ON CACHE BOOL "") + set(LIBCXX_ABI_VERSION 2 CACHE STRING "") endif() -foreach(target aarch64-linux-gnu;armv7-linux-gnueabihf;i386-linux-gnu;x86_64-linux-gnu) +foreach(target aarch64-unknown-linux-gnu;armv7-unknown-linux-gnueabihf;i386-unknown-linux-gnu;x86_64-unknown-linux-gnu) if(LINUX_${target}_SYSROOT) # Set the per-target builtins options. list(APPEND BUILTIN_TARGETS "${target}") @@ -68,6 +88,9 @@ foreach(target aarch64-linux-gnu;armv7-linux-gnueabihf;i386-linux-gnu;x86_64-lin set(RUNTIMES_${target}_SANITIZER_CXX_ABI "libc++" CACHE STRING "") set(RUNTIMES_${target}_SANITIZER_CXX_ABI_INTREE ON CACHE BOOL "") set(RUNTIMES_${target}_COMPILER_RT_USE_BUILTINS_LIBRARY ON CACHE BOOL "") + + # Use .build-id link. + list(APPEND RUNTIME_BUILD_ID_LINK "${target}") endif() endforeach() @@ -82,49 +105,66 @@ if(FUCHSIA_SDK) foreach(target x86_64;aarch64) # Set the per-target builtins options. - list(APPEND BUILTIN_TARGETS "${target}-fuchsia") - set(BUILTINS_${target}-fuchsia_CMAKE_SYSTEM_NAME Fuchsia CACHE STRING "") - set(BUILTINS_${target}-fuchsia_CMAKE_BUILD_TYPE Release CACHE STRING "") - set(BUILTINS_${target}-fuchsia_CMAKE_ASM_FLAGS ${FUCHSIA_${target}_COMPILER_FLAGS} CACHE STRING "") - set(BUILTINS_${target}-fuchsia_CMAKE_C_FLAGS ${FUCHSIA_${target}_COMPILER_FLAGS} CACHE STRING "") - set(BUILTINS_${target}-fuchsia_CMAKE_CXX_FLAGS ${FUCHSIA_${target}_COMPILER_FLAGS} CACHE STRING "") - set(BUILTINS_${target}-fuchsia_CMAKE_SHARED_LINKER_FLAGS ${FUCHSIA_${target}_LINKER_FLAGS} CACHE STRING "") - set(BUILTINS_${target}-fuchsia_CMAKE_MODULE_LINKER_FLAGS ${FUCHSIA_${target}_LINKER_FLAGS} CACHE STRING "") - set(BUILTINS_${target}-fuchsia_CMAKE_EXE_LINKER_FLAGS ${FUCHSIA_${target}_LINKER_FLAGS} CACHE STRING "") - set(BUILTINS_${target}-fuchsia_CMAKE_SYSROOT ${FUCHSIA_${target}_SYSROOT} CACHE PATH "") + list(APPEND BUILTIN_TARGETS "${target}-unknown-fuchsia") + set(BUILTINS_${target}-unknown-fuchsia_CMAKE_SYSTEM_NAME Fuchsia CACHE STRING "") + set(BUILTINS_${target}-unknown-fuchsia_CMAKE_BUILD_TYPE Release CACHE STRING "") + set(BUILTINS_${target}-unknown-fuchsia_CMAKE_ASM_FLAGS ${FUCHSIA_${target}_COMPILER_FLAGS} CACHE STRING "") + set(BUILTINS_${target}-unknown-fuchsia_CMAKE_C_FLAGS ${FUCHSIA_${target}_COMPILER_FLAGS} CACHE STRING "") + set(BUILTINS_${target}-unknown-fuchsia_CMAKE_CXX_FLAGS ${FUCHSIA_${target}_COMPILER_FLAGS} CACHE STRING "") + set(BUILTINS_${target}-unknown-fuchsia_CMAKE_SHARED_LINKER_FLAGS ${FUCHSIA_${target}_LINKER_FLAGS} CACHE STRING "") + set(BUILTINS_${target}-unknown-fuchsia_CMAKE_MODULE_LINKER_FLAGS ${FUCHSIA_${target}_LINKER_FLAGS} CACHE STRING "") + set(BUILTINS_${target}-unknown-fuchsia_CMAKE_EXE_LINKER_FLAGS ${FUCHSIA_${target}_LINKER_FLAGS} CACHE STRING "") + set(BUILTINS_${target}-unknown-fuchsia_CMAKE_SYSROOT ${FUCHSIA_${target}_SYSROOT} CACHE PATH "") # Set the per-target runtimes options. - list(APPEND RUNTIME_TARGETS "${target}-fuchsia") - set(RUNTIMES_${target}-fuchsia_CMAKE_SYSTEM_NAME Fuchsia CACHE STRING "") - set(RUNTIMES_${target}-fuchsia_CMAKE_BUILD_TYPE Release CACHE STRING "") - set(RUNTIMES_${target}-fuchsia_CMAKE_BUILD_WITH_INSTALL_RPATH ON CACHE BOOL "") - set(RUNTIMES_${target}-fuchsia_CMAKE_ASM_FLAGS ${FUCHSIA_${target}_COMPILER_FLAGS} CACHE STRING "") - set(RUNTIMES_${target}-fuchsia_CMAKE_C_FLAGS ${FUCHSIA_${target}_COMPILER_FLAGS} CACHE STRING "") - set(RUNTIMES_${target}-fuchsia_CMAKE_CXX_FLAGS ${FUCHSIA_${target}_COMPILER_FLAGS} CACHE STRING "") - set(RUNTIMES_${target}-fuchsia_CMAKE_SHARED_LINKER_FLAGS ${FUCHSIA_${target}_LINKER_FLAGS} CACHE STRING "") - set(RUNTIMES_${target}-fuchsia_CMAKE_MODULE_LINKER_FLAGS ${FUCHSIA_${target}_LINKER_FLAGS} CACHE STRING "") - set(RUNTIMES_${target}-fuchsia_CMAKE_EXE_LINKER_FLAGS ${FUCHSIA_${target}_LINKER_FLAGS} CACHE STRING "") - 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_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_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_STATICALLY_LINK_ABI_IN_SHARED_LIBRARY OFF CACHE BOOL "") - set(RUNTIMES_${target}-fuchsia_LIBCXX_ABI_VERSION 2 CACHE STRING "") + list(APPEND RUNTIME_TARGETS "${target}-unknown-fuchsia") + set(RUNTIMES_${target}-unknown-fuchsia_CMAKE_SYSTEM_NAME Fuchsia CACHE STRING "") + set(RUNTIMES_${target}-unknown-fuchsia_CMAKE_BUILD_TYPE Release CACHE STRING "") + set(RUNTIMES_${target}-unknown-fuchsia_CMAKE_BUILD_WITH_INSTALL_RPATH ON CACHE BOOL "") + set(RUNTIMES_${target}-unknown-fuchsia_CMAKE_ASM_FLAGS ${FUCHSIA_${target}_COMPILER_FLAGS} CACHE STRING "") + set(RUNTIMES_${target}-unknown-fuchsia_CMAKE_C_FLAGS ${FUCHSIA_${target}_COMPILER_FLAGS} CACHE STRING "") + set(RUNTIMES_${target}-unknown-fuchsia_CMAKE_CXX_FLAGS ${FUCHSIA_${target}_COMPILER_FLAGS} CACHE STRING "") + set(RUNTIMES_${target}-unknown-fuchsia_CMAKE_SHARED_LINKER_FLAGS ${FUCHSIA_${target}_LINKER_FLAGS} CACHE STRING "") + set(RUNTIMES_${target}-unknown-fuchsia_CMAKE_MODULE_LINKER_FLAGS ${FUCHSIA_${target}_LINKER_FLAGS} CACHE STRING "") + set(RUNTIMES_${target}-unknown-fuchsia_CMAKE_EXE_LINKER_FLAGS ${FUCHSIA_${target}_LINKER_FLAGS} CACHE STRING "") + set(RUNTIMES_${target}-unknown-fuchsia_CMAKE_SYSROOT ${FUCHSIA_${target}_SYSROOT} CACHE PATH "") + set(RUNTIMES_${target}-unknown-fuchsia_LLVM_ENABLE_ASSERTIONS ON CACHE BOOL "") + set(RUNTIMES_${target}-unknown-fuchsia_LIBUNWIND_USE_COMPILER_RT ON CACHE BOOL "") + set(RUNTIMES_${target}-unknown-fuchsia_LIBUNWIND_HERMETIC_STATIC_LIBRARY ON CACHE BOOL "") + set(RUNTIMES_${target}-unknown-fuchsia_LIBUNWIND_INSTALL_STATIC_LIBRARY OFF CACHE BOOL "") + set(RUNTIMES_${target}-unknown-fuchsia_LIBCXXABI_USE_COMPILER_RT ON CACHE BOOL "") + set(RUNTIMES_${target}-unknown-fuchsia_LIBCXXABI_USE_LLVM_UNWINDER ON CACHE BOOL "") + set(RUNTIMES_${target}-unknown-fuchsia_LIBCXXABI_ENABLE_STATIC_UNWINDER ON CACHE BOOL "") + set(RUNTIMES_${target}-unknown-fuchsia_LIBCXXABI_HERMETIC_STATIC_LIBRARY ON CACHE BOOL "") + set(RUNTIMES_${target}-unknown-fuchsia_LIBCXXABI_INSTALL_STATIC_LIBRARY OFF CACHE BOOL "") + set(RUNTIMES_${target}-unknown-fuchsia_LIBCXXABI_STATICALLY_LINK_UNWINDER_IN_SHARED_LIBRARY OFF CACHE BOOL "") + set(RUNTIMES_${target}-unknown-fuchsia_LIBCXX_USE_COMPILER_RT ON CACHE BOOL "") + set(RUNTIMES_${target}-unknown-fuchsia_LIBCXX_ENABLE_STATIC_ABI_LIBRARY ON CACHE BOOL "") + set(RUNTIMES_${target}-unknown-fuchsia_LIBCXX_HERMETIC_STATIC_LIBRARY ON CACHE BOOL "") + set(RUNTIMES_${target}-unknown-fuchsia_LIBCXX_STATICALLY_LINK_ABI_IN_SHARED_LIBRARY OFF CACHE BOOL "") + set(RUNTIMES_${target}-unknown-fuchsia_LIBCXX_ABI_VERSION 2 CACHE STRING "") + + set(RUNTIMES_${target}-unknown-fuchsia+asan_LLVM_BUILD_COMPILER_RT OFF CACHE BOOL "") + set(RUNTIMES_${target}-unknown-fuchsia+asan_LLVM_USE_SANITIZER "Address" CACHE STRING "") + set(RUNTIMES_${target}-unknown-fuchsia+asan_LIBCXXABI_ENABLE_NEW_DELETE_DEFINITIONS OFF CACHE BOOL "") + set(RUNTIMES_${target}-unknown-fuchsia+asan_LIBCXX_ENABLE_NEW_DELETE_DEFINITIONS OFF CACHE BOOL "") + + set(RUNTIMES_${target}-unknown-fuchsia+noexcept_LLVM_BUILD_COMPILER_RT OFF CACHE BOOL "") + set(RUNTIMES_${target}-unknown-fuchsia+noexcept_LIBCXXABI_ENABLE_EXCEPTIONS OFF CACHE BOOL "") + set(RUNTIMES_${target}-unknown-fuchsia+noexcept_LIBCXX_ENABLE_EXCEPTIONS OFF CACHE BOOL "") + + # Use .build-id link. + list(APPEND RUNTIME_BUILD_ID_LINK "${target}-unknown-fuchsia") endforeach() - set(LLVM_RUNTIME_SANITIZERS "Address" CACHE STRING "") - set(LLVM_RUNTIME_SANITIZER_Address_TARGETS "x86_64-fuchsia;aarch64-fuchsia" CACHE STRING "") + set(LLVM_RUNTIME_MULTILIBS "asan;noexcept" CACHE STRING "") + set(LLVM_RUNTIME_MULTILIB_asan_TARGETS "x86_64-unknown-fuchsia;aarch64-unknown-fuchsia" CACHE STRING "") + set(LLVM_RUNTIME_MULTILIB_noexcept_TARGETS "x86_64-unknown-fuchsia;aarch64-unknown-fuchsia" CACHE STRING "") endif() set(LLVM_BUILTIN_TARGETS "${BUILTIN_TARGETS}" CACHE STRING "") set(LLVM_RUNTIME_TARGETS "${RUNTIME_TARGETS}" CACHE STRING "") +set(LLVM_RUNTIME_BUILD_ID_LINK_TARGETS "${RUNTIME_BUILD_ID_LINK}" CACHE STRING "") # Setup toolchain. set(LLVM_INSTALL_TOOLCHAIN_ONLY ON CACHE BOOL "") @@ -154,12 +194,12 @@ set(LLVM_TOOLCHAIN_TOOLS set(LLVM_DISTRIBUTION_COMPONENTS clang - libclang lld LTO clang-apply-replacements + clang-doc clang-format - clang-headers + clang-resource-headers clang-include-fixer clang-refactor clang-tidy diff --git a/cmake/caches/Fuchsia.cmake b/cmake/caches/Fuchsia.cmake index cc3baa294d0..63bd62d1e93 100644 --- a/cmake/caches/Fuchsia.cmake +++ b/cmake/caches/Fuchsia.cmake @@ -4,49 +4,46 @@ 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 "") set(COMPILER_RT_ENABLE_TVOS OFF CACHE BOOL "") set(COMPILER_RT_ENABLE_WATCHOS OFF CACHE BOOL "") -elseif(UNIX) - set(LIBUNWIND_ENABLE_SHARED OFF CACHE BOOL "") - set(LIBUNWIND_USE_COMPILER_RT ON CACHE BOOL "") - set(LIBUNWIND_INSTALL_LIBRARY OFF CACHE BOOL "") - set(LIBCXXABI_USE_COMPILER_RT ON CACHE BOOL "") - set(LIBCXXABI_ENABLE_SHARED OFF CACHE BOOL "") - set(LIBCXXABI_USE_LLVM_UNWINDER ON CACHE BOOL "") - set(LIBCXXABI_ENABLE_STATIC_UNWINDER ON CACHE BOOL "") - set(LIBCXXABI_INSTALL_LIBRARY OFF CACHE BOOL "") - set(LIBCXX_USE_COMPILER_RT ON CACHE BOOL "") - set(LIBCXX_ENABLE_SHARED OFF CACHE BOOL "") - set(LIBCXX_ENABLE_STATIC_ABI_LIBRARY ON CACHE BOOL "") endif() +set(LIBUNWIND_ENABLE_SHARED OFF CACHE BOOL "") +set(LIBUNWIND_INSTALL_LIBRARY OFF CACHE BOOL "") +set(LIBUNWIND_USE_COMPILER_RT ON CACHE BOOL "") +set(LIBCXXABI_ENABLE_SHARED OFF CACHE BOOL "") +set(LIBCXXABI_ENABLE_STATIC_UNWINDER ON CACHE BOOL "") +set(LIBCXXABI_INSTALL_LIBRARY OFF CACHE BOOL "") +set(LIBCXXABI_USE_COMPILER_RT ON CACHE BOOL "") +set(LIBCXXABI_USE_LLVM_UNWINDER ON CACHE BOOL "") +set(LIBCXX_ABI_VERSION 2 CACHE STRING "") +set(LIBCXX_ENABLE_SHARED OFF CACHE BOOL "") +set(LIBCXX_ENABLE_STATIC_ABI_LIBRARY ON CACHE BOOL "") +set(LIBCXX_USE_COMPILER_RT ON CACHE BOOL "") + if(BOOTSTRAP_CMAKE_SYSTEM_NAME) set(target "${BOOTSTRAP_CMAKE_CXX_COMPILER_TARGET}") if(STAGE2_LINUX_${target}_SYSROOT) @@ -78,6 +75,17 @@ 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 diff --git a/cmake/modules/AddClang.cmake b/cmake/modules/AddClang.cmake index 7e22f16f365..0c9cd667603 100644 --- a/cmake/modules/AddClang.cmake +++ b/cmake/modules/AddClang.cmake @@ -81,16 +81,26 @@ macro(add_clang_library name) ) endif() if(ARG_SHARED) - set(ARG_ENABLE_SHARED SHARED) + set(LIBTYPE SHARED) + else() + # llvm_add_library ignores BUILD_SHARED_LIBS if STATIC is explicitly set, + # so we need to handle it here. + if(BUILD_SHARED_LIBS) + set(LIBTYPE SHARED OBJECT) + else() + set(LIBTYPE STATIC OBJECT) + endif() + set_property(GLOBAL APPEND PROPERTY CLANG_STATIC_LIBS ${name}) endif() - llvm_add_library(${name} ${ARG_ENABLE_SHARED} ${ARG_UNPARSED_ARGUMENTS} ${srcs}) + llvm_add_library(${name} ${LIBTYPE} ${ARG_UNPARSED_ARGUMENTS} ${srcs}) if(TARGET ${name}) target_link_libraries(${name} INTERFACE ${LLVM_COMMON_LIBS}) if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY OR ${name} STREQUAL "libclang") - + set(export_to_clangtargets) if(${name} IN_LIST LLVM_DISTRIBUTION_COMPONENTS OR + "clang-libraries" IN_LIST LLVM_DISTRIBUTION_COMPONENTS OR NOT LLVM_DISTRIBUTION_COMPONENTS) set(export_to_clangtargets EXPORT ClangTargets) set_property(GLOBAL PROPERTY CLANG_HAS_EXPORTS True) @@ -103,11 +113,13 @@ macro(add_clang_library name) ARCHIVE DESTINATION lib${LLVM_LIBDIR_SUFFIX} RUNTIME DESTINATION bin) - if (${ARG_SHARED} AND NOT CMAKE_CONFIGURATION_TYPES) + if (NOT LLVM_ENABLE_IDE) add_llvm_install_targets(install-${name} DEPENDS ${name} COMPONENT ${name}) endif() + + set_property(GLOBAL APPEND PROPERTY CLANG_LIBS ${name}) endif() set_property(GLOBAL APPEND PROPERTY CLANG_EXPORTS ${name}) else() @@ -131,9 +143,10 @@ macro(add_clang_tool name) endif() add_clang_executable(${name} ${ARGN}) - add_dependencies(${name} clang-headers) + add_dependencies(${name} clang-resource-headers) if (CLANG_BUILD_TOOLS) + set(export_to_clangtargets) if(${name} IN_LIST LLVM_DISTRIBUTION_COMPONENTS OR NOT LLVM_DISTRIBUTION_COMPONENTS) set(export_to_clangtargets EXPORT ClangTargets) @@ -145,7 +158,7 @@ macro(add_clang_tool name) RUNTIME DESTINATION bin COMPONENT ${name}) - if(NOT CMAKE_CONFIGURATION_TYPES) + if(NOT LLVM_ENABLE_IDE) add_llvm_install_targets(install-${name} DEPENDS ${name} COMPONENT ${name}) diff --git a/cmake/modules/CMakeLists.txt b/cmake/modules/CMakeLists.txt index be6d1d7257b..d233f552f01 100644 --- a/cmake/modules/CMakeLists.txt +++ b/cmake/modules/CMakeLists.txt @@ -55,10 +55,19 @@ set(CLANG_CONFIG_EXPORTS_FILE) if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY) get_property(clang_has_exports GLOBAL PROPERTY CLANG_HAS_EXPORTS) if(clang_has_exports) - install(EXPORT ClangTargets DESTINATION ${CLANG_INSTALL_PACKAGE_DIR}) + install(EXPORT ClangTargets DESTINATION ${CLANG_INSTALL_PACKAGE_DIR} + COMPONENT clang-cmake-exports) endif() install(FILES ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/ClangConfig.cmake - DESTINATION ${CLANG_INSTALL_PACKAGE_DIR}) + DESTINATION ${CLANG_INSTALL_PACKAGE_DIR} + COMPONENT clang-cmake-exports) + + if(NOT LLVM_ENABLE_IDE) + # Add a dummy target so this can be used with LLVM_DISTRIBUTION_COMPONENTS + add_custom_target(clang-cmake-exports) + add_llvm_install_targets(install-clang-cmake-exports + COMPONENT clang-cmake-exports) + endif() endif() diff --git a/cmake/modules/FindZ3.cmake b/cmake/modules/FindZ3.cmake deleted file mode 100644 index 7a224f789ec..00000000000 --- a/cmake/modules/FindZ3.cmake +++ /dev/null @@ -1,51 +0,0 @@ -# Looking for Z3 in CLANG_ANALYZER_Z3_INSTALL_DIR -find_path(Z3_INCLUDE_DIR NAMES z3.h - NO_DEFAULT_PATH - PATHS ${CLANG_ANALYZER_Z3_INSTALL_DIR}/include - PATH_SUFFIXES libz3 z3 - ) - -find_library(Z3_LIBRARIES NAMES z3 libz3 - NO_DEFAULT_PATH - PATHS ${CLANG_ANALYZER_Z3_INSTALL_DIR} - PATH_SUFFIXES lib bin - ) - -find_program(Z3_EXECUTABLE z3 - NO_DEFAULT_PATH - PATHS ${CLANG_ANALYZER_Z3_INSTALL_DIR} - PATH_SUFFIXES bin - ) - -# If Z3 has not been found in CLANG_ANALYZER_Z3_INSTALL_DIR look in the default directories -find_path(Z3_INCLUDE_DIR NAMES z3.h - PATH_SUFFIXES libz3 z3 - ) - -find_library(Z3_LIBRARIES NAMES z3 libz3 - PATH_SUFFIXES lib bin - ) - -find_program(Z3_EXECUTABLE z3 - PATH_SUFFIXES bin - ) - -if(Z3_INCLUDE_DIR AND Z3_LIBRARIES AND Z3_EXECUTABLE) - execute_process (COMMAND ${Z3_EXECUTABLE} -version - OUTPUT_VARIABLE libz3_version_str - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE) - - string(REGEX REPLACE "^Z3 version ([0-9.]+)" "\\1" - Z3_VERSION_STRING "${libz3_version_str}") - unset(libz3_version_str) -endif() - -# handle the QUIETLY and REQUIRED arguments and set Z3_FOUND to TRUE if -# all listed variables are TRUE -include(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(Z3 - REQUIRED_VARS Z3_LIBRARIES Z3_INCLUDE_DIR - VERSION_VAR Z3_VERSION_STRING) - -mark_as_advanced(Z3_INCLUDE_DIR Z3_LIBRARIES) diff --git a/cmake/modules/ProtobufMutator.cmake b/cmake/modules/ProtobufMutator.cmake index 5f23f33f4c7..15fe95ed6e8 100644 --- a/cmake/modules/ProtobufMutator.cmake +++ b/cmake/modules/ProtobufMutator.cmake @@ -1,3 +1,4 @@ +include(ExternalProject) set(PBM_PREFIX protobuf_mutator) set(PBM_PATH ${CMAKE_CURRENT_BINARY_DIR}/${PBM_PREFIX}/src/${PBM_PREFIX}) set(PBM_LIB_PATH ${PBM_PATH}-build/src/libprotobuf-mutator.a) diff --git a/docs/APINotes.rst b/docs/APINotes.rst new file mode 100644 index 00000000000..83ce634623c --- /dev/null +++ b/docs/APINotes.rst @@ -0,0 +1,361 @@ +================================================ +API Notes: Annotations Without Modifying Headers +================================================ + +**The Problem:** You have headers you want to use, but you also want to add +extra information to some of the APIs. You don't want to put that information +in the headers themselves---perhaps because you want to keep them clean for +other clients, or perhaps because they're from some open source project and you +don't want to modify them at all. + +**Incomplete solution:** Redeclare all the interesting APIs in your own header +and add the attributes you want. Unfortunately, this: + +* doesn't work with attributes that must be present on a definition +* doesn't allow changing the definition in other ways +* requires your header to be included in any client code to take effect + +**Better solution:** Provide a "sidecar" file with the information you want to +add, and have that automatically get picked up by the module-building logic in +the compiler. + +That's API notes. + +API notes use a YAML-based file format. YAML is a format best explained by +example, so here is a `small example`__ from the compiler test suite of API +notes for a hypothetical "SomeKit" framework. + +__ https://github.com/apple/swift-clang/blob/upstream-with-swift/test/APINotes/Inputs/Frameworks/SomeKit.framework/Headers/SomeKit.apinotes + + +Usage +===== + +API notes files are found relative to the module map that defines a module, +under the name "SomeKit.apinotes" for a module named "SomeKit". Additionally, a +file named "SomeKit_private.apinotes" will also be picked up to go with a +private module map. For bare modules these two files will be in the same +directory as the corresponding module map; for framework modules, they should +be placed in the Headers and PrivateHeaders directories, respectively. The +module map for a private top-level framework module should be placed in the +PrivateHeaders directory as well, though it does not need an additional +"_private" suffix on its name. + +Clang will search for API notes files next to module maps only when passed the +``-fapinotes-modules`` option. + + +Limitations +=========== + +- Since they're identified by module name, API notes cannot be used to modify + arbitrary textual headers. + + +"Versioned" API Notes +===================== + +Many API notes affect how a C API is imported into Swift. In order to change +that behavior while still remaining backwards-compatible, API notes can be +selectively applied based on the Swift compatibility version provided to the +compiler (e.g. ``-fapinotes-swift-version=5``). The rule is that an +explicitly-versioned API note applies to that version *and all earlier +versions,* and any applicable explicitly-versioned API note takes precedence +over an unversioned API note. + + +Reference +========= + +An API notes file contains a YAML dictionary with the following top-level +entries: + +:Name: + + The name of the module (the framework name, for frameworks). Note that this + is always the name of a top-level module, even within a private API notes + file. + + :: + + Name: MyFramework + +:Classes, Protocols, Tags, Typedefs, Globals, Enumerators, Functions: + + Arrays of top-level declarations. Each entry in the array must have a + 'Name' key with its Objective-C name. "Tags" refers to structs, enums, and + unions; "Enumerators" refers to enum cases. + + :: + + Classes: + - Name: MyController + … + - Name: MyView + … + +:SwiftVersions: + + Contains explicit information for backwards compatibility. Each entry in + the array contains a 'Version' key, which should be set to '4' for + annotations that only apply to Swift 4 mode and earlier. The other entries + in this dictionary are the same declaration entries as at the top level: + Classes, Protocols, Tags, Typedefs, Globals, Enumerators, and Functions. + + :: + + SwiftVersions: + - Version: 4 + Classes: … + Protocols: … + +Each entry under 'Classes' and 'Protocols' can contain "Methods" and +"Properties" arrays, in addition to the attributes described below: + +:Methods: + + Identified by 'Selector' and 'MethodKind'; the MethodKind is either + "Instance" or "Class". + + :: + + Classes: + - Name: UIViewController + Methods: + - Selector: "presentViewController:animated:" + MethodKind: Instance + … + +:Properties: + + Identified by 'Name' and 'PropertyKind'; the PropertyKind is also either + "Instance" or "Class". + + :: + + Classes: + - Name: UIView + Properties: + - Name: subviews + PropertyKind: Instance + … + +Each declaration supports the following annotations (if relevant to that +declaration kind), all of which are optional: + +:SwiftName: + + Equivalent to NS_SWIFT_NAME. For a method, must include the full Swift name + with all arguments. Use "_" to omit an argument label. + + :: + + - Selector: "presentViewController:animated:" + MethodKind: Instance + SwiftName: "present(_:animated:)" + + - Class: NSBundle + SwiftName: Bundle + +:Availability, AvailabilityMsg: + + A value of "nonswift" is equivalent to NS_SWIFT_UNAVAILABLE. A value of + "available" can be used in the "SwiftVersions" section to undo the effect of + "nonswift". + + :: + + - Selector: "dealloc" + MethodKind: Instance + Availability: nonswift + AvailabilityMsg: "prefer 'deinit'" + +:SwiftPrivate: + + Equivalent to NS_REFINED_FOR_SWIFT. + + :: + + - Name: CGColorEqualToColor + SwiftPrivate: true + +:Nullability: + + Used for properties and globals. There are four options, identified by their + initials: + + - "N"onnull (``_Nonnull``) + - "O"ptional (``_Nullable``) + - "U"nspecified (``_Null_unspecified``) + - "S"calar (deprecated) + + Note that 'Nullability' is overridden by 'Type', even in a "SwiftVersions" + section. + + .. note:: + + 'Nullability' can also be used to describe the argument types of methods + and functions, but this usage is deprecated in favor of 'Parameters' (see + below). + + :: + + - Name: dataSource + Nullability: O + +:NullabilityOfRet: + + Used for methods and functions. Describes the nullability of the return type. + + Note that 'NullabilityOfRet' is overridden by 'ResultType', even in a + "SwiftVersions" section. + + .. warning:: + + Due to a compiler bug, 'NullabilityOfRet' may change nullability of the + parameters as well (rdar://30544062). Avoid using it and instead use + 'ResultType' and specify the return type along with a nullability + annotation (see documentation for 'ResultType'). + + :: + + - Selector: superclass + MethodKind: Class + NullabilityOfRet: O + +:Type: + + Used for properties and globals. This completely overrides the type of the + declaration; it should ideally only be used for Swift backwards + compatibility, when existing type information has been made more precise in a + header. Prefer 'Nullability' and other annotations when possible. + + Note that the type is *not* parsed in the context where it will be used, + which means that macros are not available and nullability must be applied + explicitly (even in an ``NS_ASSUME_NONNULL_BEGIN`` section). + + :: + + - Name: delegate + PropertyKind: Instance + Type: "id" + +:ResultType: + + Used for methods and functions. This completely overrides the return type; it + should ideally only be used for Swift backwards compatibility, when existing + type information has been made more precise in a header. + + Note that the type is *not* parsed in the context where it will be used, + which means that macros are not available and nullability must be applied + explicitly (even in an ``NS_ASSUME_NONNULL_BEGIN`` section). + + :: + + - Selector: "subviews" + MethodKind: Instance + ResultType: "NSArray * _Nonnull" + +:SwiftImportAsAccessors: + + Used for properties. If true, the property will be exposed in Swift as its + accessor methods, rather than as a computed property using ``var``. + + :: + + - Name: currentContext + PropertyKind: Class + SwiftImportAsAccessors: true + +:NSErrorDomain: + + Used for NSError code enums. The value is the name of the associated domain + NSString constant; an empty string ("") means the enum is a normal enum + rather than an error code. + + :: + + - Name: MKErrorCode + NSErrorDomain: MKErrorDomain + +:SwiftWrapper: + + Controls NS_STRING_ENUM and NS_EXTENSIBLE_STRING_ENUM. There are three + options: + + - "struct" (extensible) + - "enum" + - "none" + + Note that even an "enum" wrapper is still presented as a struct in Swift; + it's just a "more enum-like" struct. + + :: + + - Name: AVMediaType + SwiftWrapper: none + +:EnumKind: + + Has the same effect as NS_ENUM and NS_OPTIONS. There are four options: + + - "NSEnum" / "CFEnum" + - "NSClosedEnum" / "CFClosedEnum" + - "NSOptions" / "CFOptions" + - "none" + + :: + + - Name: GKPhotoSize + EnumKind: none + +:Parameters: + + Used for methods and functions. Parameters are identified by a 0-based + 'Position' and support the 'Nullability', 'NoEscape', and 'Type' keys. + + .. note:: + + Using 'Parameters' within a parameter entry to describe the parameters of a + block is not implemented. Use 'Type' on the entire parameter instead. + + :: + + - Selector: "isEqual:" + MethodKind: Instance + Parameters: + - Position: 0 + Nullability: O + +:NoEscape: + + Used only for block parameters. Equivalent to NS_NOESCAPE. + + :: + + - Name: dispatch_sync + Parameters: + - Position: 0 + NoEscape: true + +:SwiftBridge: + + Used for Objective-C class types bridged to Swift value types. An empty + string ("") means a type is not bridged. Not supported outside of Apple + frameworks (the Swift side of it requires conforming to implementation-detail + protocols that are subject to change). + + :: + + - Name: NSIndexSet + SwiftBridge: IndexSet + +:DesignatedInit: + + Used for init methods. Equivalent to NS_DESIGNATED_INITIALIZER. + + :: + + - Selector: "initWithFrame:" + MethodKind: Instance + DesignatedInit: true diff --git a/docs/AddressSanitizer.rst b/docs/AddressSanitizer.rst index 67ef59b5ea2..05888dce6a2 100644 --- a/docs/AddressSanitizer.rst +++ b/docs/AddressSanitizer.rst @@ -119,7 +119,7 @@ force disabled by setting ``ASAN_OPTIONS=symbolize=0``): #1 0x7f7ddabcac4d in __libc_start_main ??:0 ... -Note that on OS X you may need to run ``dsymutil`` on your binary to have the +Note that on macOS you may need to run ``dsymutil`` on your binary to have the file\:line info in the AddressSanitizer reports. Additional Checks @@ -134,14 +134,14 @@ globals defined in another translation unit. To enable this check at runtime, you should set environment variable ``ASAN_OPTIONS=check_initialization_order=1``. -Note that this option is not supported on OS X. +Note that this option is not supported on macOS. Memory leak detection --------------------- For more information on leak detector in AddressSanitizer, see :doc:`LeakSanitizer`. The leak detection is turned on by default on Linux, -and can be enabled using ``ASAN_OPTIONS=detect_leaks=1`` on OS X; +and can be enabled using ``ASAN_OPTIONS=detect_leaks=1`` on macOS; however, it is not yet supported on other platforms. Issue Suppression @@ -273,7 +273,7 @@ Supported Platforms AddressSanitizer is supported on: * Linux i386/x86\_64 (tested on Ubuntu 12.04) -* OS X 10.7 - 10.11 (i386/x86\_64) +* macOS 10.7 - 10.11 (i386/x86\_64) * iOS Simulator * Android ARM * NetBSD i386/x86\_64 diff --git a/docs/AutomaticReferenceCounting.rst b/docs/AutomaticReferenceCounting.rst index 3e51d2f5d79..9e4456085b6 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. @@ -268,7 +268,7 @@ ARC's semantics and restrictions. * There must be reliable conventions for whether and when "ownership" is passed between caller and callee, for both arguments and return values. Objective-C methods follow such a convention very reliably, at least for - system libraries on Mac OS X, and functions always pass objects at +0. The + system libraries on macOS, and functions always pass objects at +0. The C-based APIs for Core Foundation objects, on the other hand, have much more varied transfer semantics. diff --git a/docs/ClangCommandLineReference.rst b/docs/ClangCommandLineReference.rst index e852c3e3879..bad91ff830d 100644 --- a/docs/ClangCommandLineReference.rst +++ b/docs/ClangCommandLineReference.rst @@ -610,6 +610,10 @@ C++ standard library to use Generate code for the given target +.. option:: --print-supported-cpus + +Print supported cpu models for the given target + .. option:: -time Time individual commands @@ -2218,7 +2222,7 @@ Generate branches with extended addressability, usually via indirect jumps. .. option:: -mmacosx-version-min=, -mmacos-version-min= -Set Mac OS X deployment target +Set macOS deployment target .. option:: -mmcu= @@ -2396,6 +2400,15 @@ Generate code which only uses the general purpose registers (AArch64 only) AMDGPU ------ +.. option:: -mcumode, -mno-cumode + +CU wavefront execution mode is used if enabled and WGP wavefront execution mode +is used if disabled (AMDGPU only) + +.. option:: -mwavefrontsize64, -mno-wavefrontsize64 + +Wavefront size 64 is used if enabled and wavefront size 32 if disabled (AMDGPU only) + .. option:: -mxnack, -mno-xnack Enable XNACK (AMDGPU only) @@ -2610,6 +2623,8 @@ X86 .. option:: -mavx512bitalg, -mno-avx512bitalg +.. option:: -mavx512bf16, -mno-avx512bf16 + .. option:: -mavx512bw, -mno-avx512bw .. option:: -mavx512cd, -mno-avx512cd @@ -2632,6 +2647,8 @@ X86 .. option:: -mavx512vnni, -mno-avx512vnni +.. option:: -mavx512vp2intersect, -mno-avx512vp2intersect + .. option:: -mavx512vpopcntdq, -mno-avx512vpopcntdq .. option:: -mbmi, -mno-bmi @@ -2648,6 +2665,8 @@ X86 .. option:: -mcx16, -mno-cx16 +.. option:: -menqcmd, -mno-enqcmd + .. option:: -mf16c, -mno-f16c .. option:: -mfma, -mno-fma diff --git a/docs/ClangFormat.rst b/docs/ClangFormat.rst index f2228c57505..c1347f3070b 100644 --- a/docs/ClangFormat.rst +++ b/docs/ClangFormat.rst @@ -11,12 +11,12 @@ Standalone Tool =============== :program:`clang-format` is located in `clang/tools/clang-format` and can be used -to format C/C++/Java/JavaScript/Objective-C/Protobuf code. +to format C/C++/Java/JavaScript/Objective-C/Protobuf/C# code. .. code-block:: console $ clang-format -help - OVERVIEW: A tool to format C/C++/Java/JavaScript/Objective-C/Protobuf code. + OVERVIEW: A tool to format C/C++/Java/JavaScript/Objective-C/Protobuf/C# code. If no arguments are specified, it formats the code from standard input and writes the result to the standard output. @@ -165,6 +165,19 @@ menu item by renaming the script, and can assign the menu item a keyboard shortcut in the BBEdit preferences, under Menus & Shortcuts. +CLion Integration +================== + +:program:`clang-format` is integrated into `CLion `_ as an alternative code formatter. It is disabled by default and +can be turned on in Settings/Preferences | Editor | Code Style. + +If :program:`clang-format` support is enabled, CLion detects config files when +opening a project and suggests overriding the current IDE settings. Code style +rules from the ``.clang-format`` files are then applied automatically to all +editor actions, including auto-completion, code generation, and refactorings. + + Visual Studio Integration ========================= diff --git a/docs/ClangFormatStyleOptions.rst b/docs/ClangFormatStyleOptions.rst index 054d5c32c6f..1276a41acb4 100644 --- a/docs/ClangFormatStyleOptions.rst +++ b/docs/ClangFormatStyleOptions.rst @@ -7,8 +7,8 @@ supported by :doc:`LibFormat` and :doc:`ClangFormat`. When using :program:`clang-format` command line utility or ``clang::format::reformat(...)`` functions from code, one can either use one of -the predefined styles (LLVM, Google, Chromium, Mozilla, WebKit) or create a -custom style by configuring specific style options. +the predefined styles (LLVM, Google, Chromium, Mozilla, WebKit, Microsoft) or +create a custom style by configuring specific style options. Configuring Style with clang-format @@ -68,6 +68,10 @@ An example of a configuration file for multiple languages: Language: Proto # Don't format .proto files. DisableFormat: true + --- + Language: CSharp + # Use 100 columns for C#. + ColumnLimit: 100 ... An easy way to get a valid ``.clang-format`` file containing all configuration @@ -137,13 +141,16 @@ 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 - `_ + `_ + * ``Microsoft`` + A style complying with `Microsoft's style guide + `_ .. START_FORMAT_STYLE_OPTIONS @@ -270,6 +277,41 @@ the configuration (without a prefix: ``Auto``). int a; // My comment a vs. int a; // My comment a int b = 2; // comment b int b = 2; // comment about b +**AllowAllArgumentsOnNextLine** (``bool``) + If a function call or braced initializer list doesn't fit on a + line, allow putting all arguments onto the next line, even if + ``BinPackArguments`` is ``false``. + + .. code-block:: c++ + + true: + callFunction( + a, b, c, d); + + false: + callFunction(a, + b, + c, + d); + +**AllowAllConstructorInitializersOnNextLine** (``bool``) + If a constructor definition with a member initializer list doesn't + fit on a single line, allow putting all member initializers onto the next + line, if ```ConstructorInitializerAllOnOneLineOrOnePerLine``` is true. + Note that this parameter has no effect if + ```ConstructorInitializerAllOnOneLineOrOnePerLine``` is false. + + .. code-block:: c++ + + true: + MyClass::MyClass() : + member0(0), member1(2) {} + + false: + MyClass::MyClass() : + member0(0), + member1(2) {} + **AllowAllParametersOfDeclarationOnNextLine** (``bool``) If the function declaration doesn't fit on a line, allow putting all parameters of a function declaration onto @@ -367,9 +409,84 @@ the configuration (without a prefix: ``Auto``). -**AllowShortIfStatementsOnASingleLine** (``bool``) +**AllowShortIfStatementsOnASingleLine** (``ShortIfStyle``) If ``true``, ``if (a) return;`` can be put on a single line. + Possible values: + + * ``SIS_Never`` (in configuration: ``Never``) + Never put short ifs on the same line. + + .. code-block:: c++ + + if (a) + return ; + else { + return; + } + + * ``SIS_WithoutElse`` (in configuration: ``WithoutElse``) + Without else put short ifs on the same line only if + the else is not a compound statement. + + .. code-block:: c++ + + if (a) return; + else + return; + + * ``SIS_Always`` (in configuration: ``Always``) + Always put short ifs on the same line if + the else is not a compound statement or not. + + .. code-block:: c++ + + if (a) return; + else { + return; + } + + + +**AllowShortLambdasOnASingleLine** (``ShortLambdaStyle``) + Dependent on the value, ``auto lambda []() { return 0; }`` can be put on a + single line. + + Possible values: + + * ``SLS_None`` (in configuration: ``None``) + Never merge lambdas into a single line. + + * ``SLS_Empty`` (in configuration: ``Empty``) + Only merge empty lambdas. + + .. code-block:: c++ + + auto lambda = [](int a) {} + auto lambda2 = [](int a) { + return a; + }; + + * ``SLS_Inline`` (in configuration: ``Inline``) + Merge lambda into a single line if argument of a function. + + .. code-block:: c++ + + auto lambda = [](int a) { + return a; + }; + sort(a.begin(), a.end(), ()[] { return x < y; }) + + * ``SLS_All`` (in configuration: ``All``) + Merge all lambdas fitting on a single line. + + .. code-block:: c++ + + auto lambda = [](int a) {} + auto lambda2 = [](int a) { return a; }; + + + **AllowShortLoopsOnASingleLine** (``bool``) If ``true``, ``while (true) continue;`` can be put on a single line. @@ -587,6 +704,23 @@ the configuration (without a prefix: ``Auto``). Nested configuration flags: + * ``bool AfterCaseLabel`` Wrap case labels. + + .. code-block:: c++ + + false: true: + switch (foo) { vs. switch (foo) { + case 1: { case 1: + bar(); { + break; bar(); + } break; + default: { } + plop(); default: + } { + } plop(); + } + } + * ``bool AfterClass`` Wrap class definitions. .. code-block:: c++ @@ -925,19 +1059,28 @@ the configuration (without a prefix: ``Auto``). .. code-block:: c++ - try { + try + { foo(); } - catch () { + catch () + { } void foo() { bar(); } - class foo { + class foo + { }; - if (foo()) { + if (foo()) + { } - else { + else + { } - enum X : int { A, B }; + enum X : int + { + A, + B + }; * ``BS_GNU`` (in configuration: ``GNU``) Always break before braces and add an extra level of indentation to @@ -1212,7 +1355,7 @@ the configuration (without a prefix: ``Auto``). true: false: namespace a { vs. namespace a { foo(); foo(); - } // namespace a; } + } // namespace a } **ForEachMacros** (``std::vector``) A vector of macros that should be interpreted as foreach loops @@ -1233,6 +1376,24 @@ the configuration (without a prefix: ``Auto``). For example: BOOST_FOREACH. +**TypenameMacros** (``std::vector``) + A vector of macros that should be interpreted as type declarations + instead of as function calls. + + These are expected to be macros of the form: + + .. code-block: c++ + + STACK_OF(...) + + In the .clang-format configuration file, this can be configured like: + + .. code-block: yaml + + TypenameMacros: ['STACK_OF', 'LIST'] + + For example: OpenSSL STACK_OF, BSD LIST_ENTRY. + **IncludeBlocks** (``IncludeBlocksStyle``) Dependent on the value, multiple ``#include`` blocks can be sorted as one and divided based on category. @@ -1278,7 +1439,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 @@ -1365,6 +1526,17 @@ the configuration (without a prefix: ``Auto``). # endif #endif + * ``PPDIS_BeforeHash`` (in configuration: ``BeforeHash``) + Indents directives before the hash. + + .. code-block:: c++ + + #if FOO + #if BAR + #include + #endif + #endif + **IndentWidth** (``unsigned``) @@ -1496,6 +1668,9 @@ the configuration (without a prefix: ``Auto``). * ``LK_Cpp`` (in configuration: ``Cpp``) Should be used for C, C++. + * ``LK_CSharp`` (in configuration: ``CSharp``) + Should be used for C#. + * ``LK_Java`` (in configuration: ``Java``) Should be used for Java. @@ -1607,6 +1782,19 @@ the configuration (without a prefix: ``Auto``). +**NamespaceMacros** (``std::vector``) + A vector of macros which are used to open namespace blocks. + + These are expected to be macros of the form: + + .. code-block:: c++ + + NAMESPACE(, ...) { + + } + + For example: TESTSUITE + **ObjCBinPackProtocolList** (``BinPackStyle``) Controls bin-packing Objective-C protocol conformance list items into as few lines as possible when they go over ``ColumnLimit``. @@ -1812,6 +2000,14 @@ the configuration (without a prefix: ``Auto``). true: false: (int) i; vs. (int)i; +**SpaceAfterLogicalNot** (``bool``) + If ``true``, a space is inserted after the logical not operator (``!``). + + .. code-block:: c++ + + true: false: + ! someExpression(); vs. !someExpression(); + **SpaceAfterTemplateKeyword** (``bool``) If ``true``, a space will be inserted after the 'template' keyword. @@ -1886,6 +2082,19 @@ the configuration (without a prefix: ``Auto``). } } + * ``SBPO_NonEmptyParentheses`` (in configuration: ``NonEmptyParentheses``) + Put a space before opening parentheses only if the parentheses are not + empty i.e. '()' + + .. code-block:: c++ + + void() { + if (true) { + f(); + g (x, y, z); + } + } + * ``SBPO_Always`` (in configuration: ``Always``) Always put a space before opening parentheses, except when it's prohibited by the syntax rules (in function-like macro definitions) or diff --git a/docs/ClangPlugins.rst b/docs/ClangPlugins.rst index 5e6082e9034..23e037e197c 100644 --- a/docs/ClangPlugins.rst +++ b/docs/ClangPlugins.rst @@ -55,7 +55,7 @@ registering it using ``PragmaHandlerRegistry::Add<>``: class ExamplePragmaHandler : public PragmaHandler { public: ExamplePragmaHandler() : PragmaHandler("example_pragma") { } - void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, Token &PragmaTok) { // Handle the pragma } @@ -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 00000000000..f18fd81384e --- /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 99e8a5e4f68..bc30459957a 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/CommandGuide/clang.rst b/docs/CommandGuide/clang.rst index a75b6c91157..f511022dd77 100644 --- a/docs/CommandGuide/clang.rst +++ b/docs/CommandGuide/clang.rst @@ -316,7 +316,7 @@ number of cross compilers, or may only support a native target. .. option:: -mmacosx-version-min= - When building for Mac OS X, specify the minimum version supported by your + When building for macOS, specify the minimum version supported by your application. .. option:: -miphoneos-version-min @@ -324,6 +324,12 @@ number of cross compilers, or may only support a native target. When building for iPhone OS, specify the minimum version supported by your application. +.. option:: --print-supported-cpus + + Print out a list of supported processors for the given target (specified + through --target= or -arch ). If no target is + specified, the system default target will be used. + .. option:: -march= Specify that Clang should generate code for a specific processor family diff --git a/docs/ControlFlowIntegrity.rst b/docs/ControlFlowIntegrity.rst index b0b37f83f1c..f57bdf5d2cb 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 bb1770da5af..076713201a7 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 94502f9c49e..7d9b1e8359a 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 b92fa3fcc06..58c605a9a83 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 4e6f5d14cde..12e2cc25256 100644 --- a/docs/HardwareAssistedAddressSanitizerDesign.rst +++ b/docs/HardwareAssistedAddressSanitizerDesign.rst @@ -131,7 +131,8 @@ HWASAN: https://www.kernel.org/doc/Documentation/arm64/tagged-pointers.txt). * **Does not require redzones to detect buffer overflows**, but the buffer overflow detection is probabilistic, with roughly - `(2**TS-1)/(2**TS)` probability of catching a bug. + `1/(2**TS)` chance of missing a bug (6.25% or 0.39% with 4 and 8-bit TS + respectively). * **Does not require quarantine to detect heap-use-after-free, or stack-use-after-return**. The detection is similarly probabilistic. @@ -162,7 +163,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 686aca840ad..dfa199ec595 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 b6b49d7547b..e1b5bd7c78f 100644 --- a/docs/InternalsManual.rst +++ b/docs/InternalsManual.rst @@ -423,6 +423,9 @@ Fix-it hints on errors and warnings need to obey these rules: driver, they should only be used when it's very likely they match the user's intent. * Clang must recover from errors as if the fix-it had been applied. +* Fix-it hints on a warning must not change the meaning of the code. + However, a hint may clarify the meaning as intentional, for example by adding + parentheses when the precedence of operators isn't obvious. If a fix-it can't obey these rules, put the fix-it on a note. Fix-its on notes are not applied automatically. @@ -534,7 +537,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 @@ -827,6 +830,79 @@ wrappers. The AST Library =============== +.. _ASTPhilosophy: + +Design philosophy +----------------- + +Immutability +^^^^^^^^^^^^ + +Clang AST nodes (types, declarations, statements, expressions, and so on) are +generally designed to be immutable once created. This provides a number of key +benefits: + + * Canonicalization of the "meaning" of nodes is possible as soon as the nodes + are created, and is not invalidated by later addition of more information. + For example, we :ref:`canonicalize types `, and use a + canonicalized representation of expressions when determining whether two + function template declarations involving dependent expressions declare the + same entity. + * AST nodes can be reused when they have the same meaning. For example, we + reuse ``Type`` nodes when representing the same type (but maintain separate + ``TypeLoc``\s for each instance where a type is written), and we reuse + non-dependent ``Stmt`` and ``Expr`` nodes across instantiations of a + template. + * Serialization and deserialization of the AST to/from AST files is simpler: + we do not need to track modifications made to AST nodes imported from AST + files and serialize separate "update records". + +There are unfortunately exceptions to this general approach, such as: + + * A the first declaration of a redeclarable entity maintains a pointer to the + most recent declaration of that entity, which naturally needs to change as + more declarations are parsed. + * Name lookup tables in declaration contexts change after the namespace + declaration is formed. + * We attempt to maintain only a single declaration for an instantiation of a + template, rather than having distinct declarations for an instantiation of + the declaration versus the definition, so template instantiation often + updates parts of existing declarations. + * Some parts of declarations are required to be instantiated separately (this + includes default arguments and exception specifications), and such + instantiations update the existing declaration. + +These cases tend to be fragile; mutable AST state should be avoided where +possible. + +As a consequence of this design principle, we typically do not provide setters +for AST state. (Some are provided for short-term modifications intended to be +used immediately after an AST node is created and before it's "published" as +part of the complete AST, or where language semantics require after-the-fact +updates.) + +Faithfulness +^^^^^^^^^^^^ + +The AST intends to provide a representation of the program that is faithful to +the original source. We intend for it to be possible to write refactoring tools +using only information stored in, or easily reconstructible from, the Clang AST. +This means that the AST representation should either not desugar source-level +constructs to simpler forms, or -- where made necessary by language semantics +or a clear engineering tradeoff -- should desugar minimally and wrap the result +in a construct representing the original source form. + +For example, ``CXXForRangeStmt`` directly represents the syntactic form of a +range-based for statement, but also holds a semantic representation of the +range declaration and iterator declarations. It does not contain a +fully-desugared ``ForStmt``, however. + +Some AST nodes (for example, ``ParenExpr``) represent only syntax, and others +(for example, ``ImplicitCastExpr``) represent only semantics, but most nodes +will represent a combination of syntax and associated semantics. Inheritance +is typically used when representing different (but related) syntaxes for nodes +with the same or similar semantics. + .. _Type: The ``Type`` class and its subclasses @@ -889,6 +965,8 @@ way to query whether two types are structurally identical to each other, ignoring typedefs. The solution to both of these problems is the idea of canonical types. +.. _CanonicalType: + Canonical Types ^^^^^^^^^^^^^^^ @@ -1149,6 +1227,10 @@ the source code. In the semantics-centric view, only the most recent "``f``" will be found by the lookup, since it effectively replaces the first declaration of "``f``". +(Note that because ``f`` can be redeclared at block scope, or in a friend +declaration, etc. it is possible that the declaration of ``f`` found by name +lookup will not be the most recent one.) + In the semantics-centric view, overloading of functions is represented explicitly. For example, given two declarations of a function "``g``" that are overloaded, e.g., @@ -1313,7 +1395,7 @@ The transparent ``DeclContext``\ s are: Multiply-Defined Declaration Contexts ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -C++ namespaces have the interesting --- and, so far, unique --- property that +C++ namespaces have the interesting property that the namespace can be defined multiple times, and the declarations provided by each namespace definition are effectively merged (from the semantic point of view). For example, the following two code snippets are semantically @@ -1353,6 +1435,18 @@ this context (which will be the only result, for non-namespace contexts) via internally within the lookup and insertion methods of the ``DeclContext``, so the vast majority of clients can ignore them. +Because the same entity can be defined multiple times in different modules, +it is also possible for there to be multiple definitions of (for instance) +a ``CXXRecordDecl``, all of which describe a definition of the same class. +In such a case, only one of those "definitions" is considered by Clang to be +the definiition of the class, and the others are treated as non-defining +declarations that happen to also contain member declarations. Corresponding +members in each definition of such multiply-defined classes are identified +either by redeclaration chains (if the members are ``Redeclarable``) +or by simply a pointer to the canonical declaration (if the declarations +are not ``Redeclarable`` -- in that case, a ``Mergeable`` base class is used +instead). + .. _CFG: The ``CFG`` class @@ -1364,7 +1458,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 +1780,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 +1842,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 +1867,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 +1918,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 +1930,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 +1993,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 +2009,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 f357c03507d..286ab88d01e 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 1f3441b033d..b5766402e2d 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 fe267a60f36..1e4f72902ec 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: @@ -479,44 +479,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 ========================================================= @@ -1041,9 +1055,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 @@ -1359,7 +1373,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 @@ -1782,7 +1796,7 @@ the arguments. Both arguments and the result have the bitwidth specified by the name of the builtin. ``__builtin_rotateright`` -_------------------------ +------------------------- * ``__builtin_rotateright8`` * ``__builtin_rotateright16`` @@ -2223,7 +2237,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**: @@ -2291,6 +2305,61 @@ automatically will insert one if the first argument to `llvm.coro.suspend` is token `none`. If a user calls `__builin_suspend`, clang will insert `token none` as the first argument to the intrinsic. +Source location builtins +------------------------ + +Clang provides experimental builtins to support C++ standard library implementation +of ``std::experimental::source_location`` as specified in http://wg21.link/N4600. +With the exception of ``__builtin_COLUMN``, these builtins are also implemented by +GCC. + +**Syntax**: + +.. code-block:: c + + const char *__builtin_FILE(); + const char *__builtin_FUNCTION(); + unsigned __builtin_LINE(); + unsigned __builtin_COLUMN(); // Clang only + +**Example of use**: + +.. code-block:: c++ + + void my_assert(bool pred, int line = __builtin_LINE(), // Captures line of caller + const char* file = __builtin_FILE(), + const char* function = __builtin_FUNCTION()) { + if (pred) return; + printf("%s:%d assertion failed in function %s\n", file, line, function); + std::abort(); + } + + struct MyAggregateType { + int x; + int line = __builtin_LINE(); // captures line where aggregate initialization occurs + }; + static_assert(MyAggregateType{42}.line == __LINE__); + + struct MyClassType { + int line = __builtin_LINE(); // captures line of the constructor used during initialization + constexpr MyClassType(int) { assert(line == __LINE__); } + }; + +**Description**: + +The builtins ``__builtin_LINE``, ``__builtin_FUNCTION``, and ``__builtin_FILE`` return +the values, at the "invocation point", for ``__LINE__``, ``__FUNCTION__``, and +``__FILE__`` respectively. These builtins are constant expressions. + +When the builtins appear as part of a default function argument the invocation +point is the location of the caller. When the builtins appear as part of a +default member initializer, the invocation point is the location of the +constructor or aggregate initialization used to create the object. Otherwise +the invocation point is the same as the location of the builtin. + +When the invocation point of ``__builtin_FUNCTION`` is not a function scope the +empty string is returned. + Non-standard C++11 Attributes ============================= @@ -2301,10 +2370,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. @@ -2367,6 +2436,103 @@ Which compiles to (on X86-32): movl %gs:(%eax), %eax ret +PowerPC Language Extensions +------------------------------ + +Set the Floating Point Rounding Mode +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +PowerPC64/PowerPC64le supports the builtin function ``__builtin_setrnd`` to set +the floating point rounding mode. This function will use the least significant +two bits of integer argument to set the floating point rounding mode. + +.. code-block:: c++ + + double __builtin_setrnd(int mode); + +The effective values for mode are: + + - 0 - round to nearest + - 1 - round to zero + - 2 - round to +infinity + - 3 - round to -infinity + +Note that the mode argument will modulo 4, so if the int argument is greater +than 3, it will only use the least significant two bits of the mode. +Namely, ``__builtin_setrnd(102))`` is equal to ``__builtin_setrnd(2)``. + +PowerPC Language Extensions +------------------------------ + +Set the Floating Point Rounding Mode +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +PowerPC64/PowerPC64le supports the builtin function ``__builtin_setrnd`` to set +the floating point rounding mode. This function will use the least significant +two bits of integer argument to set the floating point rounding mode. + +.. code-block:: c++ + + double __builtin_setrnd(int mode); + +The effective values for mode are: + + - 0 - round to nearest + - 1 - round to zero + - 2 - round to +infinity + - 3 - round to -infinity + +Note that the mode argument will modulo 4, so if the integer argument is greater +than 3, it will only use the least significant two bits of the mode. +Namely, ``__builtin_setrnd(102))`` is equal to ``__builtin_setrnd(2)``. + +PowerPC Language Extensions +------------------------------ + +Set the Floating Point Rounding Mode +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +PowerPC64/PowerPC64le supports the builtin function ``__builtin_setrnd`` to set +the floating point rounding mode. This function will use the least significant +two bits of integer argument to set the floating point rounding mode. + +.. code-block:: c++ + + double __builtin_setrnd(int mode); + +The effective values for mode are: + + - 0 - round to nearest + - 1 - round to zero + - 2 - round to +infinity + - 3 - round to -infinity + +Note that the mode argument will modulo 4, so if the integer argument is greater +than 3, it will only use the least significant two bits of the mode. +Namely, ``__builtin_setrnd(102))`` is equal to ``__builtin_setrnd(2)``. + +PowerPC cache builtins +^^^^^^^^^^^^^^^^^^^^^^ + +The PowerPC architecture specifies instructions implementing cache operations. +Clang provides builtins that give direct programmer access to these cache +instructions. + +Currently the following builtins are implemented in clang: + +``__builtin_dcbf`` copies the contents of a modified block from the data cache +to main memory and flushes the copy from the data cache. + +**Syntax**: + +.. code-block:: c + + void __dcbf(const void* addr); /* Data Cache Block Flush */ + +**Example of Use**: + +.. code-block:: c + + int a = 1; + __builtin_dcbf (&a); + Extensions for Static Analysis ============================== @@ -2730,7 +2896,9 @@ same namespace. For instance: 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. +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 ------------------- diff --git a/docs/LeakSanitizer.rst b/docs/LeakSanitizer.rst index 3601587c42f..53a3ee15055 100644 --- a/docs/LeakSanitizer.rst +++ b/docs/LeakSanitizer.rst @@ -17,7 +17,7 @@ detection phase. Usage ===== -LeakSanitizer is supported on x86\_64 Linux and OS X. In order to use it, +LeakSanitizer is supported on x86\_64 Linux and macOS. In order to use it, simply build your program with :doc:`AddressSanitizer`: .. code-block:: console diff --git a/docs/LibASTMatchersReference.html b/docs/LibASTMatchersReference.html index 27cb00b6bdf..47f2c8a489e 100644 --- a/docs/LibASTMatchersReference.html +++ b/docs/LibASTMatchersReference.html @@ -645,6 +645,19 @@

Node Matchers

+Matcher<OMPClause>ompDefaultClauseMatcher<OMPDefaultClause>... +
Matches OpenMP ``default`` clause.
+
+Given
+
+  #pragma omp parallel default(none)
+  #pragma omp parallel default(shared)
+  #pragma omp parallel
+
+``ompDefaultClause()`` matches ``default(none)`` and ``default(shared)``.
+
+ + Matcher<QualType>qualTypeMatcher<QualType>...
Matches QualTypes in the clang AST.
 
@@ -718,7 +731,7 @@

Node Matchers

Matcher<Stmt>blockExprMatcher<BlockExpr>... -
MAtches a reference to a block.
+
Matches a reference to a block.
 
 Example: matches "^{}":
   void f() { ^{}(); }
@@ -788,6 +801,11 @@ 

Node Matchers

+Matcher<Stmt>chooseExprMatcher<ChooseExpr>... +
Matches GNU __builtin_choose_expr.
+
+ + Matcher<Stmt>compoundLiteralExprMatcher<CompoundLiteralExpr>...
Matches compound (i.e. non-scalar) literals
 
@@ -1370,6 +1388,20 @@ 

Node Matchers

+Matcher<Stmt>ompExecutableDirectiveMatcher<OMPExecutableDirective>... +
Matches any ``#pragma omp`` executable directive.
+
+Given
+
+  #pragma omp parallel
+  #pragma omp parallel default(none)
+  #pragma omp taskyield
+
+``ompExecutableDirective()`` matches ``omp parallel``,
+``omp parallel default(none)`` and ``omp taskyield``.
+
+ + Matcher<Stmt>opaqueValueExprMatcher<OpaqueValueExpr>...
Matches opaque value expressions. They are used as helpers
 to reference another expressions and can be met
@@ -2608,6 +2640,9 @@ 

Narrowing Matchers

Example: matches the implicit cast around 0 (matcher = castExpr(hasCastKind(CK_NullToPointer))) int *p = 0; + +If the matcher is use from clang-query, CastKind parameter +should be passed as a quoted string. e.g., ofKind("CK_NullToPointer").
@@ -2738,7 +2773,7 @@

Narrowing Matchers

Given __attribute__((device)) void f() { ... } decl(hasAttr(clang::attr::CUDADevice)) matches the function declaration of -f. If the matcher is use from clang-query, attr::Kind parameter should be +f. If the matcher is used from clang-query, attr::Kind parameter should be passed as a quoted string. e.g., hasAttr("attr::CUDADevice").
@@ -2792,6 +2827,29 @@

Narrowing Matchers

+Matcher<Decl>isInStdNamespace +
Matches declarations in the namespace `std`, but not in nested namespaces.
+
+Given
+  class vector {};
+  namespace foo {
+    class vector {};
+    namespace std {
+      class vector {};
+    }
+  }
+  namespace std {
+    inline namespace __1 {
+      class vector {}; // #1
+      namespace experimental {
+        class vector {};
+      }
+    }
+  }
+cxxRecordDecl(hasName("vector"), isInStdNamespace()) will match only #1.
+
+ + Matcher<Decl>isPrivate
Matches private C++ declarations.
 
@@ -3420,6 +3478,66 @@ 

Narrowing Matchers

+Matcher<OMPDefaultClause>isNoneKind +
Matches if the OpenMP ``default`` clause has ``none`` kind specified.
+
+Given
+
+  #pragma omp parallel
+  #pragma omp parallel default(none)
+  #pragma omp parallel default(shared)
+
+``ompDefaultClause(isNoneKind())`` matches only ``default(none)``.
+
+ + +Matcher<OMPDefaultClause>isSharedKind +
Matches if the OpenMP ``default`` clause has ``shared`` kind specified.
+
+Given
+
+  #pragma omp parallel
+  #pragma omp parallel default(none)
+  #pragma omp parallel default(shared)
+
+``ompDefaultClause(isSharedKind())`` matches only ``default(shared)``.
+
+ + +Matcher<OMPExecutableDirective>isAllowedToContainClauseKindOpenMPClauseKind CKind +
Matches if the OpenMP directive is allowed to contain the specified OpenMP
+clause kind.
+
+Given
+
+  #pragma omp parallel
+  #pragma omp parallel for
+  #pragma omp          for
+
+`ompExecutableDirective(isAllowedToContainClause(OMPC_default))`` matches
+``omp parallel`` and ``omp parallel for``.
+
+If the matcher is use from clang-query, ``OpenMPClauseKind`` parameter
+should be passed as a quoted string. e.g.,
+``isAllowedToContainClauseKind("OMPC_default").``
+
+ + +Matcher<OMPExecutableDirective>isStandaloneDirective +
Matches standalone OpenMP directives,
+i.e., directives that can't have a structured block.
+
+Given
+
+  #pragma omp parallel
+  {}
+  #pragma omp taskyield
+
+``ompExecutableDirective(isStandaloneDirective()))`` matches
+``omp taskyield``.
+
+ + Matcher<ObjCMessageExpr>argumentCountIsunsigned N
Checks that a call expression or a constructor call expression has
 a specific number of arguments (including absent default arguments).
@@ -3472,11 +3590,24 @@ 

Narrowing Matchers

+Matcher<ObjCMessageExpr>isClassMessage +
Returns true when the Objective-C message is sent to a class.
+
+Example
+matcher = objcMessageExpr(isClassMessage())
+matches
+  [NSString stringWithFormat:@"format"];
+but not
+  NSString *x = @"hello";
+  [x containsString:@"h"];
+
+ + Matcher<ObjCMessageExpr>isInstanceMessage
Returns true when the Objective-C message is sent to an instance.
 
 Example
-matcher = objcMessagaeExpr(isInstanceMessage())
+matcher = objcMessageExpr(isInstanceMessage())
 matches
   NSString *x = @"hello";
   [x containsString:@"h"];
@@ -3507,6 +3638,18 @@ 

Narrowing Matchers

+Matcher<ObjCMethodDecl>isClassMethod +
Returns true when the Objective-C method declaration is a class method.
+
+Example
+matcher = objcMethodDecl(isClassMethod())
+matches
+@interface I + (void)foo; @end
+but not
+@interface I - (void)bar; @end
+
+ + Matcher<ObjCMethodDecl>isDefinition
Matches if a declaration has a body attached.
 
@@ -3529,6 +3672,18 @@ 

Narrowing Matchers

+Matcher<ObjCMethodDecl>isInstanceMethod +
Returns true when the Objective-C method declaration is an instance method.
+
+Example
+matcher = objcMethodDecl(isInstanceMethod())
+matches
+@interface I - (void)bar; @end
+but not
+@interface I + (void)foo; @end
+
+ + Matcher<ParmVarDecl>hasDefaultArgument
Matches a declaration that has default arguments.
 
@@ -3790,6 +3945,19 @@ 

Narrowing Matchers

+Matcher<Stmt>isOMPStructuredBlock +
Matches the Stmt AST node that is marked as being the structured-block
+of an OpenMP executable directive.
+
+Given
+
+   #pragma omp parallel
+   {}
+
+``stmt(isOMPStructuredBlock()))`` matches ``{}``.
+
+ + Matcher<StringLiteral>hasSizeunsigned N
Matches nodes that have the specified size.
 
@@ -3981,6 +4149,9 @@ 

Narrowing Matchers

int s = sizeof(x) + alignof(x) unaryExprOrTypeTraitExpr(ofKind(UETT_SizeOf)) matches sizeof(x) + +If the matcher is use from clang-query, UnaryExprOrTypeTrait parameter +should be passed as a quoted string. e.g., ofKind("UETT_SizeOf").
@@ -4810,16 +4981,20 @@

AST Traversal Matchers

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 +5032,39 @@

AST Traversal Matchers

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 +5076,20 @@

AST Traversal Matchers

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()`.
 
@@ -5518,6 +5728,32 @@

AST Traversal Matchers

+Matcher<Expr>ignoringElidableConstructorCallast_matchers::Matcher<Expr> InnerMatcher +
Matches expressions that match InnerMatcher that are possibly wrapped in an
+elidable constructor.
+
+In C++17 copy elidable constructors are no longer being
+generated in the AST as it is not permitted by the standard. They are
+however part of the AST in C++14 and earlier. Therefore, to write a matcher
+that works in all language modes, the matcher has to skip elidable
+constructor AST nodes if they appear in the AST. This matcher can be used to
+skip those elidable constructors.
+
+Given
+
+struct H {};
+H G();
+void f() {
+  H D = G();
+}
+
+``varDecl(hasInitializer(any(
+      ignoringElidableConstructorCall(callExpr()),
+      exprWithCleanups(ignoringElidableConstructorCall(callExpr()))))``
+matches ``H D = G()``
+
+ + Matcher<Expr>ignoringImpCastsMatcher<Expr> InnerMatcher
Matches expressions that match InnerMatcher after any implicit casts
 are stripped off.
@@ -5866,6 +6102,15 @@ 

AST Traversal Matchers

+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 +6220,20 @@ 

AST Traversal Matchers

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`.
 
@@ -6092,6 +6341,36 @@

AST Traversal Matchers

+Matcher<OMPExecutableDirective>hasAnyClauseMatcher<OMPClause> InnerMatcher +
Matches any clause in an OpenMP directive.
+
+Given
+
+  #pragma omp parallel
+  #pragma omp parallel default(none)
+
+``ompExecutableDirective(hasAnyClause(anything()))`` matches
+``omp parallel default(none)``.
+
+ + +Matcher<OMPExecutableDirective>hasStructuredBlockMatcher<Stmt> InnerMatcher +
Matches the structured-block of the OpenMP executable directive
+
+Prerequisite: the executable directive must not be standalone directive.
+If it is, it will never match.
+
+Given
+
+   #pragma omp parallel
+   ;
+   #pragma omp parallel
+   {}
+
+``ompExecutableDirective(hasStructuredBlock(nullStmt()))`` will match ``;``
+
+ + Matcher<ObjCMessageExpr>hasAnyArgumentMatcher<Expr> InnerMatcher
Matches any argument of a call expression or a constructor call
 expression, or an ObjC-message-send expression.
@@ -6796,16 +7075,20 @@ 

AST Traversal Matchers

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 8b7ee7f98fa..878f8085de6 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;clang-tools-extra" -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. @@ -94,14 +85,14 @@ going on. First, we'll need to create a new directory for our tool and tell CMake that it exists. As this is not going to be a core clang tool, it will -live in the ``tools/extra`` repository. +live in the ``clang-tools-extra`` repository. .. code-block:: console - cd ~/clang-llvm/llvm/tools/clang - mkdir tools/extra/loop-convert - echo 'add_subdirectory(loop-convert)' >> tools/extra/CMakeLists.txt - vim tools/extra/loop-convert/CMakeLists.txt + cd ~/clang-llvm + mkdir clang-tools-extra/loop-convert + echo 'add_subdirectory(loop-convert)' >> clang-tools-extra/CMakeLists.txt + vim clang-tools-extra/loop-convert/CMakeLists.txt CMakeLists.txt should have the following contents: @@ -121,7 +112,7 @@ CMakeLists.txt should have the following contents: With that done, Ninja will be able to compile our tool. Let's give it something to compile! Put the following into -``tools/extra/loop-convert/LoopConvert.cpp``. A detailed explanation of +``clang-tools-extra/loop-convert/LoopConvert.cpp``. A detailed explanation of why the different parts are needed can be found in the `LibTooling documentation `_. diff --git a/docs/LibTooling.rst b/docs/LibTooling.rst index 41110f5d314..2aaa508a136 100644 --- a/docs/LibTooling.rst +++ b/docs/LibTooling.rst @@ -187,8 +187,8 @@ Clang tools need their builtin headers and search for them the same way Clang does. Thus, the default location to look for builtin headers is in a path ``$(dirname /path/to/tool)/../lib/clang/3.3/include`` relative to the tool binary. This works out-of-the-box for tools running from llvm's toplevel -binary directory after building clang-headers, or if the tool is running from -the binary directory of a clang install next to the clang binary. +binary directory after building clang-resource-headers, or if the tool is +running from the binary directory of a clang install next to the clang binary. Tips: if your tool fails to find ``stddef.h`` or similar headers, call the tool with ``-v`` and look at the search paths it looks through. @@ -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 cd2acae9702..b2486052abf 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/Modules.rst b/docs/Modules.rst index 7aee4ffee2d..34ad55a4876 100644 --- a/docs/Modules.rst +++ b/docs/Modules.rst @@ -360,7 +360,7 @@ The *module-id* should consist of only a single *identifier*, which provides the The ``explicit`` qualifier can only be applied to a submodule, i.e., a module that is nested within another module. The contents of explicit submodules are only made available when the submodule itself was explicitly named in an import declaration or was re-exported from an imported module. -The ``framework`` qualifier specifies that this module corresponds to a Darwin-style framework. A Darwin-style framework (used primarily on Mac OS X and iOS) is contained entirely in directory ``Name.framework``, where ``Name`` is the name of the framework (and, therefore, the name of the module). That directory has the following layout: +The ``framework`` qualifier specifies that this module corresponds to a Darwin-style framework. A Darwin-style framework (used primarily on macOS and iOS) is contained entirely in directory ``Name.framework``, where ``Name`` is the name of the framework (and, therefore, the name of the module). That directory has the following layout: .. parsed-literal:: diff --git a/docs/OpenMPSupport.rst b/docs/OpenMPSupport.rst index e8ec1e371b0..a8bfddce63a 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 109260da905..079fba16711 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 369f944354c..417f572cc06 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,14 @@ 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. +- ``clang -dumpversion`` now returns the version of Clang itself. +- ... New Pragmas in Clang -------------------- -- Clang now supports adding multiple `#pragma clang attribute` attributes into - a scope of pushed attributes. +- ... Attribute Changes in Clang -------------------------- @@ -169,17 +92,10 @@ 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 now treats non-existent files as possible typos for flags, + ``clang-cl /diagnostic:caret /c test.cc`` for example now produces + ``clang: error: no such file or directory: '/diagnostic:caret'; did you mean '/diagnostics:caret'?`` -- 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. -- ... C Language Changes in Clang @@ -209,7 +125,14 @@ C++1z Feature Support Objective-C Language Changes in Clang ------------------------------------- -... +- Fixed encoding of ObjC pointer types that are pointers to typedefs. + +.. code-block:: objc + + typedef NSArray MyArray; + + // clang used to encode this as "^{NSArray=#}" instead of "@". + const char *s0 = @encode(MyArray *); OpenCL C Language Changes in Clang ---------------------------------- @@ -219,34 +142,38 @@ 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. +Build System Changes +-------------------- + +These are major changes to the build system that have happened since the 8.0.0 +release of Clang. Users of the build system should adjust accordingly. + +- In 8.0.0 and below, the install-clang-headers target would install clang's + resource directory headers. This installation is now performed by the + install-clang-resource-headers target. Users of the old install-clang-headers + target should switch to the new install-clang-resource-headers target. The + install-clang-headers target now installs clang's API headers (corresponding + to its libraries), which is consistent with the install-llvm-headers target. + - ... AST Matchers @@ -257,19 +184,26 @@ AST Matchers clang-format ------------ - -- ... +- Add language support for clang-formatting C# files +- Add Microsoft coding style to encapsulate default C# formatting style +- Added new option `PPDIS_BeforeHash` (in configuration: `BeforeHash`) to + `IndentPPDirectives` which indents preprocessor directives before the hash. 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 --------------- -- ... +- The UninitializedObject checker is now considered as stable. + (moved from the 'alpha.cplusplus' to the 'optin.cplusplus' package) ... @@ -278,32 +212,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 b046aa61689..8b5557bf59b 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). @@ -126,7 +126,7 @@ and link command lines. Supported Platforms ------------------- -SafeStack was tested on Linux, NetBSD, FreeBSD and MacOSX. +SafeStack was tested on Linux, NetBSD, FreeBSD and macOS. Low-level API ------------- @@ -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 f3f13c83176..c7cd853dd66 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 da609dcd9de..b1ab4c6e8b2 100644 --- a/docs/ShadowCallStack.rst +++ b/docs/ShadowCallStack.rst @@ -8,28 +8,43 @@ 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, 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). An x86_64 implementation was evaluated using Chromium and was found +to have critical performance and security deficiencies--it was removed in +LLVM 9.0. Details on the x86_64 implementation can be 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. Like the previous implementation of ShadowCallStack on x86_64, 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 +52,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 +186,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 +197,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/ThinLTO.rst b/docs/ThinLTO.rst index 6e6cb801f52..e127413c002 100644 --- a/docs/ThinLTO.rst +++ b/docs/ThinLTO.rst @@ -198,7 +198,7 @@ To bootstrap clang/LLVM with ThinLTO, follow these steps: 1. The host compiler_ must be a version of clang that supports ThinLTO. #. The host linker_ must support ThinLTO (and in the case of gold, must be - `configured with plugins enabled `_. + `configured with plugins enabled `_). #. Use the following additional `CMake variables `_ when configuring the bootstrap compiler build: diff --git a/docs/ThreadSanitizer.rst b/docs/ThreadSanitizer.rst index 0d039bd5b25..ca5dfaafb45 100644 --- a/docs/ThreadSanitizer.rst +++ b/docs/ThreadSanitizer.rst @@ -19,9 +19,11 @@ Supported Platforms ThreadSanitizer is supported on the following OS: -* Linux -* NetBSD +* Android aarch64, x86_64 +* Darwin arm64, x86_64 * FreeBSD +* Linux aarch64, x86_64, powerpc64, powerpc64le +* NetBSD Support for other 64-bit architectures is possible, contributions are welcome. Support for 32-bit platforms is problematic and is not planned. diff --git a/docs/Toolchain.rst b/docs/Toolchain.rst index 3540708a382..da65f14597b 100644 --- a/docs/Toolchain.rst +++ b/docs/Toolchain.rst @@ -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 ddffee85c98..2456f5040d4 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. @@ -295,7 +295,7 @@ UndefinedBehaviorSanitizer is supported on the following operating systems: * NetBSD * FreeBSD * OpenBSD -* OS X 10.6 onwards +* macOS * Windows The runtime library is relatively portable and platform independent. If the OS @@ -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 e47a2e402da..001003a3fa6 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 @@ -324,13 +324,21 @@ output format of the diagnostics that it generates. .. _opt_fsave-optimization-record: -**-fsave-optimization-record** - Write optimization remarks to a YAML file. +.. option:: -fsave-optimization-record[=] + + Write optimization remarks to a separate file. This option, which defaults to off, controls whether Clang writes - optimization reports to a YAML file. By recording diagnostics in a file, - using a structured YAML format, users can parse or sort the remarks in a - convenient way. + optimization reports to a separate file. By recording diagnostics in a file, + users can parse or sort the remarks in a convenient way. + + By default, the serialization format is YAML. + + The supported serialization formats are: + + - .. _opt_fsave_optimization_record_yaml: + + ``-fsave-optimization-record=yaml``: A structured YAML format. .. _opt_foptimization-record-file: @@ -343,7 +351,21 @@ output format of the diagnostics that it generates. If this option is not used, optimization records are output to a file named after the primary file being compiled. If that's "foo.c", for example, - optimization records are output to "foo.opt.yaml". + optimization records are output to "foo.opt.yaml". If a specific + serialization format is specified, the file will be named + "foo.opt.". + +.. _opt_foptimization-record-passes: + +**-foptimization-record-passes** + Only include passes which match a specified regular expression. + + When optimization reports are being output (see + :ref:`-fsave-optimization-record `), this + option controls the passes that will be included in the final report. + + If this option is not used, all the passes are included in the optimization + record. .. _opt_fdiagnostics-show-hotness: @@ -994,7 +1016,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 @@ -1006,7 +1028,7 @@ on-disk cache that contains the vital information necessary to reduce some of the work needed to process a corresponding header file. While details of precompiled headers vary between compilers, precompiled headers have been shown to be highly effective at speeding up program -compilation on systems with very large system headers (e.g., Mac OS X). +compilation on systems with very large system headers (e.g., macOS). Generating a PCH File ^^^^^^^^^^^^^^^^^^^^^ @@ -1482,7 +1504,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 +1543,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 @@ -1745,7 +1767,8 @@ controlled by the GCC-compatible flags ``-fprofile-generate`` and ``-fprofile-use``. Although these flags are semantically equivalent to their GCC counterparts, they *do not* handle GCC-compatible profiles. They are only meant to implement GCC's semantics with respect to -profile creation and use. +profile creation and use. Flag ``-fcs-profile-generate`` also instruments +programs using the same instrumentation method as ``-fprofile-generate``. .. option:: -fprofile-generate[=] @@ -1778,6 +1801,45 @@ profile creation and use. ``LLVM_PROFILE_FILE`` can still be used to override the directory and filename for the profile file at runtime. +.. option:: -fcs-profile-generate[=] + + The ``-fcs-profile-generate`` and ``-fcs-profile-generate=`` flags will use + the same instrumentation method, and generate the same profile as in the + ``-fprofile-generate`` and ``-fprofile-generate=`` flags. The difference is + that the instrumentation is performed after inlining so that the resulted + profile has a better context sensitive information. They cannot be used + together with ``-fprofile-generate`` and ``-fprofile-generate=`` flags. + They are typically used in conjunction with ``-fprofile-use`` flag. + The profile generated by ``-fcs-profile-generate`` and ``-fprofile-generate`` + can be merged by llvm-profdata. A use example: + + .. code-block:: console + + $ clang++ -O2 -fprofile-generate=yyy/zzz code.cc -o code + $ ./code + $ llvm-profdata merge -output=code.profdata yyy/zzz/ + + The first few steps are the same as that in ``-fprofile-generate`` + compilation. Then perform a second round of instrumentation. + + .. code-block:: console + + $ clang++ -O2 -fprofile-use=code.profdata -fcs-profile-generate=sss/ttt \ + -o cs_code + $ ./cs_code + $ llvm-profdata merge -output=cs_code.profdata sss/ttt code.profdata + + The resulted ``cs_code.prodata`` combines ``code.profdata`` and the profile + generated from binary ``cs_code``. Profile ``cs_code.profata`` can be used by + ``-fprofile-use`` compilaton. + + .. code-block:: console + + $ clang++ -O2 -fprofile-use=cs_code.profdata + + The above command will read both profiles to the compiler at the identical + point of instrumenations. + .. option:: -fprofile-use[=] Without any other arguments, ``-fprofile-use`` behaves identically to @@ -1831,9 +1893,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. @@ -2706,7 +2768,7 @@ X86 ^^^ The support for X86 (both 32-bit and 64-bit) is considered stable on -Darwin (Mac OS X), Linux, FreeBSD, and Dragonfly BSD: it has been tested +Darwin (macOS), Linux, FreeBSD, and Dragonfly BSD: it has been tested to correctly compile many large C, C++, Objective-C, and Objective-C++ codebases. @@ -2761,8 +2823,8 @@ backend. Operating System Features and Limitations ----------------------------------------- -Darwin (Mac OS X) -^^^^^^^^^^^^^^^^^ +Darwin (macOS) +^^^^^^^^^^^^^^ Thread Sanitizer is not supported. @@ -2829,7 +2891,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 +2990,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 +3020,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 @@ -2996,6 +3073,8 @@ Execute ``clang-cl /?`` to see a list of supported options: /Yc Generate a pch file for all code up to and including /Yu Load a pch file and use it instead of all code up to and including /Z7 Enable CodeView debug information in object files + /Zc:char8_t Enable C++2a char8_t type + /Zc:char8_t- Disable C++2a char8_t type /Zc:dllexportInlines- Don't dllexport/dllimport inline member functions of dllexport/import classes /Zc:dllexportInlines dllexport/dllimport inline member functions of dllexport/import classes (default) /Zc:sizedDealloc- Disable C++14 sized global deallocation functions @@ -3049,6 +3128,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 +3136,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 +3159,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 +3172,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 +3192,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 +3214,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 00000000000..93b8f0cbf5c --- /dev/null +++ b/docs/analyzer/checkers.rst @@ -0,0 +1,2048 @@ +================== +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: + + +cplusplus +^^^^^^^^^ + +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.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 optin.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 ""*. + +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 +^^^ +macOS 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.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 + } + +alpha.nondeterminism.PointerIteration (C++) +""""""""""""""""""""""""""""""""""""""""""" +Check for non-determinism caused by iterating unordered containers of pointers. + +.. code-block:: c + + void test() { + int a = 1, b = 2; + std::unordered_set UnorderedPtrSet = {&a, &b}; + + for (auto i : UnorderedPtrSet) // warn + f(i); + } + +alpha.nondeterminism.PointerSorting (C++) +""""""""""""""""""""""""""""""""""""""""" +Check for non-determinism caused by sorting of pointers. + +.. code-block:: c + + void test() { + int a = 1, b = 2; + std::vector V = {&a, &b}; + std::sort(V.begin(), V.end()); // 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 00000000000..7e14fbe464f --- /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 00000000000..ac51911aff1 --- /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 00000000000..00ffaac491e --- /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 00000000000..2a4103240fe --- /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 00000000000..b26ddcb3d96 --- /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 00000000000..979a5d97c77 --- /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 00000000000..66ed56fd866 --- /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 00000000000..68c5a4a8f1c --- /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 00000000000..a3d74a765f9 --- /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 99% rename from docs/analyzer/DebugChecks.rst rename to docs/analyzer/developer-docs/DebugChecks.rst index 56ce015d645..3f9bed78604 100644 --- a/docs/analyzer/DebugChecks.rst +++ b/docs/analyzer/developer-docs/DebugChecks.rst @@ -15,7 +15,7 @@ General Analysis Dumpers These checkers are used to dump the results of various infrastructural analyses to stderr. Some checkers also have "view" variants, which will display a graph -using a 'dot' format viewer (such as Graphviz on OS X) instead. +using a 'dot' format viewer (such as Graphviz on macOS) instead. - debug.DumpCallGraph, debug.ViewCallGraph: Show the call graph generated for the current translation unit. This is used to determine the order in which to 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 3842075fcd6..2e8fe37055b 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 af41e4ec8f0..c9dc7a04892 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 ef994b6401e..c963e5b720f 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 93909d0f25d..be6f473dbdf 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 767567f22fd..00000000000 --- 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 19113d0d5a7..dab70266d9d 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -50,9 +50,9 @@ # 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 @@ # 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/doxygen.cfg.in b/docs/doxygen.cfg.in index 61f9120017f..9fe259ae74f 100644 --- a/docs/doxygen.cfg.in +++ b/docs/doxygen.cfg.in @@ -384,7 +384,7 @@ TYPEDEF_HIDES_STRUCT = NO # the optimal cache size from a speed point of view. # Minimum value: 0, maximum value: 9, default value: 0. -LOOKUP_CACHE_SIZE = 2 +LOOKUP_CACHE_SIZE = 3 #--------------------------------------------------------------------------- # Build related configuration options diff --git a/docs/index.rst b/docs/index.rst index 3eb1d160c75..b4d234c08ec 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 @@ -42,6 +43,7 @@ Using Clang as a Compiler MSVCCompatibility OpenMPSupport ThinLTO + APINotes CommandGuide/index FAQ diff --git a/examples/AnnotateFunctions/AnnotateFunctions.cpp b/examples/AnnotateFunctions/AnnotateFunctions.cpp index 375f18f8e09..96eb78eb17d 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 // //===----------------------------------------------------------------------===// // @@ -59,7 +58,7 @@ class PragmaAnnotateHandler : public PragmaHandler { public: PragmaAnnotateHandler() : PragmaHandler("enable_annotate") { } - void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, Token &PragmaTok) override { Token Tok; diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 8c2654840a9..e4fedf3682e 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -3,9 +3,6 @@ if(NOT CLANG_BUILD_EXAMPLES) set(EXCLUDE_FROM_ALL ON) endif() -if(CLANG_ENABLE_STATIC_ANALYZER) -add_subdirectory(analyzer-plugin) -endif() add_subdirectory(clang-interpreter) add_subdirectory(PrintFunctionNames) add_subdirectory(AnnotateFunctions) diff --git a/examples/PrintFunctionNames/PrintFunctionNames.cpp b/examples/PrintFunctionNames/PrintFunctionNames.cpp index 9f6d495caec..e573ac93eb3 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 deleted file mode 100644 index 7c7b2aec198..00000000000 --- a/examples/analyzer-plugin/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -set(LLVM_EXPORTED_SYMBOL_FILE ${CMAKE_CURRENT_SOURCE_DIR}/SampleAnalyzerPlugin.exports) -add_llvm_library(SampleAnalyzerPlugin MODULE MainCallChecker.cpp PLUGIN_TOOL clang) - -if(LLVM_ENABLE_PLUGINS AND (WIN32 OR CYGWIN)) - target_link_libraries(SampleAnalyzerPlugin PRIVATE - clangAnalysis - clangAST - clangStaticAnalyzerCore - LLVMSupport - ) -endif() diff --git a/examples/clang-interpreter/CMakeLists.txt b/examples/clang-interpreter/CMakeLists.txt index b69a82e0541..ae2c0876c85 100644 --- a/examples/clang-interpreter/CMakeLists.txt +++ b/examples/clang-interpreter/CMakeLists.txt @@ -16,7 +16,7 @@ add_clang_executable(clang-interpreter ) add_dependencies(clang-interpreter - clang-headers + clang-resource-headers ) target_link_libraries(clang-interpreter diff --git a/examples/clang-interpreter/Test.cxx b/examples/clang-interpreter/Test.cxx index d39249214dc..ed7fc86f9e5 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 1c83b1d3e75..8fb52700a75 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 3cfec388308..8f26a861171 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 6f483ee28b5..2669c1a792c 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 56d0e36c563..139948f3eda 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 76eeda18010..1eb3442ccb2 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 58c8af5aa47..4af8c93a367 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/FatalErrorHandler.h b/include/clang-c/FatalErrorHandler.h new file mode 100644 index 00000000000..74c9a8fe98b --- /dev/null +++ b/include/clang-c/FatalErrorHandler.h @@ -0,0 +1,33 @@ +/*===-- clang-c/FatalErrorHandler.h - Fatal Error Handling --------*- 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 *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_CLANG_C_FATAL_ERROR_HANDLER_H +#define LLVM_CLANG_C_FATAL_ERROR_HANDLER_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Installs error handler that prints error message to stderr and calls abort(). + * Replaces currently installed error handler (if any). + */ +void clang_install_aborting_llvm_fatal_error_handler(); + +/** + * Removes currently installed error handler (if any). + * If no error handler is intalled, the default strategy is to print error + * message to stderr and call exit(1). + */ +void clang_uninstall_llvm_fatal_error_handler(); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h index c51dfb1598b..07e71bd48d0 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 59 #define CINDEX_VERSION_ENCODE(major, minor) ( \ ((major) * 10000) \ @@ -221,7 +221,12 @@ enum CXCursor_ExceptionSpecificationKind { /** * The exception specification has not been parsed yet. */ - CXCursor_ExceptionSpecificationKind_Unparsed + CXCursor_ExceptionSpecificationKind_Unparsed, + + /** + * The cursor has a __declspec(nothrow) exception specification. + */ + CXCursor_ExceptionSpecificationKind_NoThrow }; /** @@ -1341,7 +1346,17 @@ enum CXTranslationUnit_Flags { /** * Used to indicate that implicit attributes should be visited. */ - CXTranslationUnit_VisitImplicitAttributes = 0x2000 + CXTranslationUnit_VisitImplicitAttributes = 0x2000, + + /** + * Used to indicate that non-errors from included files should be ignored. + * + * If set, clang_getDiagnosticSetFromTU() will not report e.g. warnings from + * included files anymore. This speeds up clang_getDiagnosticSetFromTU() for + * the case where these warnings are not of interest, as for an IDE for + * example, which typically shows only the diagnostics in the main file. + */ + CXTranslationUnit_IgnoreNonErrorsFromIncludedFiles = 0x4000 }; /** @@ -2586,7 +2601,11 @@ enum CXCursorKind { CXCursor_ObjCRuntimeVisible = 435, CXCursor_ObjCBoxable = 436, CXCursor_FlagEnum = 437, - CXCursor_LastAttr = CXCursor_FlagEnum, + CXCursor_ConvergentAttr = 438, + CXCursor_WarnUnusedAttr = 439, + CXCursor_WarnUnusedResultAttr = 440, + CXCursor_AlignedAttr = 441, + CXCursor_LastAttr = CXCursor_AlignedAttr, /* Preprocessing */ CXCursor_PreprocessingDirective = 500, @@ -3311,7 +3330,9 @@ enum CXTypeKind { CXType_OCLIntelSubgroupAVCImeResultDualRefStreamout = 173, CXType_OCLIntelSubgroupAVCImeSingleRefStreamin = 174, - CXType_OCLIntelSubgroupAVCImeDualRefStreamin = 175 + CXType_OCLIntelSubgroupAVCImeDualRefStreamin = 175, + + CXType_ExtVector = 176 }; /** @@ -3838,7 +3859,11 @@ enum CXTypeLayoutError { /** * The Field name is not valid for this record. */ - CXTypeLayoutError_InvalidFieldName = -5 + CXTypeLayoutError_InvalidFieldName = -5, + /** + * The type is undeduced. + */ + CXTypeLayoutError_Undeduced = -6 }; /** @@ -3910,11 +3935,23 @@ CINDEX_LINKAGE CXType clang_Type_getModifiedType(CXType T); */ CINDEX_LINKAGE long long clang_Cursor_getOffsetOfField(CXCursor C); +/** + * Determine whether the given cursor represents an anonymous + * tag or namespace + */ +CINDEX_LINKAGE unsigned clang_Cursor_isAnonymous(CXCursor C); + /** * Determine whether the given cursor represents an anonymous record * declaration. */ -CINDEX_LINKAGE unsigned clang_Cursor_isAnonymous(CXCursor C); +CINDEX_LINKAGE unsigned clang_Cursor_isAnonymousRecordDecl(CXCursor C); + +/** + * Determine whether the given cursor represents an inline namespace + * declaration. + */ +CINDEX_LINKAGE unsigned clang_Cursor_isInlineNamespace(CXCursor C); enum CXRefQualifierKind { /** No ref-qualifier was provided. */ diff --git a/include/clang-c/Platform.h b/include/clang-c/Platform.h index e2a4dccbdaf..5284b533253 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/APINotes/APINotesOptions.h b/include/clang/APINotes/APINotesOptions.h index d1cb16dacfc..4c15e7fc56e 100644 --- a/include/clang/APINotes/APINotesOptions.h +++ b/include/clang/APINotes/APINotesOptions.h @@ -30,9 +30,8 @@ class APINotesOptions { /// The set of search paths where we API notes can be found for /// particular modules. /// - /// The API notes in this directory are stored as - /// .apinotes or .apinotesc, and are only - /// applied when building the module . + /// The API notes in this directory are stored as .apinotes, + /// and are only applied when building the module . std::vector ModuleSearchPaths; }; diff --git a/include/clang/APINotes/APINotesReader.h b/include/clang/APINotes/APINotesReader.h index 06572102a95..f3ad7533b6b 100644 --- a/include/clang/APINotes/APINotesReader.h +++ b/include/clang/APINotes/APINotesReader.h @@ -206,61 +206,6 @@ class APINotesReader { /// /// \returns information about the typedef, if known. VersionedInfo lookupTypedef(StringRef name); - - /// Visitor used when walking the contents of the API notes file. - class Visitor { - public: - virtual ~Visitor(); - - /// Visit an Objective-C class. - virtual void visitObjCClass(ContextID contextID, StringRef name, - const ObjCContextInfo &info, - llvm::VersionTuple swiftVersion); - - /// Visit an Objective-C protocol. - virtual void visitObjCProtocol(ContextID contextID, StringRef name, - const ObjCContextInfo &info, - llvm::VersionTuple swiftVersion); - - /// Visit an Objective-C method. - virtual void visitObjCMethod(ContextID contextID, StringRef selector, - bool isInstanceMethod, - const ObjCMethodInfo &info, - llvm::VersionTuple swiftVersion); - - /// Visit an Objective-C property. - virtual void visitObjCProperty(ContextID contextID, StringRef name, - bool isInstance, - const ObjCPropertyInfo &info, - llvm::VersionTuple swiftVersion); - - /// Visit a global variable. - virtual void visitGlobalVariable(StringRef name, - const GlobalVariableInfo &info, - llvm::VersionTuple swiftVersion); - - /// Visit a global function. - virtual void visitGlobalFunction(StringRef name, - const GlobalFunctionInfo &info, - llvm::VersionTuple swiftVersion); - - /// Visit an enumerator. - virtual void visitEnumConstant(StringRef name, - const EnumConstantInfo &info, - llvm::VersionTuple swiftVersion); - - /// Visit a tag. - virtual void visitTag(StringRef name, const TagInfo &info, - llvm::VersionTuple swiftVersion); - - /// Visit a typedef. - virtual void visitTypedef(StringRef name, const TypedefInfo &info, - llvm::VersionTuple swiftVersion); - }; - - /// Visit the contents of the API notes file, passing each entity to the - /// given visitor. - void visit(Visitor &visitor); }; } // end namespace api_notes diff --git a/include/clang/APINotes/APINotesYAMLCompiler.h b/include/clang/APINotes/APINotesYAMLCompiler.h index 508da65993e..fa991d3a3d0 100644 --- a/include/clang/APINotes/APINotesYAMLCompiler.h +++ b/include/clang/APINotes/APINotesYAMLCompiler.h @@ -35,27 +35,14 @@ namespace api_notes { Dump, }; - enum class OSType { - OSX, - IOS, - TvOS, - WatchOS, - Absent - }; - /// Converts API notes from YAML format to binary format. bool compileAPINotes(llvm::StringRef yamlInput, const FileEntry *sourceFile, llvm::raw_ostream &os, - OSType targetOS, llvm::SourceMgr::DiagHandlerTy diagHandler = nullptr, void *diagHandlerCtxt = nullptr); bool parseAndDumpAPINotes(llvm::StringRef yamlInput); - - /// Converts API notes from the compiled binary format to the YAML format. - bool decompileAPINotes(std::unique_ptr input, - llvm::raw_ostream &os); } // end namespace api_notes } // end namespace clang diff --git a/include/clang/APINotes/Types.h b/include/clang/APINotes/Types.h index 04591621a79..b2ca595b0c3 100644 --- a/include/clang/APINotes/Types.h +++ b/include/clang/APINotes/Types.h @@ -27,9 +27,6 @@ namespace api_notes { /// The file extension used for the source representation of API notes. static const char SOURCE_APINOTES_EXTENSION[] = "apinotes"; -/// The file extension used for the binary representation of API notes. -static const char BINARY_APINOTES_EXTENSION[] = "apinotesc"; - /// Opaque context ID used to refer to an Objective-C class or protocol. class ContextID { public: diff --git a/include/clang/ARCMigrate/ARCMT.h b/include/clang/ARCMigrate/ARCMT.h index 30c24f1cdb1..49e94a92cd0 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 2571ca75be5..641c259b386 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 731307f24e2..76b65b2f688 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 d4057c9da5f..6943479831e 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" @@ -24,14 +24,52 @@ namespace clang { class AddrLabelExpr; class ASTContext; class CharUnits; + class CXXRecordDecl; + class Decl; class DiagnosticBuilder; class Expr; class FieldDecl; - class Decl; + struct PrintingPolicy; + class Type; class ValueDecl; - class CXXRecordDecl; - class QualType; +/// Symbolic representation of typeid(T) for some type T. +class TypeInfoLValue { + const Type *T; + +public: + TypeInfoLValue() : T() {} + explicit TypeInfoLValue(const Type *T); + + const Type *getType() const { return T; } + explicit operator bool() const { return T; } + + void *getOpaqueValue() { return const_cast(T); } + static TypeInfoLValue getFromOpaqueValue(void *Value) { + TypeInfoLValue V; + V.T = reinterpret_cast(Value); + return V; + } + + void print(llvm::raw_ostream &Out, const PrintingPolicy &Policy) const; +}; +} + +namespace llvm { +template<> struct PointerLikeTypeTraits { + static void *getAsVoidPointer(clang::TypeInfoLValue V) { + return V.getOpaqueValue(); + } + static clang::TypeInfoLValue getFromVoidPointer(void *P) { + return clang::TypeInfoLValue::getFromOpaqueValue(P); + } + // Validated by static_assert in APValue.cpp; hardcoded to avoid needing + // to include Type.h. + static constexpr int NumLowBitsAvailable = 3; +}; +} + +namespace clang { /// APValue - This class implements a discriminated union of [uninitialized] /// [APSInt] [APFloat], [Complex APSInt] [Complex APFloat], [Expr + Offset], /// [Vector: N * APValue], [Array: N * APValue] @@ -40,9 +78,13 @@ class APValue { typedef llvm::APFloat APFloat; public: enum ValueKind { - Uninitialized, + /// There is no such object (it's outside its lifetime). + None, + /// This object has an indeterminate value (C++ [basic.indet]). + Indeterminate, Int, Float, + FixedPoint, ComplexInt, ComplexFloat, LValue, @@ -55,14 +97,14 @@ class APValue { }; class LValueBase { - public: - typedef llvm::PointerUnion PtrTy; + typedef llvm::PointerUnion + PtrTy; - LValueBase() : CallIndex(0), Version(0) {} - - template - LValueBase(T P, unsigned I = 0, unsigned V = 0) - : Ptr(P), CallIndex(I), Version(V) {} + public: + LValueBase() : Local{} {} + LValueBase(const ValueDecl *P, unsigned I = 0, unsigned V = 0); + LValueBase(const Expr *P, unsigned I = 0, unsigned V = 0); + static LValueBase getTypeInfo(TypeInfoLValue LV, QualType TypeInfo); template bool is() const { return Ptr.is(); } @@ -77,45 +119,73 @@ class APValue { bool isNull() const; - explicit operator bool () const; + explicit operator bool() const; - PtrTy getPointer() const { - return Ptr; - } + unsigned getCallIndex() const; + unsigned getVersion() const; + QualType getTypeInfoType() const; - unsigned getCallIndex() const { - return CallIndex; - } - - void setCallIndex(unsigned Index) { - CallIndex = Index; - } - - unsigned getVersion() const { - return Version; - } - - bool operator==(const LValueBase &Other) const { - return Ptr == Other.Ptr && CallIndex == Other.CallIndex && - Version == Other.Version; + friend bool operator==(const LValueBase &LHS, const LValueBase &RHS); + friend bool operator!=(const LValueBase &LHS, const LValueBase &RHS) { + return !(LHS == RHS); } + friend llvm::hash_code hash_value(const LValueBase &Base); private: PtrTy Ptr; - unsigned CallIndex, Version; + struct LocalState { + unsigned CallIndex, Version; + }; + union { + LocalState Local; + /// The type std::type_info, if this is a TypeInfoLValue. + void *TypeInfoType; + }; }; + /// A FieldDecl or CXXRecordDecl, along with a flag indicating whether we + /// mean a virtual or non-virtual base class subobject. typedef llvm::PointerIntPair BaseOrMemberType; - union LValuePathEntry { - /// BaseOrMember - The FieldDecl or CXXRecordDecl indicating the next item - /// in the path. An opaque value of type BaseOrMemberType. - void *BaseOrMember; - /// ArrayIndex - The array index of the next item in the path. - uint64_t ArrayIndex; + + /// A non-discriminated union of a base, field, or array index. + class LValuePathEntry { + static_assert(sizeof(uintptr_t) <= sizeof(uint64_t), + "pointer doesn't fit in 64 bits?"); + uint64_t Value; + + public: + LValuePathEntry() : Value() {} + LValuePathEntry(BaseOrMemberType BaseOrMember) + : Value{reinterpret_cast(BaseOrMember.getOpaqueValue())} {} + static LValuePathEntry ArrayIndex(uint64_t Index) { + LValuePathEntry Result; + Result.Value = Index; + return Result; + } + + BaseOrMemberType getAsBaseOrMember() const { + return BaseOrMemberType::getFromOpaqueValue( + reinterpret_cast(Value)); + } + uint64_t getAsArrayIndex() const { return Value; } + + friend bool operator==(LValuePathEntry A, LValuePathEntry B) { + return A.Value == B.Value; + } + friend bool operator!=(LValuePathEntry A, LValuePathEntry B) { + return A.Value != B.Value; + } + friend llvm::hash_code hash_value(LValuePathEntry A) { + return llvm::hash_value(A.Value); + } }; struct NoLValuePath {}; struct UninitArray {}; struct UninitStruct {}; + + friend class ASTReader; + friend class ASTWriter; + private: ValueKind Kind; @@ -168,55 +238,64 @@ class APValue { DataType Data; public: - APValue() : Kind(Uninitialized) {} - explicit APValue(APSInt I) : Kind(Uninitialized) { + APValue() : Kind(None) {} + explicit APValue(APSInt I) : Kind(None) { MakeInt(); setInt(std::move(I)); } - explicit APValue(APFloat F) : Kind(Uninitialized) { + explicit APValue(APFloat F) : Kind(None) { MakeFloat(); setFloat(std::move(F)); } - explicit APValue(const APValue *E, unsigned N) : Kind(Uninitialized) { + explicit APValue(APFixedPoint FX) : Kind(None) { + MakeFixedPoint(std::move(FX)); + } + explicit APValue(const APValue *E, unsigned N) : Kind(None) { MakeVector(); setVector(E, N); } - APValue(APSInt R, APSInt I) : Kind(Uninitialized) { + APValue(APSInt R, APSInt I) : Kind(None) { MakeComplexInt(); setComplexInt(std::move(R), std::move(I)); } - APValue(APFloat R, APFloat I) : Kind(Uninitialized) { + APValue(APFloat R, APFloat I) : Kind(None) { MakeComplexFloat(); setComplexFloat(std::move(R), std::move(I)); } APValue(const APValue &RHS); - APValue(APValue &&RHS) : Kind(Uninitialized) { swap(RHS); } + APValue(APValue &&RHS) : Kind(None) { swap(RHS); } APValue(LValueBase B, const CharUnits &O, NoLValuePath N, bool IsNullPtr = false) - : Kind(Uninitialized) { + : Kind(None) { MakeLValue(); setLValue(B, O, N, IsNullPtr); } APValue(LValueBase B, const CharUnits &O, ArrayRef Path, bool OnePastTheEnd, bool IsNullPtr = false) - : Kind(Uninitialized) { + : Kind(None) { MakeLValue(); setLValue(B, O, Path, OnePastTheEnd, IsNullPtr); } - APValue(UninitArray, unsigned InitElts, unsigned Size) : Kind(Uninitialized) { + APValue(UninitArray, unsigned InitElts, unsigned Size) : Kind(None) { MakeArray(InitElts, Size); } - APValue(UninitStruct, unsigned B, unsigned M) : Kind(Uninitialized) { + APValue(UninitStruct, unsigned B, unsigned M) : Kind(None) { MakeStruct(B, M); } explicit APValue(const FieldDecl *D, const APValue &V = APValue()) - : Kind(Uninitialized) { + : Kind(None) { MakeUnion(); setUnion(D, V); } APValue(const ValueDecl *Member, bool IsDerivedMember, - ArrayRef Path) : Kind(Uninitialized) { + ArrayRef Path) : Kind(None) { MakeMemberPointer(Member, IsDerivedMember, Path); } APValue(const AddrLabelExpr* LHSExpr, const AddrLabelExpr* RHSExpr) - : Kind(Uninitialized) { + : Kind(None) { MakeAddrLabelDiff(); setAddrLabelDiff(LHSExpr, RHSExpr); } + static APValue IndeterminateValue() { + APValue Result; + Result.Kind = Indeterminate; + return Result; + } ~APValue() { - MakeUninit(); + if (Kind != None && Kind != Indeterminate) + DestroyDataAndMakeUninit(); } /// Returns whether the object performed allocations. @@ -230,9 +309,14 @@ class APValue { void swap(APValue &RHS); ValueKind getKind() const { return Kind; } - bool isUninit() const { return Kind == Uninitialized; } + + bool isAbsent() const { return Kind == None; } + bool isIndeterminate() const { return Kind == Indeterminate; } + bool hasValue() const { return Kind != None && Kind != Indeterminate; } + 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; } @@ -246,8 +330,8 @@ class APValue { void dump() const; void dump(raw_ostream &OS) const; - void printPretty(raw_ostream &OS, ASTContext &Ctx, QualType Ty) const; - std::string getAsString(ASTContext &Ctx, QualType Ty) const; + void printPretty(raw_ostream &OS, const ASTContext &Ctx, QualType Ty) const; + std::string getAsString(const ASTContext &Ctx, QualType Ty) const; APSInt &getInt() { assert(isInt() && "Invalid accessor"); @@ -257,6 +341,12 @@ class APValue { return const_cast(this)->getInt(); } + /// Try to convert this value to an integral constant. This works if it's an + /// integer, null pointer, or offset from a null pointer. Returns true on + /// success. + bool toIntegralConstant(APSInt &Result, QualType SrcTy, + const ASTContext &Ctx) const; + APFloat &getFloat() { assert(isFloat() && "Invalid accessor"); return *(APFloat*)(char*)Data.buffer; @@ -265,6 +355,14 @@ class APValue { 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 +504,10 @@ class APValue { 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]; @@ -451,51 +553,52 @@ class APValue { private: void DestroyDataAndMakeUninit(); - void MakeUninit() { - if (Kind != Uninitialized) - DestroyDataAndMakeUninit(); - } void MakeInt() { - assert(isUninit() && "Bad state change"); + assert(isAbsent() && "Bad state change"); new ((void*)Data.buffer) APSInt(1); Kind = Int; } void MakeFloat() { - assert(isUninit() && "Bad state change"); + assert(isAbsent() && "Bad state change"); new ((void*)(char*)Data.buffer) APFloat(0.0); Kind = Float; } + void MakeFixedPoint(APFixedPoint &&FX) { + assert(isAbsent() && "Bad state change"); + new ((void *)(char *)Data.buffer) APFixedPoint(std::move(FX)); + Kind = FixedPoint; + } void MakeVector() { - assert(isUninit() && "Bad state change"); + assert(isAbsent() && "Bad state change"); new ((void*)(char*)Data.buffer) Vec(); Kind = Vector; } void MakeComplexInt() { - assert(isUninit() && "Bad state change"); + assert(isAbsent() && "Bad state change"); new ((void*)(char*)Data.buffer) ComplexAPSInt(); Kind = ComplexInt; } void MakeComplexFloat() { - assert(isUninit() && "Bad state change"); + assert(isAbsent() && "Bad state change"); new ((void*)(char*)Data.buffer) ComplexAPFloat(); Kind = ComplexFloat; } void MakeLValue(); void MakeArray(unsigned InitElts, unsigned Size); void MakeStruct(unsigned B, unsigned M) { - assert(isUninit() && "Bad state change"); + assert(isAbsent() && "Bad state change"); new ((void*)(char*)Data.buffer) StructData(B, M); Kind = Struct; } void MakeUnion() { - assert(isUninit() && "Bad state change"); + assert(isAbsent() && "Bad state change"); new ((void*)(char*)Data.buffer) UnionData(); Kind = Union; } void MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember, ArrayRef Path); void MakeAddrLabelDiff() { - assert(isUninit() && "Bad state change"); + assert(isAbsent() && "Bad state change"); new ((void*)(char*)Data.buffer) AddrLabelDiffData(); Kind = AddrLabelDiff; } diff --git a/include/clang/AST/AST.h b/include/clang/AST/AST.h index 6db351d1064..6d0f274121b 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 1167c566a35..dc216a89c20 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 0e7f15d4021..a473d569e47 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" @@ -265,17 +265,21 @@ class ASTContext : public RefCountedBase { /// Mapping from __block VarDecls to BlockVarCopyInit. llvm::DenseMap BlockVarCopyInits; - /// Mapping from class scope functions specialization to their - /// template patterns. - llvm::DenseMap - ClassScopeSpecializationPattern; - /// Mapping from materialized temporaries with static storage duration /// that appear in constant initializers to their evaluated values. These are /// allocated in a std::map because their address must be stable. llvm::DenseMap MaterializedTemporaryValues; + /// Used to cleanups APValues stored in the AST. + mutable llvm::SmallVector APValueCleanups; + + /// A cache mapping a string value to a StringLiteral object with the same + /// value. + /// + /// This is lazily created. This is intentionally not serialized. + mutable llvm::StringMap StringLiteralCache; + /// Representation of a "canonical" template template parameter that /// is used in canonical template names. class CanonicalTemplateTemplateParm : public llvm::FoldingSetNode { @@ -891,11 +895,6 @@ class ASTContext : public RefCountedBase { TemplateOrSpecializationInfo getTemplateOrSpecializationInfo(const VarDecl *Var); - FunctionDecl *getClassScopeSpecializationPattern(const FunctionDecl *FD); - - void setClassScopeSpecializationPattern(FunctionDecl *FD, - FunctionDecl *Pattern); - /// Note that the static data member \p Inst is an instantiation of /// the static data member template \p Tmpl of a class template. void setInstantiatedFromStaticDataMember(VarDecl *Inst, VarDecl *Tmpl, @@ -1055,6 +1054,9 @@ class ASTContext : public RefCountedBase { #define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \ CanQualType Id##Ty; #include "clang/Basic/OpenCLExtensionTypes.def" +#define SVE_TYPE(Name, Id, SingletonId) \ + CanQualType SingletonId; +#include "clang/Basic/AArch64SVEACLETypes.def" // Types for deductions in C++0x [stmt.ranged]'s desugaring. Built on demand. mutable QualType AutoDeductTy; // Deduction against 'auto'. @@ -1333,6 +1335,10 @@ class ASTContext : public RefCountedBase { ArrayType::ArraySizeModifier ASM, unsigned IndexTypeQuals) const; + /// Return a type for a constant array for a string literal of the + /// specified element type and length. + QualType getStringLiteralArrayType(QualType EltTy, unsigned Length) const; + /// Returns a vla type where known sizes are replaced with [*]. QualType getVariableArrayDecayedType(QualType Ty) const; @@ -1451,6 +1457,9 @@ class ASTContext : public RefCountedBase { QualType getParenType(QualType NamedType) const; + QualType getMacroQualifiedType(QualType UnderlyingTy, + const IdentifierInfo *MacroII) const; + QualType getElaboratedType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, QualType NamedType, TagDecl *OwnedTagDecl = nullptr) const; @@ -1519,7 +1528,7 @@ class ASTContext : public RefCountedBase { /// C++11 deduced auto type. QualType getAutoType(QualType DeducedType, AutoTypeKeyword Keyword, - bool IsDependent) const; + bool IsDependent, bool IsPack = false) const; /// C++11 deduction pattern for 'auto' type. QualType getAutoDeductType() const; @@ -1984,6 +1993,7 @@ class ASTContext : public RefCountedBase { TemplateName getOverloadedTemplateName(UnresolvedSetIterator Begin, UnresolvedSetIterator End) const; + TemplateName getAssumedTemplateName(DeclarationName Name) const; TemplateName getQualifiedTemplateName(NestedNameSpecifier *NNS, bool TemplateKeyword, @@ -2002,6 +2012,9 @@ class ASTContext : public RefCountedBase { /// No error GE_None, + /// Missing a type + GE_Missing_type, + /// Missing a type from GE_Missing_stdio, @@ -2241,7 +2254,8 @@ class ASTContext : public RefCountedBase { VTableContextBase *getVTableContext(); - MangleContext *createMangleContext(); + /// If \p T is null pointer, assume the target in ASTContext. + MangleContext *createMangleContext(const TargetInfo *T = nullptr); void DeepCollectObjCIvars(const ObjCInterfaceDecl *OI, bool leafClass, SmallVectorImpl &Ivars) const; @@ -2387,7 +2401,8 @@ class ASTContext : public RefCountedBase { /// Retrieves the default calling convention for the current target. CallingConv getDefaultCallingConvention(bool IsVariadic, - bool IsCXXMethod) const; + bool IsCXXMethod, + bool IsBuiltin = false) const; /// Retrieves the "canonical" template name that refers to a /// given template. @@ -2504,6 +2519,11 @@ class ASTContext : public RefCountedBase { /// \p LHS < \p RHS, return -1. int getFloatingTypeOrder(QualType LHS, QualType RHS) const; + /// Compare the rank of two floating point types as above, but compare equal + /// if both types have the same floating-point semantics on the target (i.e. + /// long double and double on AArch64 will return 0). + int getFloatingTypeSemanticOrder(QualType LHS, QualType RHS) const; + /// Return a real floating point or a complex type (based on /// \p typeDomain/\p typeSize). /// @@ -2640,6 +2660,12 @@ class ASTContext : public RefCountedBase { // 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 //===--------------------------------------------------------------------===// @@ -2693,7 +2719,7 @@ class ASTContext : public RefCountedBase { /// otherwise returns null. const ObjCInterfaceDecl *getObjContainingInterface(const NamedDecl *ND) const; - /// Set the copy inialization expression of a block var decl. \p CanThrow + /// Set the copy initialization expression of a block var decl. \p CanThrow /// indicates whether the copy expression can throw or not. void setBlockVarCopyInit(const VarDecl* VD, Expr *CopyExpr, bool CanThrow); @@ -2796,51 +2822,60 @@ class ASTContext : public RefCountedBase { APValue *getMaterializedTemporaryValue(const MaterializeTemporaryExpr *E, bool MayCreate); + /// Adds an APValue that will be destructed during the destruction of the + /// ASTContext. + void AddAPValueCleanup(APValue *Ptr) const { APValueCleanups.push_back(Ptr); } + + /// Return a string representing the human readable name for the specified + /// function declaration or file name. Used by SourceLocExpr and + /// PredefinedExpr to cache evaluated results. + StringLiteral *getPredefinedStringLiteralFromCache(StringRef Key) const; + //===--------------------------------------------------------------------===// // Statistics //===--------------------------------------------------------------------===// /// The number of implicitly-declared default constructors. - static unsigned NumImplicitDefaultConstructors; + unsigned NumImplicitDefaultConstructors = 0; /// The number of implicitly-declared default constructors for /// which declarations were built. - static unsigned NumImplicitDefaultConstructorsDeclared; + unsigned NumImplicitDefaultConstructorsDeclared = 0; /// The number of implicitly-declared copy constructors. - static unsigned NumImplicitCopyConstructors; + unsigned NumImplicitCopyConstructors = 0; /// The number of implicitly-declared copy constructors for /// which declarations were built. - static unsigned NumImplicitCopyConstructorsDeclared; + unsigned NumImplicitCopyConstructorsDeclared = 0; /// The number of implicitly-declared move constructors. - static unsigned NumImplicitMoveConstructors; + unsigned NumImplicitMoveConstructors = 0; /// The number of implicitly-declared move constructors for /// which declarations were built. - static unsigned NumImplicitMoveConstructorsDeclared; + unsigned NumImplicitMoveConstructorsDeclared = 0; /// The number of implicitly-declared copy assignment operators. - static unsigned NumImplicitCopyAssignmentOperators; + unsigned NumImplicitCopyAssignmentOperators = 0; /// The number of implicitly-declared copy assignment operators for /// which declarations were built. - static unsigned NumImplicitCopyAssignmentOperatorsDeclared; + unsigned NumImplicitCopyAssignmentOperatorsDeclared = 0; /// The number of implicitly-declared move assignment operators. - static unsigned NumImplicitMoveAssignmentOperators; + unsigned NumImplicitMoveAssignmentOperators = 0; /// The number of implicitly-declared move assignment operators for /// which declarations were built. - static unsigned NumImplicitMoveAssignmentOperatorsDeclared; + unsigned NumImplicitMoveAssignmentOperatorsDeclared = 0; /// The number of implicitly-declared destructors. - static unsigned NumImplicitDestructors; + unsigned NumImplicitDestructors = 0; /// The number of implicitly-declared destructors for which /// declarations were built. - static unsigned NumImplicitDestructorsDeclared; + unsigned NumImplicitDestructorsDeclared = 0; public: /// Initialize built-in types. @@ -2855,18 +2890,51 @@ class ASTContext : public RefCountedBase { private: void InitBuiltinType(CanQualType &R, BuiltinType::Kind K); + class ObjCEncOptions { + unsigned Bits; + + ObjCEncOptions(unsigned Bits) : Bits(Bits) {} + + public: + ObjCEncOptions() : Bits(0) {} + ObjCEncOptions(const ObjCEncOptions &RHS) : Bits(RHS.Bits) {} + +#define OPT_LIST(V) \ + V(ExpandPointedToStructures, 0) \ + V(ExpandStructures, 1) \ + V(IsOutermostType, 2) \ + V(EncodingProperty, 3) \ + V(IsStructField, 4) \ + V(EncodeBlockParameters, 5) \ + V(EncodeClassNames, 6) \ + +#define V(N,I) ObjCEncOptions& set##N() { Bits |= 1 << I; return *this; } +OPT_LIST(V) +#undef V + +#define V(N,I) bool N() const { return Bits & 1 << I; } +OPT_LIST(V) +#undef V + +#undef OPT_LIST + + LLVM_NODISCARD ObjCEncOptions keepingOnly(ObjCEncOptions Mask) const { + return Bits & Mask.Bits; + } + + LLVM_NODISCARD ObjCEncOptions forComponentType() const { + ObjCEncOptions Mask = ObjCEncOptions() + .setIsOutermostType() + .setIsStructField(); + return Bits & ~Mask.Bits; + } + }; + // Return the Objective-C type encoding for a given type. void getObjCEncodingForTypeImpl(QualType t, std::string &S, - bool ExpandPointedToStructures, - bool ExpandStructures, + ObjCEncOptions Options, const FieldDecl *Field, - bool OutermostType = false, - bool EncodingProperty = false, - bool StructField = false, - bool EncodeBlockParameters = false, - bool EncodeClassNames = false, - bool EncodePointerToObjCTypedef = false, - QualType *NotEncodedT=nullptr) const; + QualType *NotEncodedT = nullptr) const; // Adds the encoding of the structure's members. void getObjCEncodingForStructureImpl(RecordDecl *RD, std::string &S, @@ -2986,8 +3054,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 @@ -3010,7 +3078,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); } @@ -3048,7 +3116,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 00000000000..70c8e24f918 --- /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 fe92604587e..d6549e12d92 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/ASTDumper.h b/include/clang/AST/ASTDumper.h new file mode 100644 index 00000000000..61202f057a8 --- /dev/null +++ b/include/clang/AST/ASTDumper.h @@ -0,0 +1,56 @@ +//===--- ASTDumper.h - Dumping implementation for ASTs --------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_ASTDUMPER_H +#define LLVM_CLANG_AST_ASTDUMPER_H + +#include "clang/AST/ASTNodeTraverser.h" +#include "clang/AST/TextNodeDumper.h" + +namespace clang { + +class ASTDumper : public ASTNodeTraverser { + + TextNodeDumper NodeDumper; + + raw_ostream &OS; + + const bool ShowColors; + +public: + ASTDumper(raw_ostream &OS, const comments::CommandTraits *Traits, + const SourceManager *SM) + : ASTDumper(OS, Traits, SM, SM && SM->getDiagnostics().getShowColors()) {} + + ASTDumper(raw_ostream &OS, const comments::CommandTraits *Traits, + const SourceManager *SM, bool ShowColors) + : ASTDumper(OS, Traits, SM, ShowColors, LangOptions()) {} + ASTDumper(raw_ostream &OS, const comments::CommandTraits *Traits, + const SourceManager *SM, bool ShowColors, + const PrintingPolicy &PrintPolicy) + : NodeDumper(OS, ShowColors, SM, PrintPolicy, Traits), OS(OS), + ShowColors(ShowColors) {} + + TextNodeDumper &doGetNodeDelegate() { return NodeDumper; } + + void dumpLookups(const DeclContext *DC, bool DumpDecls); + + template + void dumpTemplateDeclSpecialization(const SpecializationDecl *D, + bool DumpExplicitInst, bool DumpRefOnly); + template + void dumpTemplateDecl(const TemplateDecl *D, bool DumpExplicitInst); + + void VisitFunctionTemplateDecl(const FunctionTemplateDecl *D); + void VisitClassTemplateDecl(const ClassTemplateDecl *D); + void VisitVarTemplateDecl(const VarTemplateDecl *D); +}; + +} // namespace clang + +#endif diff --git a/include/clang/AST/ASTDumperUtils.h b/include/clang/AST/ASTDumperUtils.h index 129c40ce3e1..55a085449a9 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,16 +13,21 @@ #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 { +/// Used to specify the format for printing AST dump information. +enum ASTDumpOutputFormat { + ADOF_Default, + ADOF_JSON +}; + // Colors used for various parts of the AST dump // 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 +42,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 +97,6 @@ class ColorScope { } }; -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 038d5c3d361..93919bbdd52 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 277004361e1..25f45888800 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 // //===----------------------------------------------------------------------===// // @@ -33,7 +32,8 @@ namespace clang { class ASTContext; -class ASTImporterLookupTable; +class ASTImporterSharedState; +class Attr; class CXXBaseSpecifier; class CXXCtorInitializer; class Decl; @@ -43,8 +43,8 @@ class FileManager; class NamedDecl; class Stmt; class TagDecl; +class TranslationUnitDecl; class TypeSourceInfo; -class Attr; class ImportError : public llvm::ErrorInfo { public: @@ -87,14 +87,142 @@ class Attr; using ImportedCXXBaseSpecifierMap = llvm::DenseMap; - private: + enum class ODRHandlingType { Conservative, Liberal }; + + // An ImportPath is the list of the AST nodes which we visit during an + // Import call. + // If node `A` depends on node `B` then the path contains an `A`->`B` edge. + // From the call stack of the import functions we can read the very same + // path. + // + // Now imagine the following AST, where the `->` represents dependency in + // therms of the import. + // ``` + // A->B->C->D + // `->E + // ``` + // We would like to import A. + // The import behaves like a DFS, so we will visit the nodes in this order: + // ABCDE. + // During the visitation we will have the following ImportPaths: + // ``` + // A + // AB + // ABC + // ABCD + // ABC + // AB + // ABE + // AB + // A + // ``` + // If during the visit of E there is an error then we set an error for E, + // then as the call stack shrinks for B, then for A: + // ``` + // A + // AB + // ABC + // ABCD + // ABC + // AB + // ABE // Error! Set an error to E + // AB // Set an error to B + // A // Set an error to A + // ``` + // However, during the import we could import C and D without any error and + // they are independent from A,B and E. + // We must not set up an error for C and D. + // So, at the end of the import we have an entry in `ImportDeclErrors` for + // A,B,E but not for C,D. + // + // Now what happens if there is a cycle in the import path? + // Let's consider this AST: + // ``` + // A->B->C->A + // `->E + // ``` + // During the visitation we will have the below ImportPaths and if during + // the visit of E there is an error then we will set up an error for E,B,A. + // But what's up with C? + // ``` + // A + // AB + // ABC + // ABCA + // ABC + // AB + // ABE // Error! Set an error to E + // AB // Set an error to B + // A // Set an error to A + // ``` + // This time we know that both B and C are dependent on A. + // This means we must set up an error for C too. + // As the call stack reverses back we get to A and we must set up an error + // to all nodes which depend on A (this includes C). + // But C is no longer on the import path, it just had been previously. + // Such situation can happen only if during the visitation we had a cycle. + // If we didn't have any cycle, then the normal way of passing an Error + // object through the call stack could handle the situation. + // This is why we must track cycles during the import process for each + // visited declaration. + class ImportPathTy { + public: + using VecTy = llvm::SmallVector; + + void push(Decl *D) { + Nodes.push_back(D); + ++Aux[D]; + } + + void pop() { + if (Nodes.empty()) + return; + --Aux[Nodes.back()]; + Nodes.pop_back(); + } + + /// Returns true if the last element can be found earlier in the path. + bool hasCycleAtBack() const { + auto Pos = Aux.find(Nodes.back()); + return Pos != Aux.end() && Pos->second > 1; + } + + using Cycle = llvm::iterator_range; + Cycle getCycleAtBack() const { + assert(Nodes.size() >= 2); + return Cycle(Nodes.rbegin(), + std::find(Nodes.rbegin() + 1, Nodes.rend(), Nodes.back()) + + 1); + } + + /// Returns the copy of the cycle. + VecTy copyCycleAtBack() const { + auto R = getCycleAtBack(); + return VecTy(R.begin(), R.end()); + } + + private: + // All the nodes of the path. + VecTy Nodes; + // Auxiliary container to be able to answer "Do we have a cycle ending + // at last element?" as fast as possible. + // We count each Decl's occurrence over the path. + llvm::SmallDenseMap Aux; + }; - /// Pointer to the import specific lookup table, which may be shared - /// amongst several ASTImporter objects. - /// This is an externally managed resource (and should exist during the - /// lifetime of the ASTImporter object) - /// If not set then the original C/C++ lookup is used. - ASTImporterLookupTable *LookupTable = nullptr; + private: + std::shared_ptr SharedState = nullptr; + + /// The path which we go through during the import of a given AST node. + ImportPathTy ImportPath; + /// Sometimes we have to save some part of an import path, so later we can + /// set up properties to the saved nodes. + /// We may have several of these import paths associated to one Decl. + using SavedImportPathsForOneDecl = + llvm::SmallVector; + using SavedImportPathsTy = + llvm::SmallDenseMap; + SavedImportPathsTy SavedImportPaths; /// The contexts we're importing to and from. ASTContext &ToContext, &FromContext; @@ -105,6 +233,8 @@ class Attr; /// Whether to perform a minimal import. bool Minimal; + ODRHandlingType ODRHandling; + /// Whether the last diagnostic came from the "from" context. bool LastDiagFromFrom = false; @@ -116,6 +246,18 @@ class Attr; /// context to the corresponding declarations in the "to" context. llvm::DenseMap ImportedDecls; + /// Mapping from the already-imported declarations in the "from" + /// context to the error status of the import of that declaration. + /// This map contains only the declarations that were not correctly + /// imported. The same declaration may or may not be included in + /// ImportedDecls. This map is updated continuously during imports and never + /// cleared (like ImportedDecls). + llvm::DenseMap ImportDeclErrors; + + /// Mapping from the already-imported declarations in the "to" + /// context to the corresponding declarations in the "from" context. + llvm::DenseMap ImportedFromDecls; + /// Mapping from the already-imported statements in the "from" /// context to the corresponding statements in the "to" context. llvm::DenseMap ImportedStmts; @@ -138,6 +280,15 @@ class Attr; void AddToLookupTable(Decl *ToD); + protected: + /// Can be overwritten by subclasses to implement their own import logic. + /// The overwritten method should call this method if it didn't import the + /// decl on its own. + virtual Expected ImportImpl(Decl *From); + + /// Used only in unittests to verify the behaviour of the error handling. + virtual bool returnWithErrorInTest() { return false; }; + public: /// \param ToContext The context we'll be importing into. @@ -158,7 +309,7 @@ class Attr; ASTImporter(ASTContext &ToContext, FileManager &ToFileManager, ASTContext &FromContext, FileManager &FromFileManager, bool MinimalImport, - ASTImporterLookupTable *LookupTable = nullptr); + std::shared_ptr SharedState = nullptr); virtual ~ASTImporter(); @@ -166,6 +317,8 @@ class Attr; /// to-be-completed forward declarations when possible. bool isMinimalImport() const { return Minimal; } + void setODRHandling(ODRHandlingType T) { ODRHandling = T; } + /// \brief Import the given object, returns the result. /// /// \param To Import the object into this variable. @@ -173,63 +326,51 @@ class Attr; /// \return Error information (success or error). template LLVM_NODISCARD llvm::Error importInto(ImportT &To, const ImportT &From) { - To = Import(From); - if (From && !To) - return llvm::make_error(); - return llvm::Error::success(); - // FIXME: this should be the final code - //auto ToOrErr = Import(From); - //if (ToOrErr) - // To = *ToOrErr; - //return ToOrErr.takeError(); + auto ToOrErr = Import(From); + if (ToOrErr) + To = *ToOrErr; + return ToOrErr.takeError(); } /// Import the given type from the "from" context into the "to" /// context. A null type is imported as a null type (no error). /// /// \returns The equivalent type in the "to" context, or the import error. - llvm::Expected Import_New(QualType FromT); - // FIXME: Remove this version. - QualType Import(QualType FromT); + llvm::Expected Import(QualType FromT); /// Import the given type source information from the /// "from" context into the "to" context. /// /// \returns The equivalent type source information in the "to" /// context, or the import error. - llvm::Expected Import_New(TypeSourceInfo *FromTSI); - // FIXME: Remove this version. - TypeSourceInfo *Import(TypeSourceInfo *FromTSI); + llvm::Expected Import(TypeSourceInfo *FromTSI); /// Import the given attribute from the "from" context into the /// "to" context. /// /// \returns The equivalent attribute in the "to" context, or the import /// error. - llvm::Expected Import_New(const Attr *FromAttr); - // FIXME: Remove this version. - Attr *Import(const Attr *FromAttr); + llvm::Expected Import(const Attr *FromAttr); /// Import the given declaration from the "from" context into the /// "to" context. /// /// \returns The equivalent declaration in the "to" context, or the import /// error. - llvm::Expected Import_New(Decl *FromD); - llvm::Expected Import_New(const Decl *FromD) { - return Import_New(const_cast(FromD)); - } - // FIXME: Remove this version. - Decl *Import(Decl *FromD); - Decl *Import(const Decl *FromD) { + llvm::Expected Import(Decl *FromD); + llvm::Expected Import(const Decl *FromD) { return Import(const_cast(FromD)); } /// Return the copy of the given declaration in the "to" context if /// it has already been imported from the "from" context. Otherwise return - /// NULL. + /// nullptr. Decl *GetAlreadyImportedOrNull(const Decl *FromD) const; + /// Return the translation unit from where the declaration was + /// imported. If it does not exist nullptr is returned. + TranslationUnitDecl *GetFromTU(Decl *ToD); + /// Import the given declaration context from the "from" /// AST context into the "to" AST context. /// @@ -242,28 +383,21 @@ class Attr; /// /// \returns The equivalent expression in the "to" context, or the import /// error. - llvm::Expected Import_New(Expr *FromE); - // FIXME: Remove this version. - Expr *Import(Expr *FromE); + llvm::Expected Import(Expr *FromE); /// Import the given statement from the "from" context into the /// "to" context. /// /// \returns The equivalent statement in the "to" context, or the import /// error. - llvm::Expected Import_New(Stmt *FromS); - // FIXME: Remove this version. - Stmt *Import(Stmt *FromS); + llvm::Expected Import(Stmt *FromS); /// Import the given nested-name-specifier from the "from" /// context into the "to" context. /// /// \returns The equivalent nested-name-specifier in the "to" /// context, or the import error. - llvm::Expected - Import_New(NestedNameSpecifier *FromNNS); - // FIXME: Remove this version. - NestedNameSpecifier *Import(NestedNameSpecifier *FromNNS); + llvm::Expected Import(NestedNameSpecifier *FromNNS); /// Import the given nested-name-specifier-loc from the "from" /// context into the "to" context. @@ -271,42 +405,32 @@ class Attr; /// \returns The equivalent nested-name-specifier-loc in the "to" /// context, or the import error. llvm::Expected - Import_New(NestedNameSpecifierLoc FromNNS); - // FIXME: Remove this version. - NestedNameSpecifierLoc Import(NestedNameSpecifierLoc FromNNS); + Import(NestedNameSpecifierLoc FromNNS); /// Import the given template name from the "from" context into the /// "to" context, or the import error. - llvm::Expected Import_New(TemplateName From); - // FIXME: Remove this version. - TemplateName Import(TemplateName From); + llvm::Expected Import(TemplateName From); /// Import the given source location from the "from" context into /// the "to" context. /// /// \returns The equivalent source location in the "to" context, or the /// import error. - llvm::Expected Import_New(SourceLocation FromLoc); - // FIXME: Remove this version. - SourceLocation Import(SourceLocation FromLoc); + llvm::Expected Import(SourceLocation FromLoc); /// Import the given source range from the "from" context into /// the "to" context. /// /// \returns The equivalent source range in the "to" context, or the import /// error. - llvm::Expected Import_New(SourceRange FromRange); - // FIXME: Remove this version. - SourceRange Import(SourceRange FromRange); + llvm::Expected Import(SourceRange FromRange); /// Import the given declaration name from the "from" /// context into the "to" context. /// /// \returns The equivalent declaration name in the "to" context, or the /// import error. - llvm::Expected Import_New(DeclarationName FromName); - // FIXME: Remove this version. - DeclarationName Import(DeclarationName FromName); + llvm::Expected Import(DeclarationName FromName); /// Import the given identifier from the "from" context /// into the "to" context. @@ -320,46 +444,32 @@ class Attr; /// /// \returns The equivalent selector in the "to" context, or the import /// error. - llvm::Expected Import_New(Selector FromSel); - // FIXME: Remove this version. - Selector Import(Selector FromSel); + llvm::Expected Import(Selector FromSel); /// Import the given file ID from the "from" context into the /// "to" context. /// /// \returns The equivalent file ID in the source manager of the "to" /// context, or the import error. - llvm::Expected Import_New(FileID, bool IsBuiltin = false); - // FIXME: Remove this version. - FileID Import(FileID, bool IsBuiltin = false); + llvm::Expected Import(FileID, bool IsBuiltin = false); /// Import the given C++ constructor initializer from the "from" /// context into the "to" context. /// /// \returns The equivalent initializer in the "to" context, or the import /// error. - llvm::Expected - Import_New(CXXCtorInitializer *FromInit); - // FIXME: Remove this version. - CXXCtorInitializer *Import(CXXCtorInitializer *FromInit); + llvm::Expected Import(CXXCtorInitializer *FromInit); /// Import the given CXXBaseSpecifier from the "from" context into /// the "to" context. /// /// \returns The equivalent CXXBaseSpecifier in the source manager of the /// "to" context, or the import error. - llvm::Expected - Import_New(const CXXBaseSpecifier *FromSpec); - // FIXME: Remove this version. - CXXBaseSpecifier *Import(const CXXBaseSpecifier *FromSpec); + llvm::Expected Import(const CXXBaseSpecifier *FromSpec); /// Import the definition of the given declaration, including all of /// the declarations it contains. - LLVM_NODISCARD llvm::Error ImportDefinition_New(Decl *From); - - // FIXME: Compatibility function. - // Usages of this should be changed to ImportDefinition_New. - void ImportDefinition(Decl *From); + LLVM_NODISCARD llvm::Error ImportDefinition(Decl *From); /// Cope with a name conflict when importing a declaration into the /// given context. @@ -386,12 +496,11 @@ class Attr; /// /// \param NumDecls the number of conflicting declarations in \p Decls. /// - /// \returns the name that the newly-imported declaration should have. - virtual DeclarationName HandleNameConflict(DeclarationName Name, - DeclContext *DC, - unsigned IDNS, - NamedDecl **Decls, - unsigned NumDecls); + /// \returns the name that the newly-imported declaration should have. Or + /// an error if we can't handle the name conflict. + virtual Expected + HandleNameConflict(DeclarationName Name, DeclContext *DC, unsigned IDNS, + NamedDecl **Decls, unsigned NumDecls); /// Retrieve the context that AST nodes are being imported into. ASTContext &getToContext() const { return ToContext; } @@ -422,9 +531,13 @@ class Attr; /// Subclasses can override this function to observe all of the \c From -> /// \c To declaration mappings as they are imported. - virtual Decl *Imported(Decl *From, Decl *To) { return To; } + virtual void Imported(Decl *From, Decl *To) {} + + void RegisterImportedDecl(Decl *FromD, Decl *ToD); /// Store and assign the imported declaration to its counterpart. + /// It may happen that several decls from the 'from' context are mapped to + /// the same decl in the 'to' context. Decl *MapImported(Decl *From, Decl *To); /// Called by StructuralEquivalenceContext. If a RecordDecl is @@ -435,6 +548,14 @@ class Attr; /// importation, eliminating this loop. virtual Decl *GetOriginalDecl(Decl *To) { return nullptr; } + /// Return if import of the given declaration has failed and if yes + /// the kind of the problem. This gives the first error encountered with + /// the node. + llvm::Optional getImportDeclErrorIfAny(Decl *FromD) const; + + /// Mark (newly) imported declaration with error. + void setImportDeclError(Decl *From, ImportError Error); + /// Determine whether the given types are structurally /// equivalent. bool IsStructurallyEquivalent(QualType From, QualType To, @@ -445,7 +566,6 @@ class Attr; /// \returns The index of the field in its parent context (starting from 0). /// On error `None` is returned (parent context is non-record). static llvm::Optional getFieldIndex(Decl *F); - }; } // namespace clang diff --git a/include/clang/AST/ASTImporterLookupTable.h b/include/clang/AST/ASTImporterLookupTable.h index 14cafe817dd..407478a5105 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/ASTImporterSharedState.h b/include/clang/AST/ASTImporterSharedState.h new file mode 100644 index 00000000000..e384950590e --- /dev/null +++ b/include/clang/AST/ASTImporterSharedState.h @@ -0,0 +1,80 @@ +//===- ASTImporterSharedState.h - ASTImporter specific state --*- C++ -*---===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the ASTImporter specific state, which may be shared +// amongst several ASTImporter objects. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_ASTIMPORTERSHAREDSTATE_H +#define LLVM_CLANG_AST_ASTIMPORTERSHAREDSTATE_H + +#include "clang/AST/ASTImporterLookupTable.h" +#include "llvm/ADT/DenseMap.h" +// FIXME We need this because of ImportError. +#include "clang/AST/ASTImporter.h" + +namespace clang { + +class TranslationUnitDecl; + +/// Importer specific state, which may be shared amongst several ASTImporter +/// objects. +class ASTImporterSharedState { + + /// Pointer to the import specific lookup table. + std::unique_ptr LookupTable; + + /// Mapping from the already-imported declarations in the "to" + /// context to the error status of the import of that declaration. + /// This map contains only the declarations that were not correctly + /// imported. The same declaration may or may not be included in + /// ImportedFromDecls. This map is updated continuously during imports and + /// never cleared (like ImportedFromDecls). + llvm::DenseMap ImportErrors; + + // FIXME put ImportedFromDecls here! + // And from that point we can better encapsulate the lookup table. + +public: + ASTImporterSharedState() = default; + + ASTImporterSharedState(TranslationUnitDecl &ToTU) { + LookupTable = llvm::make_unique(ToTU); + } + + ASTImporterLookupTable *getLookupTable() { return LookupTable.get(); } + + void addDeclToLookup(Decl *D) { + if (LookupTable) + if (auto *ND = dyn_cast(D)) + LookupTable->add(ND); + } + + void removeDeclFromLookup(Decl *D) { + if (LookupTable) + if (auto *ND = dyn_cast(D)) + LookupTable->remove(ND); + } + + llvm::Optional getImportDeclErrorIfAny(Decl *ToD) const { + auto Pos = ImportErrors.find(ToD); + if (Pos != ImportErrors.end()) + return Pos->second; + else + return Optional(); + } + + void setImportDeclError(Decl *To, ImportError Error) { + ImportErrors[To] = Error; + } +}; + +} // namespace clang +#endif // LLVM_CLANG_AST_ASTIMPORTERSHAREDSTATE_H diff --git a/include/clang/AST/ASTLambda.h b/include/clang/AST/ASTLambda.h index 6fedcb8d380..c1153168e41 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 80184e1cc74..8879f9f3229 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 // //===----------------------------------------------------------------------===// // @@ -128,6 +127,11 @@ class ASTMutationListener { virtual void DeclarationMarkedOpenMPDeclareTarget(const Decl *D, const Attr *Attr) {} + /// A declaration is marked as a variable with OpenMP allocator. + /// + /// \param D the declaration marked as a variable with OpenMP allocator. + virtual void DeclarationMarkedOpenMPAllocate(const Decl *D, const Attr *A) {} + /// A definition has been made visible by being redefined locally. /// /// \param D The definition that was previously not visible. diff --git a/include/clang/AST/ASTNodeTraverser.h b/include/clang/AST/ASTNodeTraverser.h new file mode 100644 index 00000000000..1d4025f63bb --- /dev/null +++ b/include/clang/AST/ASTNodeTraverser.h @@ -0,0 +1,649 @@ +//===--- 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 Visit(const ast_type_traits::DynTypedNode &N) { + // FIXME: Improve this with a switch or a visitor pattern. + if (const auto *D = N.get()) + Visit(D); + else if (const auto *S = N.get()) + Visit(S); + else if (const auto *QT = N.get()) + Visit(*QT); + else if (const auto *T = N.get()) + Visit(T); + else if (const auto *C = N.get()) + Visit(C); + else if (const auto *C = N.get()) + Visit(C); + else if (const auto *T = N.get()) + Visit(*T); + } + + 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 + dumpASTTemplateArgumentListInfo(const ASTTemplateArgumentListInfo *TALI) { + if (!TALI) + return; + + 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()); + } + + void VisitOMPAllocateDecl(const OMPAllocateDecl *D) { + for (const auto *E : D->varlists()) + Visit(E); + for (const auto *C : D->clauselists()) + Visit(C); + } + + 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()); + dumpASTTemplateArgumentListInfo(D->getTemplateArgsAsWritten()); + } + 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 f8847505bc7..70e0daa08a9 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 // //===----------------------------------------------------------------------===// // @@ -112,6 +111,10 @@ struct StructuralEquivalenceContext { static llvm::Optional findUntaggedStructOrUnionIndex(RecordDecl *Anon); + // If ErrorOnTagTypeMismatch is set, return the the error, otherwise get the + // relevant warning for the input error diagnostic. + unsigned getApplicableDiagnostic(unsigned ErrorDiagnostic); + private: /// Finish checking all of the structural equivalences. /// diff --git a/include/clang/AST/ASTTypeTraits.h b/include/clang/AST/ASTTypeTraits.h index 9df9793370c..a29a04e5d24 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 // //===----------------------------------------------------------------------===// // @@ -19,6 +18,7 @@ #include "clang/AST/ASTFwd.h" #include "clang/AST/Decl.h" #include "clang/AST/NestedNameSpecifier.h" +#include "clang/AST/OpenMPClause.h" #include "clang/AST/Stmt.h" #include "clang/AST/TemplateBase.h" #include "clang/AST/TypeLoc.h" @@ -38,6 +38,17 @@ struct PrintingPolicy; namespace ast_type_traits { +/// Defines how we descend a level in the AST when we pass +/// through expressions. +enum TraversalKind { + /// Will traverse all child nodes. + TK_AsIs, + + /// Will not traverse implicit casts and parentheses. + /// Corresponds to Expr::IgnoreParenImpCasts() + TK_IgnoreImplicitCastsAndParentheses +}; + /// Kind identifier. /// /// It can be constructed from any node kind and allows for runtime type @@ -59,6 +70,7 @@ class ASTNodeKind { static ASTNodeKind getFromNode(const Decl &D); static ASTNodeKind getFromNode(const Stmt &S); static ASTNodeKind getFromNode(const Type &T); + static ASTNodeKind getFromNode(const OMPClause &C); /// \} /// Returns \c true if \c this and \c Other represent the same kind. @@ -137,6 +149,9 @@ class ASTNodeKind { NKI_Type, #define TYPE(DERIVED, BASE) NKI_##DERIVED##Type, #include "clang/AST/TypeNodes.def" + NKI_OMPClause, +#define OPENMP_CLAUSE(TextualSpelling, Class) NKI_##Class, +#include "clang/Basic/OpenMPKinds.def" NKI_NumberOfKinds }; @@ -184,12 +199,15 @@ KIND_TO_KIND_ID(TypeLoc) KIND_TO_KIND_ID(Decl) KIND_TO_KIND_ID(Stmt) KIND_TO_KIND_ID(Type) +KIND_TO_KIND_ID(OMPClause) #define DECL(DERIVED, BASE) KIND_TO_KIND_ID(DERIVED##Decl) #include "clang/AST/DeclNodes.inc" #define STMT(DERIVED, BASE) KIND_TO_KIND_ID(DERIVED) #include "clang/AST/StmtNodes.inc" #define TYPE(DERIVED, BASE) KIND_TO_KIND_ID(DERIVED##Type) #include "clang/AST/TypeNodes.def" +#define OPENMP_CLAUSE(TextualSpelling, Class) KIND_TO_KIND_ID(Class) +#include "clang/Basic/OpenMPKinds.def" #undef KIND_TO_KIND_ID inline raw_ostream &operator<<(raw_ostream &OS, ASTNodeKind K) { @@ -460,6 +478,11 @@ struct DynTypedNode::BaseConverter< T, typename std::enable_if::value>::type> : public DynCastPtrConverter {}; +template +struct DynTypedNode::BaseConverter< + T, typename std::enable_if::value>::type> + : public DynCastPtrConverter {}; + template <> struct DynTypedNode::BaseConverter< NestedNameSpecifier, void> : public PtrConverter {}; diff --git a/include/clang/AST/ASTUnresolvedSet.h b/include/clang/AST/ASTUnresolvedSet.h index 9bf63bb6e2d..8d2b23b3539 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 80cd6b7007a..d5a04767ca1 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 3ca24cd434d..6e7e184e3ab 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 a8d162b6aa7..ad87e142a21 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 00000000000..d271db010ed --- /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