27 changes: 9 additions & 18 deletions clang/bindings/python/tests/cindex/test_cdb.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,14 @@
import os
from clang.cindex import Config

from clang.cindex import CompilationDatabase, CompilationDatabaseError, Config

if "CLANG_LIBRARY_PATH" in os.environ:
Config.set_library_path(os.environ["CLANG_LIBRARY_PATH"])

from clang.cindex import CompilationDatabase
from clang.cindex import CompilationDatabaseError
from clang.cindex import CompileCommands
from clang.cindex import CompileCommand
import os
import gc
import unittest
import sys
from .util import skip_if_no_fspath
from .util import str_to_path

from pathlib import Path

kInputsDir = os.path.join(os.path.dirname(__file__), "INPUTS")

Expand All @@ -31,7 +25,7 @@ def test_create_fail(self):
with open(os.devnull, "wb") as null:
os.dup2(null.fileno(), 2)
with self.assertRaises(CompilationDatabaseError) as cm:
cdb = CompilationDatabase.fromDirectory(path)
CompilationDatabase.fromDirectory(path)
os.dup2(stderr, 2)
os.close(stderr)

Expand All @@ -40,21 +34,18 @@ def test_create_fail(self):

def test_create(self):
"""Check we can load a compilation database"""
cdb = CompilationDatabase.fromDirectory(kInputsDir)
CompilationDatabase.fromDirectory(kInputsDir)

def test_lookup_succeed(self):
"""Check we get some results if the file exists in the db"""
cdb = CompilationDatabase.fromDirectory(kInputsDir)
cmds = cdb.getCompileCommands("/home/john.doe/MyProject/project.cpp")
self.assertNotEqual(len(cmds), 0)

@skip_if_no_fspath
def test_lookup_succeed_pathlike(self):
"""Same as test_lookup_succeed, but with PathLikes"""
cdb = CompilationDatabase.fromDirectory(str_to_path(kInputsDir))
cmds = cdb.getCompileCommands(
str_to_path("/home/john.doe/MyProject/project.cpp")
)
cdb = CompilationDatabase.fromDirectory(Path(kInputsDir))
cmds = cdb.getCompileCommands(Path("/home/john.doe/MyProject/project.cpp"))
self.assertNotEqual(len(cmds), 0)

def test_all_compilecommand(self):
Expand Down Expand Up @@ -175,7 +166,7 @@ def test_compilationDB_references(self):
cmds = cdb.getCompileCommands("/home/john.doe/MyProject/project.cpp")
del cdb
gc.collect()
workingdir = cmds[0].directory
cmds[0].directory

def test_compilationCommands_references(self):
"""Ensure CompilationsCommand keeps a reference to CompilationCommands"""
Expand All @@ -185,4 +176,4 @@ def test_compilationCommands_references(self):
cmd0 = cmds[0]
del cmds
gc.collect()
workingdir = cmd0.directory
cmd0.directory
15 changes: 6 additions & 9 deletions clang/bindings/python/tests/cindex/test_code_completion.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
import os
from clang.cindex import Config

from clang.cindex import Config, TranslationUnit

if "CLANG_LIBRARY_PATH" in os.environ:
Config.set_library_path(os.environ["CLANG_LIBRARY_PATH"])

from clang.cindex import TranslationUnit

import unittest
from .util import skip_if_no_fspath
from .util import str_to_path
from pathlib import Path


class TestCodeCompletion(unittest.TestCase):
Expand Down Expand Up @@ -57,11 +55,10 @@ def test_code_complete(self):
]
self.check_completion_results(cr, expected)

@skip_if_no_fspath
def test_code_complete_pathlike(self):
files = [
(
str_to_path("fake.c"),
Path("fake.c"),
"""
/// Aaa.
int test1;
Expand All @@ -77,14 +74,14 @@ def test_code_complete_pathlike(self):
]

tu = TranslationUnit.from_source(
str_to_path("fake.c"),
Path("fake.c"),
["-std=c99"],
unsaved_files=files,
options=TranslationUnit.PARSE_INCLUDE_BRIEF_COMMENTS_IN_CODE_COMPLETION,
)

cr = tu.codeComplete(
str_to_path("fake.c"),
Path("fake.c"),
9,
1,
unsaved_files=files,
Expand Down
8 changes: 4 additions & 4 deletions clang/bindings/python/tests/cindex/test_comment.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import os
from clang.cindex import Config

from clang.cindex import Config, TranslationUnit

if "CLANG_LIBRARY_PATH" in os.environ:
Config.set_library_path(os.environ["CLANG_LIBRARY_PATH"])

from clang.cindex import TranslationUnit
from tests.cindex.util import get_cursor

import unittest

from .util import get_cursor


class TestComment(unittest.TestCase):
def test_comment(self):
Expand Down
29 changes: 14 additions & 15 deletions clang/bindings/python/tests/cindex/test_cursor.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,23 @@
import os
from clang.cindex import Config

from clang.cindex import (
AvailabilityKind,
BinaryOperator,
Config,
CursorKind,
StorageClass,
TemplateArgumentKind,
TranslationUnit,
TypeKind,
)

if "CLANG_LIBRARY_PATH" in os.environ:
Config.set_library_path(os.environ["CLANG_LIBRARY_PATH"])

import ctypes
import gc
import unittest

from clang.cindex import AvailabilityKind
from clang.cindex import CursorKind
from clang.cindex import TemplateArgumentKind
from clang.cindex import TranslationUnit
from clang.cindex import TypeKind
from clang.cindex import BinaryOperator
from clang.cindex import StorageClass
from .util import get_cursor
from .util import get_cursors
from .util import get_tu

from .util import get_cursor, get_cursors, get_tu

kInput = """\
struct s0 {
Expand Down Expand Up @@ -170,7 +169,7 @@ def test_references(self):
self.assertIsInstance(cursor.translation_unit, TranslationUnit)

# If the TU was destroyed, this should cause a segfault.
parent = cursor.semantic_parent
cursor.semantic_parent

def test_canonical(self):
source = "struct X; struct X; struct X { int member; };"
Expand Down Expand Up @@ -344,7 +343,7 @@ class Bar {
)

self.assertEqual(len(copy_assignment_operators_cursors), 10)
self.assertTrue(len(non_copy_assignment_operators_cursors), 9)
self.assertEqual(len(non_copy_assignment_operators_cursors), 7)

self.assertTrue(
all(
Expand Down
5 changes: 2 additions & 3 deletions clang/bindings/python/tests/cindex/test_cursor_kind.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import os
from clang.cindex import Config

from clang.cindex import Config, CursorKind

if "CLANG_LIBRARY_PATH" in os.environ:
Config.set_library_path(os.environ["CLANG_LIBRARY_PATH"])

from clang.cindex import CursorKind

import unittest


Expand Down
7 changes: 3 additions & 4 deletions clang/bindings/python/tests/cindex/test_diagnostics.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import os
from clang.cindex import Config

from clang.cindex import Config, Diagnostic

if "CLANG_LIBRARY_PATH" in os.environ:
Config.set_library_path(os.environ["CLANG_LIBRARY_PATH"])

from clang.cindex import *
from .util import get_tu

import unittest

from .util import get_tu

# FIXME: We need support for invalid translation units to test better.

Expand Down
16 changes: 8 additions & 8 deletions clang/bindings/python/tests/cindex/test_enums.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import unittest

from clang.cindex import (
TokenKind,
AccessSpecifier,
AvailabilityKind,
BinaryOperator,
CursorKind,
TemplateArgumentKind,
ExceptionSpecificationKind,
AvailabilityKind,
AccessSpecifier,
TypeKind,
RefQualifierKind,
LinkageKind,
TLSKind,
RefQualifierKind,
StorageClass,
BinaryOperator,
TemplateArgumentKind,
TLSKind,
TokenKind,
TypeKind,
)


Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
import os
from clang.cindex import Config

from clang.cindex import Config, CursorKind, ExceptionSpecificationKind

if "CLANG_LIBRARY_PATH" in os.environ:
Config.set_library_path(os.environ["CLANG_LIBRARY_PATH"])

import clang.cindex
from clang.cindex import ExceptionSpecificationKind
from .util import get_tu

import unittest

from .util import get_tu


def find_function_declarations(node, declarations=[]):
if node.kind == clang.cindex.CursorKind.FUNCTION_DECL:
if node.kind == CursorKind.FUNCTION_DECL:
declarations.append(node)
for child in node.get_children():
declarations = find_function_declarations(child, declarations)
Expand Down
5 changes: 2 additions & 3 deletions clang/bindings/python/tests/cindex/test_file.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import os
from clang.cindex import Config

from clang.cindex import Config, File, Index

if "CLANG_LIBRARY_PATH" in os.environ:
Config.set_library_path(os.environ["CLANG_LIBRARY_PATH"])

from clang.cindex import Index, File

import unittest


Expand Down
8 changes: 3 additions & 5 deletions clang/bindings/python/tests/cindex/test_index.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
import os
from clang.cindex import Config

from clang.cindex import Config, Index, TranslationUnit

if "CLANG_LIBRARY_PATH" in os.environ:
Config.set_library_path(os.environ["CLANG_LIBRARY_PATH"])

from clang.cindex import *
import os
import unittest


kInputsDir = os.path.join(os.path.dirname(__file__), "INPUTS")


class TestIndex(unittest.TestCase):
def test_create(self):
index = Index.create()
Index.create()

# FIXME: test Index.read

Expand Down
12 changes: 4 additions & 8 deletions clang/bindings/python/tests/cindex/test_linkage.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
import os
from clang.cindex import Config

from clang.cindex import Config, LinkageKind

if "CLANG_LIBRARY_PATH" in os.environ:
Config.set_library_path(os.environ["CLANG_LIBRARY_PATH"])

from clang.cindex import LinkageKind
from clang.cindex import Cursor
from clang.cindex import TranslationUnit

from .util import get_cursor
from .util import get_tu

import unittest

from .util import get_cursor, get_tu


class TestLinkage(unittest.TestCase):
def test_linkage(self):
Expand Down
19 changes: 10 additions & 9 deletions clang/bindings/python/tests/cindex/test_location.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
import os
from clang.cindex import Config

from clang.cindex import (
Config,
Cursor,
File,
SourceLocation,
SourceRange,
TranslationUnit,
)

if "CLANG_LIBRARY_PATH" in os.environ:
Config.set_library_path(os.environ["CLANG_LIBRARY_PATH"])

from clang.cindex import Cursor
from clang.cindex import File
from clang.cindex import SourceLocation
from clang.cindex import SourceRange
from clang.cindex import TranslationUnit
from .util import get_cursor
from .util import get_tu

import unittest

from .util import get_cursor, get_tu

baseInput = "int one;\nint two;\n"

Expand Down
10 changes: 2 additions & 8 deletions clang/bindings/python/tests/cindex/test_rewrite.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
import unittest
import tempfile
import unittest

from clang.cindex import (
Rewriter,
TranslationUnit,
File,
SourceLocation,
SourceRange,
)
from clang.cindex import File, Rewriter, SourceLocation, SourceRange, TranslationUnit


class TestRewrite(unittest.TestCase):
Expand Down
4 changes: 2 additions & 2 deletions clang/bindings/python/tests/cindex/test_source_range.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import os
from clang.cindex import Config

from clang.cindex import Config, SourceLocation, SourceRange, TranslationUnit

if "CLANG_LIBRARY_PATH" in os.environ:
Config.set_library_path(os.environ["CLANG_LIBRARY_PATH"])

import unittest
from clang.cindex import SourceLocation, SourceRange, TranslationUnit

from .util import get_tu

Expand Down
12 changes: 4 additions & 8 deletions clang/bindings/python/tests/cindex/test_tls_kind.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
import os
from clang.cindex import Config

from clang.cindex import Config, TLSKind

if "CLANG_LIBRARY_PATH" in os.environ:
Config.set_library_path(os.environ["CLANG_LIBRARY_PATH"])

from clang.cindex import TLSKind
from clang.cindex import Cursor
from clang.cindex import TranslationUnit

from .util import get_cursor
from .util import get_tu

import unittest

from .util import get_cursor, get_tu


class TestTLSKind(unittest.TestCase):
def test_tls_kind(self):
Expand Down
5 changes: 2 additions & 3 deletions clang/bindings/python/tests/cindex/test_token_kind.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import os
from clang.cindex import Config

from clang.cindex import Config, TokenKind

if "CLANG_LIBRARY_PATH" in os.environ:
Config.set_library_path(os.environ["CLANG_LIBRARY_PATH"])

from clang.cindex import TokenKind

import unittest


Expand Down
11 changes: 3 additions & 8 deletions clang/bindings/python/tests/cindex/test_tokens.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,14 @@
import os
from clang.cindex import Config

from clang.cindex import Config, CursorKind, SourceLocation, SourceRange, TokenKind

if "CLANG_LIBRARY_PATH" in os.environ:
Config.set_library_path(os.environ["CLANG_LIBRARY_PATH"])

from clang.cindex import CursorKind
from clang.cindex import Index
from clang.cindex import SourceLocation
from clang.cindex import SourceRange
from clang.cindex import TokenKind
import unittest

from .util import get_tu

import unittest


class TestTokens(unittest.TestCase):
def test_token_to_cursor(self):
Expand Down
58 changes: 25 additions & 33 deletions clang/bindings/python/tests/cindex/test_translation_unit.py
Original file line number Diff line number Diff line change
@@ -1,30 +1,28 @@
import os
from clang.cindex import Config

from clang.cindex import (
Config,
Cursor,
CursorKind,
File,
Index,
SourceLocation,
SourceRange,
TranslationUnit,
TranslationUnitLoadError,
TranslationUnitSaveError,
)

if "CLANG_LIBRARY_PATH" in os.environ:
Config.set_library_path(os.environ["CLANG_LIBRARY_PATH"])

from contextlib import contextmanager
import gc
import os
import sys
import tempfile
import unittest
from contextlib import contextmanager
from pathlib import Path

from clang.cindex import CursorKind
from clang.cindex import Cursor
from clang.cindex import File
from clang.cindex import Index
from clang.cindex import SourceLocation
from clang.cindex import SourceRange
from clang.cindex import TranslationUnitSaveError
from clang.cindex import TranslationUnitLoadError
from clang.cindex import TranslationUnit
from .util import get_cursor
from .util import get_tu
from .util import skip_if_no_fspath
from .util import str_to_path

from .util import get_cursor, get_tu

kInputsDir = os.path.join(os.path.dirname(__file__), "INPUTS")

Expand All @@ -47,7 +45,7 @@ def save_tu_pathlike(tu):
Returns the filename it was saved to.
"""
with tempfile.NamedTemporaryFile() as t:
tu.save(str_to_path(t.name))
tu.save(Path(t.name))
yield t.name


Expand Down Expand Up @@ -105,32 +103,29 @@ def test_unsaved_files(self):
self.assertEqual(spellings[-1], "y")

def test_unsaved_files_2(self):
if sys.version_info.major >= 3:
from io import StringIO
else:
from io import BytesIO as StringIO
from io import StringIO

tu = TranslationUnit.from_source(
"fake.c", unsaved_files=[("fake.c", StringIO("int x;"))]
)
spellings = [c.spelling for c in tu.cursor.get_children()]
self.assertEqual(spellings[-1], "x")

@skip_if_no_fspath
def test_from_source_accepts_pathlike(self):
tu = TranslationUnit.from_source(
str_to_path("fake.c"),
Path("fake.c"),
["-Iincludes"],
unsaved_files=[
(
str_to_path("fake.c"),
Path("fake.c"),
"""
#include "fake.h"
int x;
int SOME_DEFINE;
""",
),
(
str_to_path("includes/fake.h"),
Path("includes/fake.h"),
"""
#define SOME_DEFINE y
""",
Expand Down Expand Up @@ -192,7 +187,6 @@ def test_save(self):
self.assertTrue(os.path.exists(path))
self.assertGreater(os.path.getsize(path), 0)

@skip_if_no_fspath
def test_save_pathlike(self):
"""Ensure TranslationUnit.save() works with PathLike filename."""

Expand Down Expand Up @@ -234,14 +228,13 @@ def test_load(self):
# Just in case there is an open file descriptor somewhere.
del tu2

@skip_if_no_fspath
def test_load_pathlike(self):
"""Ensure TranslationUnits can be constructed from saved files -
PathLike variant."""
tu = get_tu("int foo();")
self.assertEqual(len(tu.diagnostics), 0)
with save_tu(tu) as path:
tu2 = TranslationUnit.from_ast_file(filename=str_to_path(path))
tu2 = TranslationUnit.from_ast_file(filename=Path(path))
self.assertEqual(len(tu2.diagnostics), 0)

foo = get_cursor(tu2, "foo")
Expand All @@ -268,18 +261,17 @@ def test_get_file(self):
with self.assertRaises(Exception):
f = tu.get_file("foobar.cpp")

@skip_if_no_fspath
def test_get_file_pathlike(self):
"""Ensure tu.get_file() works appropriately with PathLike filenames."""

tu = get_tu("int foo();")

f = tu.get_file(str_to_path("t.c"))
f = tu.get_file(Path("t.c"))
self.assertIsInstance(f, File)
self.assertEqual(f.name, "t.c")

with self.assertRaises(Exception):
f = tu.get_file(str_to_path("foobar.cpp"))
f = tu.get_file(Path("foobar.cpp"))

def test_get_source_location(self):
"""Ensure tu.get_source_location() works."""
Expand Down
18 changes: 6 additions & 12 deletions clang/bindings/python/tests/cindex/test_type.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,14 @@
import os
from clang.cindex import Config

from clang.cindex import Config, CursorKind, RefQualifierKind, TranslationUnit, TypeKind

if "CLANG_LIBRARY_PATH" in os.environ:
Config.set_library_path(os.environ["CLANG_LIBRARY_PATH"])

import gc
import unittest

from clang.cindex import CursorKind
from clang.cindex import TranslationUnit
from clang.cindex import TypeKind
from clang.cindex import RefQualifierKind
from .util import get_cursor
from .util import get_cursors
from .util import get_tu

from .util import get_cursor, get_cursors, get_tu

kInput = """\
Expand Down Expand Up @@ -138,7 +132,7 @@ def test_references(self):
self.assertIsInstance(t.translation_unit, TranslationUnit)

# If the TU was destroyed, this should cause a segfault.
decl = t.get_declaration()
t.get_declaration()

def testConstantArray(self):
tu = get_tu(constarrayInput)
Expand Down Expand Up @@ -459,8 +453,8 @@ def test_offset(self):
(["-target", "i386-pc-win32"], (8, 16, 0, 32, 64, 96)),
(["-target", "msp430-none-none"], (2, 14, 0, 32, 64, 96)),
]
for flags, values in tries:
align, total, f1, bariton, foo, bar = values
for _, values in tries:
_, _, f1, bariton, foo, bar = values
tu = get_tu(source)
teststruct = get_cursor(tu, "Test")
children = list(teststruct.get_children())
Expand Down
20 changes: 1 addition & 19 deletions clang/bindings/python/tests/cindex/util.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,6 @@
# This file provides common utility functions for the test suite.

import os

HAS_FSPATH = hasattr(os, "fspath")

if HAS_FSPATH:
from pathlib import Path as str_to_path
else:
str_to_path = None

import unittest

from clang.cindex import Cursor
from clang.cindex import TranslationUnit
from clang.cindex import Cursor, TranslationUnit


def get_tu(source, lang="c", all_warnings=False, flags=[]):
Expand Down Expand Up @@ -81,14 +69,8 @@ def get_cursors(source, spelling):
return cursors


skip_if_no_fspath = unittest.skipUnless(
HAS_FSPATH, "Requires file system path protocol / Python 3.6+"
)

__all__ = [
"get_cursor",
"get_cursors",
"get_tu",
"skip_if_no_fspath",
"str_to_path",
]
18 changes: 18 additions & 0 deletions clang/docs/APINotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -169,13 +169,31 @@ declaration kind), all of which are optional:
to ``SWIFT_RETURNS_INDEPENDENT_VALUE``) or ``computed_property`` (equivalent to
``SWIFT_COMPUTED_PROPERTY``).

::

Tags:
- Name: OwnedStorage
SwiftImportAs: owned

:SwiftRetainOp, SwiftReleaseOp:

Controls the lifetime operations of a class which uses custom reference
counting. The class must be annotated as a reference type using
``SwiftImportAs: reference``. The values are either names of global functions,
each taking a single parameter of a pointer type, or ``immortal`` for a type
that is considered alive for the duration of the program.

::

Tags:
- Name: RefCountedStorage
SwiftImportAs: reference
SwiftReleaseOp: RCRelease
SwiftRetainOp: RCRetain
- Name: ImmortalSingleton
SwiftImportAs: reference
SwiftReleaseOp: immortal
SwiftRetainOp: immortal

:SwiftCopyable:

Expand Down
2 changes: 1 addition & 1 deletion clang/docs/ClangFormatStyleOptions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2259,7 +2259,7 @@ the configuration (without a prefix: ``Auto``).
**BraceWrapping** (``BraceWrappingFlags``) :versionbadge:`clang-format 3.8` :ref:`¶ <BraceWrapping>`
Control of individual brace wrapping cases.

If ``BreakBeforeBraces`` is set to ``BS_Custom``, use this to specify how
If ``BreakBeforeBraces`` is set to ``Custom``, use this to specify how
each individual brace case should be handled. Otherwise, this is ignored.

.. code-block:: yaml
Expand Down
82 changes: 82 additions & 0 deletions clang/docs/ClangSYCLLinker.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
=======================
Clang SYCL Linker
=======================

.. contents::
:local:

.. _clang-sycl-linker:

Introduction
============

This tool works as a wrapper around the SYCL device code linking process.
The purpose of this tool is to provide an interface to link SYCL device bitcode
in LLVM IR format, SYCL device bitcode in SPIR-V IR format, and native binary
objects, and then use the SPIR-V LLVM Translator tool on fully linked device
objects to produce the final output.
After the linking stage, the fully linked device code in LLVM IR format may
undergo several SYCL-specific finalization steps before the SPIR-V code
generation step.
The tool will also support the Ahead-Of-Time (AOT) compilation flow. AOT
compilation is the process of invoking the back-end at compile time to produce
the final binary, as opposed to just-in-time (JIT) compilation when final code
generation is deferred until application runtime.

Device code linking for SYCL offloading has several known quirks that
make it difficult to use in a unified offloading setting. Two of the primary
issues are:
1. Several finalization steps are required to be run on the fully linked LLVM
IR bitcode to guarantee conformance to SYCL standards. This step is unique to
the SYCL offloading compilation flow.
2. The SPIR-V LLVM Translator tool is an external tool and hence SPIR-V IR code
generation cannot be done as part of LTO. This limitation can be lifted once
the SPIR-V backend is available as a viable LLVM backend.

This tool has been proposed to work around these issues.

Usage
=====

This tool can be used with the following options. Several of these options will
be passed down to downstream tools like 'llvm-link', 'llvm-spirv', etc.

.. code-block:: console
OVERVIEW: A utility that wraps around the SYCL device code linking process.
This enables linking and code generation for SPIR-V JIT targets and AOT
targets.
USAGE: clang-sycl-linker [options]
OPTIONS:
--arch <value> Specify the name of the target architecture.
--dry-run Print generated commands without running.
-g Specify that this was a debug compile.
-help-hidden Display all available options
-help Display available options (--help-hidden for more)
--library-path=<dir> Set the library path for SYCL device libraries
--device-libs=<value> A comma separated list of device libraries that are linked during the device link
-o <path> Path to file to write output
--save-temps Save intermediate results
--triple <value> Specify the target triple.
--version Display the version number and exit
-v Print verbose information
-spirv-dump-device-code=<dir> Directory to dump SPIR-V IR code into
-is-windows-msvc-env Specify if we are compiling under windows environment
-llvm-spirv-options=<value> Pass options to llvm-spirv tool
--llvm-spirv-path=<dir> Set the system llvm-spirv path
Example
=======

This tool is intended to be invoked when targeting any of the target offloading
toolchains. When the --sycl-link option is passed to the clang driver, the
driver will invoke the linking job of the target offloading toolchain, which in
turn will invoke this tool. This tool can be used to create one or more fully
linked device images that are ready to be wrapped and linked with host code to
generate the final executable.

.. code-block:: console
clang-sycl-linker --triple spirv64 --arch native input.bc
6 changes: 3 additions & 3 deletions clang/docs/LanguageExtensions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3979,9 +3979,9 @@ standard:
- ``4`` - to nearest, ties away from zero
The effect of passing some other value to ``__builtin_flt_rounds`` is
implementation-defined. ``__builtin_set_flt_rounds`` is currently only supported
to work on x86, x86_64, Arm and AArch64 targets. These builtins read and modify
the floating-point environment, which is not always allowed and may have unexpected
behavior. Please see the section on `Accessing the floating point environment <https://clang.llvm.org/docs/UsersManual.html#accessing-the-floating-point-environment>`_ for more information.
to work on x86, x86_64, powerpc, powerpc64, Arm and AArch64 targets. These builtins
read and modify the floating-point environment, which is not always allowed and may
have unexpected behavior. Please see the section on `Accessing the floating point environment <https://clang.llvm.org/docs/UsersManual.html#accessing-the-floating-point-environment>`_ for more information.
String builtins
---------------
Expand Down
4 changes: 2 additions & 2 deletions clang/docs/RealtimeSanitizer.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ projects. RTSan can be used to detect real-time violations, i.e. calls to method
that are not safe for use in functions with deterministic run time requirements.
RTSan considers any function marked with the ``[[clang::nonblocking]]`` attribute
to be a real-time function. At run-time, if RTSan detects a call to ``malloc``,
``free``, ``pthread_mutex_lock``, or anything else that could have a
``free``, ``pthread_mutex_lock``, or anything else known to have a
non-deterministic execution time in a function marked ``[[clang::nonblocking]]``
RTSan raises an error.
it raises an error.

RTSan performs its analysis at run-time but shares the ``[[clang::nonblocking]]``
attribute with the :doc:`FunctionEffectAnalysis` system, which operates at
Expand Down
23 changes: 23 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,19 @@ Removed Compiler Flags
Attribute Changes in Clang
--------------------------

- The ``swift_attr`` can now be applied to types. To make it possible to use imported APIs
in Swift safely there has to be a way to annotate individual parameters and result types
with relevant attributes that indicate that e.g. a block is called on a particular actor
or it accepts a Sendable or global-actor (i.e. ``@MainActor``) isolated parameter.

For example:

.. code-block:: objc
@interface MyService
-(void) handle: (void (^ __attribute__((swift_attr("@Sendable"))))(id)) handler;
@end
- Clang now disallows more than one ``__attribute__((ownership_returns(class, idx)))`` with
different class names attached to one function.

Expand Down Expand Up @@ -546,6 +559,7 @@ Bug Fixes to C++ Support
- Fixed an assertion failure in debug mode, and potential crashes in release mode, when
diagnosing a failed cast caused indirectly by a failed implicit conversion to the type of the constructor parameter.
- Fixed an assertion failure by adjusting integral to boolean vector conversions (#GH108326)
- Fixed a crash when mixture of designated and non-designated initializers in union. (#GH113855)
- Fixed an issue deducing non-type template arguments of reference type. (#GH73460)
- Fixed an issue in constraint evaluation, where type constraints on the lambda expression
containing outer unexpanded parameters were not correctly expanded. (#GH101754)
Expand Down Expand Up @@ -576,6 +590,7 @@ Bug Fixes to C++ Support
- Fixed an assertion failure in range calculations for conditional throw expressions. (#GH111854)
- Clang now correctly ignores previous partial specializations of member templates explicitly specialized for
an implicitly instantiated class template specialization. (#GH51051)
- Fixed an assertion failure caused by invalid enum forward declarations. (#GH112208)

Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down Expand Up @@ -662,6 +677,7 @@ X86 Support
- Supported intrinsics for ``MOVRS AND AVX10.2``.
* Supported intrinsics of ``_mm(256|512)_(mask(z))_loadrs_epi(8|16|32|64)``.
- Support ISA of ``AMX-FP8``.
- Support ISA of ``AMX-TRANSPOSE``.

Arm and AArch64 Support
^^^^^^^^^^^^^^^^^^^^^^^
Expand Down Expand Up @@ -856,6 +872,13 @@ Sanitizers
This new flag should allow those projects to enable integer sanitizers with
less noise.

- ``-fsanitize=signed-integer-overflow``, ``-fsanitize=unsigned-integer-overflow``,
``-fsanitize=implicit-signed-integer-truncation``, ``-fsanitize=implicit-unsigned-integer-truncation``,
``-fsanitize=enum`` now properly support the
"type" prefix within `Sanitizer Special Case Lists (SSCL)
<https://clang.llvm.org/docs/SanitizerSpecialCaseList.html>`_. See that link
for examples.

Python Binding Changes
----------------------
- Fixed an issue that led to crashes when calling ``Type.get_exception_specification_kind``.
Expand Down
61 changes: 58 additions & 3 deletions clang/docs/SanitizerSpecialCaseList.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@ file at compile-time.
Goal and usage
==============

Users of sanitizer tools, such as :doc:`AddressSanitizer`, :doc:`ThreadSanitizer`
or :doc:`MemorySanitizer` may want to disable or alter some checks for
certain source-level entities to:
Users of sanitizer tools, such as :doc:`AddressSanitizer`,
:doc:`HardwareAssistedAddressSanitizerDesign`, :doc:`ThreadSanitizer`,
:doc:`MemorySanitizer` or :doc:`UndefinedBehaviorSanitizer` may want to disable
or alter some checks for certain source-level entities to:

* speedup hot function, which is known to be correct;
* ignore a function that does some low-level magic (e.g. walks through the
Expand Down Expand Up @@ -48,6 +49,60 @@ Example
$ clang -fsanitize=address -fsanitize-ignorelist=ignorelist.txt foo.c ; ./a.out
# No error report here.
Usage with UndefinedBehaviorSanitizer
=====================================

``unsigned-integer-overflow``, ``signed-integer-overflow``,
``implicit-signed-integer-truncation``,
``implicit-unsigned-integer-truncation``, and ``enum`` sanitizers support the
ability to adjust instrumentation based on type.

By default, supported sanitizers will have their instrumentation disabled for
types specified within an ignorelist.

.. code-block:: bash
$ cat foo.c
void foo() {
int a = 2147483647; // INT_MAX
++a; // Normally, an overflow with -fsanitize=signed-integer-overflow
}
$ cat ignorelist.txt
[signed-integer-overflow]
type:int
$ clang -fsanitize=signed-integer-overflow -fsanitize-ignorelist=ignorelist.txt foo.c ; ./a.out
# no signed-integer-overflow error
For example, supplying the above ``ignorelist.txt`` to
``-fsanitize-ignorelist=ignorelist.txt`` disables overflow sanitizer
instrumentation for arithmetic operations containing values of type ``int``.

The ``=sanitize`` category is also supported. Any types assigned to the
``sanitize`` category will have their sanitizer instrumentation remain. If the
same type appears within or across ignorelists with different categories the
``sanitize`` category takes precedence -- regardless of order.

With this, one may disable instrumentation for some or all types and
specifically allow instrumentation for one or many types -- including types
created via ``typedef``. This is a way to achieve a sort of "allowlist" for
supported sanitizers.

.. code-block:: bash
$ cat ignorelist.txt
[implicit-signed-integer-truncation]
type:*
type:T=sanitize
$ cat foo.c
typedef char T;
typedef char U;
void foo(int toobig) {
T a = toobig; // instrumented
U b = toobig; // not instrumented
char c = toobig; // also not instrumented
}
Format
======

Expand Down
47 changes: 42 additions & 5 deletions clang/docs/analyzer/checkers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3584,7 +3584,7 @@ These are examples of cases that we consider safe:
RefCountable* uncounted = this; // ok
}
Here are some examples of situations that we warn about as they *might* be potentially unsafe. The logic is that either we're able to guarantee that an argument is safe or it's considered if not a bug then bug-prone.
Here are some examples of situations that we warn about as they *might* be potentially unsafe. The logic is that either we're able to guarantee that a local variable is safe or it's considered unsafe.
.. code-block:: cpp
Expand All @@ -3603,11 +3603,48 @@ Here are some examples of situations that we warn about as they *might* be poten
RefCountable* uncounted = counted.get(); // warn
}
We don't warn about these cases - we don't consider them necessarily safe but since they are very common and usually safe we'd introduce a lot of false positives otherwise:
- variable defined in condition part of an ```if``` statement
- variable defined in init statement condition of a ```for``` statement
alpha.webkit.UncheckedLocalVarsChecker
""""""""""""""""""""""""""""""""""""""
The goal of this rule is to make sure that any unchecked local variable is backed by a CheckedPtr or CheckedRef with lifetime that is strictly larger than the scope of the unchecked local variable. To be on the safe side we require the scope of an unchecked variable to be embedded in the scope of CheckedPtr/CheckRef object that backs it.
These are examples of cases that we consider safe:
.. code-block:: cpp
For the time being we also don't warn about uninitialized uncounted local variables.
void foo1() {
CheckedPtr<RefCountable> counted;
// The scope of uncounted is EMBEDDED in the scope of counted.
{
RefCountable* uncounted = counted.get(); // ok
}
}
void foo2(CheckedPtr<RefCountable> counted_param) {
RefCountable* uncounted = counted_param.get(); // ok
}
void FooClass::foo_method() {
RefCountable* uncounted = this; // ok
}
Here are some examples of situations that we warn about as they *might* be potentially unsafe. The logic is that either we're able to guarantee that a local variable is safe or it's considered unsafe.
.. code-block:: cpp
void foo1() {
RefCountable* uncounted = new RefCountable; // warn
}
RefCountable* global_uncounted;
void foo2() {
RefCountable* uncounted = global_uncounted; // warn
}
void foo3() {
RefPtr<RefCountable> counted;
// The scope of uncounted is not EMBEDDED in the scope of counted.
RefCountable* uncounted = counted.get(); // warn
}
Debug Checkers
---------------
Expand Down
1 change: 1 addition & 0 deletions clang/docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ Using Clang Tools
ClangOffloadBundler
ClangOffloadPackager
ClangRepl
ClangSYCLLinker

Design Documents
================
Expand Down
29 changes: 28 additions & 1 deletion clang/include/clang/APINotes/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -425,14 +425,24 @@ class ParamInfo : public VariableInfo {
LLVM_PREFERRED_TYPE(bool)
unsigned NoEscape : 1;

/// Whether lifetimebound was specified.
LLVM_PREFERRED_TYPE(bool)
unsigned LifetimeboundSpecified : 1;

/// Whether the this parameter has the 'lifetimebound' attribute.
LLVM_PREFERRED_TYPE(bool)
unsigned Lifetimebound : 1;

/// A biased RetainCountConventionKind, where 0 means "unspecified".
///
/// Only relevant for out-parameters.
unsigned RawRetainCountConvention : 3;

public:
ParamInfo()
: NoEscapeSpecified(false), NoEscape(false), RawRetainCountConvention() {}
: NoEscapeSpecified(false), NoEscape(false),
LifetimeboundSpecified(false), Lifetimebound(false),
RawRetainCountConvention() {}

std::optional<bool> isNoEscape() const {
if (!NoEscapeSpecified)
Expand All @@ -444,6 +454,16 @@ class ParamInfo : public VariableInfo {
NoEscape = Value.value_or(false);
}

std::optional<bool> isLifetimebound() const {
if (!LifetimeboundSpecified)
return std::nullopt;
return Lifetimebound;
}
void setLifetimebound(std::optional<bool> Value) {
LifetimeboundSpecified = Value.has_value();
Lifetimebound = Value.value_or(false);
}

std::optional<RetainCountConventionKind> getRetainCountConvention() const {
if (!RawRetainCountConvention)
return std::nullopt;
Expand All @@ -463,6 +483,11 @@ class ParamInfo : public VariableInfo {
NoEscape = RHS.NoEscape;
}

if (!LifetimeboundSpecified && RHS.LifetimeboundSpecified) {
LifetimeboundSpecified = true;
Lifetimebound = RHS.Lifetimebound;
}

if (!RawRetainCountConvention)
RawRetainCountConvention = RHS.RawRetainCountConvention;

Expand All @@ -478,6 +503,8 @@ inline bool operator==(const ParamInfo &LHS, const ParamInfo &RHS) {
return static_cast<const VariableInfo &>(LHS) == RHS &&
LHS.NoEscapeSpecified == RHS.NoEscapeSpecified &&
LHS.NoEscape == RHS.NoEscape &&
LHS.LifetimeboundSpecified == RHS.LifetimeboundSpecified &&
LHS.Lifetimebound == RHS.Lifetimebound &&
LHS.RawRetainCountConvention == RHS.RawRetainCountConvention;
}

Expand Down
10 changes: 10 additions & 0 deletions clang/include/clang/AST/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -838,6 +838,9 @@ class ASTContext : public RefCountedBase<ASTContext> {

const NoSanitizeList &getNoSanitizeList() const { return *NoSanitizeL; }

bool isTypeIgnoredBySanitizer(const SanitizerMask &Mask,
const QualType &Ty) const;

const XRayFunctionFilter &getXRayFilter() const {
return *XRayFilter;
}
Expand Down Expand Up @@ -1719,8 +1722,15 @@ class ASTContext : public RefCountedBase<ASTContext> {
QualType getInjectedClassNameType(CXXRecordDecl *Decl, QualType TST) const;

QualType getAttributedType(attr::Kind attrKind, QualType modifiedType,
QualType equivalentType,
const Attr *attr = nullptr) const;

QualType getAttributedType(const Attr *attr, QualType modifiedType,
QualType equivalentType) const;

QualType getAttributedType(NullabilityKind nullability, QualType modifiedType,
QualType equivalentType);

QualType getBTFTagAttributedType(const BTFTypeTagAttr *BTFAttr,
QualType Wrapped) const;

Expand Down
52 changes: 5 additions & 47 deletions clang/include/clang/AST/DeclTemplate.h
Original file line number Diff line number Diff line change
Expand Up @@ -857,16 +857,6 @@ class RedeclarableTemplateDecl : public TemplateDecl,
/// \endcode
bool isMemberSpecialization() const { return Common.getInt(); }

/// Determines whether any redeclaration of this template was
/// a specialization of a member template.
bool hasMemberSpecialization() const {
for (const auto *D : redecls()) {
if (D->isMemberSpecialization())
return true;
}
return false;
}

/// Note that this member template is a specialization.
void setMemberSpecialization() {
assert(!isMemberSpecialization() && "already a member specialization");
Expand Down Expand Up @@ -1965,13 +1955,7 @@ class ClassTemplateSpecializationDecl : public CXXRecordDecl,
/// specialization which was specialized by this.
llvm::PointerUnion<ClassTemplateDecl *,
ClassTemplatePartialSpecializationDecl *>
getSpecializedTemplateOrPartial() const {
if (const auto *PartialSpec =
SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization *>())
return PartialSpec->PartialSpecialization;

return SpecializedTemplate.get<ClassTemplateDecl*>();
}
getSpecializedTemplateOrPartial() const;

/// Retrieve the set of template arguments that should be used
/// to instantiate members of the class template or class template partial
Expand Down Expand Up @@ -2208,17 +2192,6 @@ class ClassTemplatePartialSpecializationDecl
return InstantiatedFromMember.getInt();
}

/// Determines whether any redeclaration of this this class template partial
/// specialization was a specialization of a member partial specialization.
bool hasMemberSpecialization() const {
for (const auto *D : redecls()) {
if (cast<ClassTemplatePartialSpecializationDecl>(D)
->isMemberSpecialization())
return true;
}
return false;
}

/// Note that this member template is a specialization.
void setMemberSpecialization() { return InstantiatedFromMember.setInt(true); }

Expand Down Expand Up @@ -2740,13 +2713,7 @@ class VarTemplateSpecializationDecl : public VarDecl,
/// Retrieve the variable template or variable template partial
/// specialization which was specialized by this.
llvm::PointerUnion<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>
getSpecializedTemplateOrPartial() const {
if (const auto *PartialSpec =
SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization *>())
return PartialSpec->PartialSpecialization;

return SpecializedTemplate.get<VarTemplateDecl *>();
}
getSpecializedTemplateOrPartial() const;

/// Retrieve the set of template arguments that should be used
/// to instantiate the initializer of the variable template or variable
Expand Down Expand Up @@ -2980,18 +2947,6 @@ class VarTemplatePartialSpecializationDecl
return InstantiatedFromMember.getInt();
}

/// Determines whether any redeclaration of this this variable template
/// partial specialization was a specialization of a member partial
/// specialization.
bool hasMemberSpecialization() const {
for (const auto *D : redecls()) {
if (cast<VarTemplatePartialSpecializationDecl>(D)
->isMemberSpecialization())
return true;
}
return false;
}

/// Note that this member template is a specialization.
void setMemberSpecialization() { return InstantiatedFromMember.setInt(true); }

Expand Down Expand Up @@ -3164,6 +3119,9 @@ class VarTemplateDecl : public RedeclarableTemplateDecl {
return makeSpecIterator(getSpecializations(), true);
}

/// Merge \p Prev with our RedeclarableTemplateDecl::Common.
void mergePrevDecl(VarTemplateDecl *Prev);

// Implement isa/cast/dyncast support
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == VarTemplate; }
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/AST/PropertiesBase.td
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ def APValue : PropertyType { let PassByReference = 1; }
def APValueKind : EnumPropertyType<"APValue::ValueKind">;
def ArraySizeModifier : EnumPropertyType<"ArraySizeModifier">;
def AttrKind : EnumPropertyType<"attr::Kind">;
def Attr : PropertyType<"const Attr *">;
def AutoTypeKeyword : EnumPropertyType;
def Bool : PropertyType<"bool">;
def BuiltinTypeKind : EnumPropertyType<"BuiltinType::Kind">;
Expand Down
42 changes: 17 additions & 25 deletions clang/include/clang/AST/Type.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ class ValueDecl;
class TagDecl;
class TemplateParameterList;
class Type;
class Attr;

enum {
TypeAlignmentInBits = 4,
Expand Down Expand Up @@ -6130,21 +6131,29 @@ class AttributedType : public Type, public llvm::FoldingSetNode {
private:
friend class ASTContext; // ASTContext creates these

const Attr *Attribute;

QualType ModifiedType;
QualType EquivalentType;

AttributedType(QualType canon, attr::Kind attrKind, QualType modified,
QualType equivalent)
: Type(Attributed, canon, equivalent->getDependence()),
ModifiedType(modified), EquivalentType(equivalent) {
AttributedTypeBits.AttrKind = attrKind;
}
: AttributedType(canon, attrKind, nullptr, modified, equivalent) {}

AttributedType(QualType canon, const Attr *attr, QualType modified,
QualType equivalent);

private:
AttributedType(QualType canon, attr::Kind attrKind, const Attr *attr,
QualType modified, QualType equivalent);

public:
Kind getAttrKind() const {
return static_cast<Kind>(AttributedTypeBits.AttrKind);
}

const Attr *getAttr() const { return Attribute; }

QualType getModifiedType() const { return ModifiedType; }
QualType getEquivalentType() const { return EquivalentType; }

Expand Down Expand Up @@ -6176,25 +6185,6 @@ class AttributedType : public Type, public llvm::FoldingSetNode {

std::optional<NullabilityKind> getImmediateNullability() const;

/// Retrieve the attribute kind corresponding to the given
/// nullability kind.
static Kind getNullabilityAttrKind(NullabilityKind kind) {
switch (kind) {
case NullabilityKind::NonNull:
return attr::TypeNonNull;

case NullabilityKind::Nullable:
return attr::TypeNullable;

case NullabilityKind::NullableResult:
return attr::TypeNullableResult;

case NullabilityKind::Unspecified:
return attr::TypeNullUnspecified;
}
llvm_unreachable("Unknown nullability kind.");
}

/// Strip off the top-level nullability annotation on the given
/// type, if it's there.
///
Expand All @@ -6207,14 +6197,16 @@ class AttributedType : public Type, public llvm::FoldingSetNode {
static std::optional<NullabilityKind> stripOuterNullability(QualType &T);

void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getAttrKind(), ModifiedType, EquivalentType);
Profile(ID, getAttrKind(), ModifiedType, EquivalentType, Attribute);
}

static void Profile(llvm::FoldingSetNodeID &ID, Kind attrKind,
QualType modified, QualType equivalent) {
QualType modified, QualType equivalent,
const Attr *attr) {
ID.AddInteger(attrKind);
ID.AddPointer(modified.getAsOpaquePtr());
ID.AddPointer(equivalent.getAsOpaquePtr());
ID.AddPointer(attr);
}

static bool classof(const Type *T) {
Expand Down
8 changes: 6 additions & 2 deletions clang/include/clang/AST/TypeProperties.td
Original file line number Diff line number Diff line change
Expand Up @@ -668,12 +668,16 @@ let Class = AttributedType in {
def : Property<"equivalentType", QualType> {
let Read = [{ node->getEquivalentType() }];
}
def : Property<"attribute", AttrKind> {
def : Property<"attrKind", AttrKind> {
let Read = [{ node->getAttrKind() }];
}
def : Property<"attribute", Attr> {
let Read = [{ node->getAttr() }];
}

def : Creator<[{
return ctx.getAttributedType(attribute, modifiedType, equivalentType);
return ctx.getAttributedType(attrKind, modifiedType,
equivalentType, attribute);
}]>;
}

Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/Basic/Attr.td
Original file line number Diff line number Diff line change
Expand Up @@ -2838,7 +2838,7 @@ def SwiftAsyncName : InheritableAttr {
let Documentation = [SwiftAsyncNameDocs];
}

def SwiftAttr : InheritableAttr {
def SwiftAttr : DeclOrTypeAttr {
let Spellings = [GNU<"swift_attr">];
let Args = [StringArgument<"Attribute">];
let Documentation = [SwiftAttrDocs];
Expand Down
4 changes: 2 additions & 2 deletions clang/include/clang/Basic/AttrDocs.td
Original file line number Diff line number Diff line change
Expand Up @@ -4507,8 +4507,8 @@ def SwiftAttrDocs : Documentation {
let Heading = "swift_attr";
let Content = [{
The ``swift_attr`` provides a Swift-specific annotation for the declaration
to which the attribute appertains to. It can be used on any declaration
in Clang. This kind of annotation is ignored by Clang as it doesn't have any
or type to which the attribute appertains to. It can be used on any declaration
or type in Clang. This kind of annotation is ignored by Clang as it doesn't have any
semantic meaning in languages supported by Clang. The Swift compiler can
interpret these annotations according to its own rules when importing C or
Objective-C declarations.
Expand Down
146 changes: 73 additions & 73 deletions clang/include/clang/Basic/BuiltinsLoongArchLASX.def

Large diffs are not rendered by default.

132 changes: 66 additions & 66 deletions clang/include/clang/Basic/BuiltinsLoongArchLSX.def

Large diffs are not rendered by default.

13 changes: 12 additions & 1 deletion clang/include/clang/Basic/BuiltinsX86_64.def
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,11 @@ TARGET_BUILTIN(__builtin_ia32_tdpbf16ps_internal, "V256iUsUsUsV256iV256iV256i",
TARGET_BUILTIN(__builtin_ia32_tdpfp16ps_internal, "V256iUsUsUsV256iV256iV256i", "n", "amx-fp16")
TARGET_BUILTIN(__builtin_ia32_tcmmimfp16ps_internal, "V256iUsUsUsV256iV256iV256i", "n", "amx-complex")
TARGET_BUILTIN(__builtin_ia32_tcmmrlfp16ps_internal, "V256iUsUsUsV256iV256iV256i", "n", "amx-complex")
TARGET_BUILTIN(__builtin_ia32_t2rpntlvwz0_internal, "vUsUsUsV256i*V256i*vC*z", "n", "amx-transpose")
TARGET_BUILTIN(__builtin_ia32_t2rpntlvwz0t1_internal, "vUsUsUsV256i*V256i*vC*z", "n", "amx-transpose")
TARGET_BUILTIN(__builtin_ia32_t2rpntlvwz1_internal, "vUsUsUsV256i*V256i*vC*z", "n", "amx-transpose")
TARGET_BUILTIN(__builtin_ia32_t2rpntlvwz1t1_internal, "vUsUsUsV256i*V256i*vC*z", "n", "amx-transpose")
TARGET_BUILTIN(__builtin_ia32_ttransposed_internal, "V256iUsUsV256i", "n", "amx-transpose")
// AMX
TARGET_BUILTIN(__builtin_ia32_tile_loadconfig, "vvC*", "n", "amx-tile")
TARGET_BUILTIN(__builtin_ia32_tile_storeconfig, "vvC*", "n", "amx-tile")
Expand All @@ -148,9 +153,15 @@ TARGET_BUILTIN(__builtin_ia32_ptwrite64, "vUOi", "n", "ptwrite")
TARGET_BUILTIN(__builtin_ia32_tcmmimfp16ps, "vIUcIUcIUc", "n", "amx-complex")
TARGET_BUILTIN(__builtin_ia32_tcmmrlfp16ps, "vIUcIUcIUc", "n", "amx-complex")

TARGET_BUILTIN(__builtin_ia32_t2rpntlvwz0, "vIUcvC*z", "n", "amx-transpose")
TARGET_BUILTIN(__builtin_ia32_t2rpntlvwz0t1, "vIUcvC*z", "n","amx-transpose")
TARGET_BUILTIN(__builtin_ia32_t2rpntlvwz1, "vIUcvC*z", "n", "amx-transpose")
TARGET_BUILTIN(__builtin_ia32_t2rpntlvwz1t1, "vIUcvC*z", "n","amx-transpose")
TARGET_BUILTIN(__builtin_ia32_ttransposed, "vIUcIUc", "n", "amx-transpose")

TARGET_BUILTIN(__builtin_ia32_prefetchi, "vvC*Ui", "nc", "prefetchi")
TARGET_BUILTIN(__builtin_ia32_cmpccxadd32, "Siv*SiSiIi", "n", "cmpccxadd")
TARGET_BUILTIN(__builtin_ia32_cmpccxadd64, "SLLiv*SLLiSLLiIi", "n", "cmpccxadd")
TARGET_BUILTIN(__builtin_ia32_cmpccxadd64, "SLLiSLLi*SLLiSLLiIi", "n", "cmpccxadd")

// AMX_FP16 FP16
TARGET_BUILTIN(__builtin_ia32_tdpfp16ps, "vIUcIUcIUc", "n", "amx-fp16")
Expand Down
3 changes: 1 addition & 2 deletions clang/include/clang/Basic/DiagnosticDriverKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,7 @@ def warn_drv_invalid_arch_name_with_suggestion : Warning<
"ignoring invalid /arch: argument '%0'; for %select{64|32}1-bit expected one of %2">,
InGroup<UnusedCommandLineArgument>;
def warn_drv_avr_mcu_not_specified : Warning<
"no target microcontroller specified on command line, cannot "
"link standard libraries, please pass -mmcu=<mcu name>">,
"no target microcontroller specified, please pass -mmcu=<mcu name>">,
InGroup<AVRRtlibLinkingQuirks>;
def warn_drv_avr_libc_not_found: Warning<
"no avr-libc installation can be found on the system, "
Expand Down
13 changes: 12 additions & 1 deletion clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -12718,7 +12718,18 @@ def err_acc_num_arg_conflict
def err_acc_clause_in_clause_region
: Error<"loop with a '%0' clause may not exist in the region of a '%1' "
"clause%select{| on a 'kernels' compute construct}2">;

def err_acc_gang_reduction_conflict
: Error<"%select{OpenACC 'gang' clause with a 'dim' value greater than "
"1|OpenACC 'reduction' clause}0 cannot "
"appear on the same 'loop' construct as a %select{'reduction' "
"clause|'gang' clause with a 'dim' value greater than 1}0">;
def err_acc_gang_reduction_numgangs_conflict
: Error<"OpenACC '%0' clause cannot appear on the same 'loop' construct "
"as a '%1' clause inside a compute construct with a "
"'num_gangs' clause with more than one argument">;
def err_reduction_op_mismatch
: Error<"OpenACC 'reduction' variable must have the same operator in all "
"nested constructs (%0 vs %1)">;
// AMDGCN builtins diagnostics
def err_amdgcn_global_load_lds_size_invalid_value : Error<"invalid size value">;
def note_amdgcn_global_load_lds_size_valid_value : Note<"size must be 1, 2, or 4">;
Expand Down
10 changes: 6 additions & 4 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -4570,9 +4570,6 @@ def ibuiltininc : Flag<["-"], "ibuiltininc">, Group<clang_i_Group>,
HelpText<"Enable builtin #include directories even when -nostdinc is used "
"before or after -ibuiltininc. "
"Using -nobuiltininc after the option disables it">;
def index_header_map : Flag<["-"], "index-header-map">,
Visibility<[ClangOption, CC1Option]>,
HelpText<"Make the next included directory (-I or -F) an indexer header map">;
def iapinotes_modules : JoinedOrSeparate<["-"], "iapinotes-modules">, Group<clang_i_Group>,
Visibility<[ClangOption, CC1Option]>,
HelpText<"Add directory to the API notes search path referenced by module name">, MetaVarName<"<directory>">;
Expand Down Expand Up @@ -6304,6 +6301,8 @@ def mamx_fp8 : Flag<["-"], "mamx-fp8">, Group<m_x86_Features_Group>;
def mno_amx_fp8 : Flag<["-"], "mno-amx-fp8">, Group<m_x86_Features_Group>;
def mamx_tile : Flag<["-"], "mamx-tile">, Group<m_x86_Features_Group>;
def mno_amx_tile : Flag<["-"], "mno-amx-tile">, Group<m_x86_Features_Group>;
def mamx_transpose : Flag<["-"], "mamx-transpose">, Group<m_x86_Features_Group>;
def mno_amx_transpose : Flag<["-"], "mno-amx-transpose">, Group<m_x86_Features_Group>;
def mcmpccxadd : Flag<["-"], "mcmpccxadd">, Group<m_x86_Features_Group>;
def mno_cmpccxadd : Flag<["-"], "mno-cmpccxadd">, Group<m_x86_Features_Group>;
def msse : Flag<["-"], "msse">, Group<m_x86_Features_Group>;
Expand Down Expand Up @@ -6781,7 +6780,10 @@ def fsycl : Flag<["-"], "fsycl">,
def fno_sycl : Flag<["-"], "fno-sycl">,
Visibility<[ClangOption, CLOption]>,
Group<sycl_Group>, HelpText<"Disables SYCL kernels compilation for device">;

def sycl_link : Flag<["--"], "sycl-link">, Flags<[HelpHidden]>,
Visibility<[ClangOption, CLOption]>,
Group<sycl_Group>, HelpText<"Perform link through clang-sycl-linker via the target "
"offloading toolchain.">;
// OS-specific options
let Flags = [TargetSpecific] in {
defm android_pad_segment : BooleanFFlag<"android-pad-segment">, Group<f_Group>;
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/Format/Format.h
Original file line number Diff line number Diff line change
Expand Up @@ -1569,7 +1569,7 @@ struct FormatStyle {

/// Control of individual brace wrapping cases.
///
/// If ``BreakBeforeBraces`` is set to ``BS_Custom``, use this to specify how
/// If ``BreakBeforeBraces`` is set to ``Custom``, use this to specify how
/// each individual brace case should be handled. Otherwise, this is ignored.
/// \code{.yaml}
/// # Example of usage:
Expand Down
16 changes: 3 additions & 13 deletions clang/include/clang/Lex/DirectoryLookup.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,6 @@ class DirectoryLookup {
LLVM_PREFERRED_TYPE(LookupType_t)
unsigned LookupType : 2;

/// Whether this is a header map used when building a framework.
LLVM_PREFERRED_TYPE(bool)
unsigned IsIndexHeaderMap : 1;

/// Whether we've performed an exhaustive search for module maps
/// within the subdirectories of this directory.
LLVM_PREFERRED_TYPE(bool)
Expand All @@ -73,13 +69,12 @@ class DirectoryLookup {
bool isFramework)
: u(Dir), DirCharacteristic(DT),
LookupType(isFramework ? LT_Framework : LT_NormalDir),
IsIndexHeaderMap(false), SearchedAllModuleMaps(false) {}
SearchedAllModuleMaps(false) {}

/// This ctor *does not take ownership* of 'Map'.
DirectoryLookup(const HeaderMap *Map, SrcMgr::CharacteristicKind DT,
bool isIndexHeaderMap)
DirectoryLookup(const HeaderMap *Map, SrcMgr::CharacteristicKind DT)
: u(Map), DirCharacteristic(DT), LookupType(LT_HeaderMap),
IsIndexHeaderMap(isIndexHeaderMap), SearchedAllModuleMaps(false) {}
SearchedAllModuleMaps(false) {}

/// getLookupType - Return the kind of directory lookup that this is: either a
/// normal directory, a framework path, or a HeaderMap.
Expand Down Expand Up @@ -146,11 +141,6 @@ class DirectoryLookup {
return getDirCharacteristic() != SrcMgr::C_User;
}

/// Whether this header map is building a framework or not.
bool isIndexHeaderMap() const {
return isHeaderMap() && IsIndexHeaderMap;
}

/// LookupFile - Lookup the specified file in this search path, returning it
/// if it exists or returning null if not.
///
Expand Down
18 changes: 3 additions & 15 deletions clang/include/clang/Lex/HeaderSearch.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,16 +108,6 @@ struct HeaderFileInfo {
LLVM_PREFERRED_TYPE(bool)
unsigned Resolved : 1;

/// Whether this is a header inside a framework that is currently
/// being built.
///
/// When a framework is being built, the headers have not yet been placed
/// into the appropriate framework subdirectories, and therefore are
/// provided via a header map. This bit indicates when this is one of
/// those framework headers.
LLVM_PREFERRED_TYPE(bool)
unsigned IndexHeaderMapHeader : 1;

/// Whether this file has been looked up as a header.
LLVM_PREFERRED_TYPE(bool)
unsigned IsValid : 1;
Expand All @@ -132,15 +122,11 @@ struct HeaderFileInfo {
/// external storage.
LazyIdentifierInfoPtr LazyControllingMacro;

/// If this header came from a framework include, this is the name
/// of the framework.
StringRef Framework;

HeaderFileInfo()
: IsLocallyIncluded(false), isImport(false), isPragmaOnce(false),
DirInfo(SrcMgr::C_User), External(false), isModuleHeader(false),
isTextualModuleHeader(false), isCompilingModuleHeader(false),
Resolved(false), IndexHeaderMapHeader(false), IsValid(false) {}
Resolved(false), IsValid(false) {}

/// Retrieve the controlling macro for this header file, if
/// any.
Expand All @@ -154,6 +140,8 @@ struct HeaderFileInfo {
void mergeModuleMembership(ModuleMap::ModuleHeaderRole Role);
};

static_assert(sizeof(HeaderFileInfo) <= 16);

/// An external source of header file information, which may supply
/// information about header files already included.
class ExternalHeaderFileInfoSource {
Expand Down
3 changes: 0 additions & 3 deletions clang/include/clang/Lex/HeaderSearchOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,6 @@ enum IncludeDirGroup {
/// Paths for '\#include <>' added by '-I'.
Angled,

/// Like Angled, but marks header maps used when building frameworks.
IndexHeaderMap,

/// Like Angled, but marks system directories.
System,

Expand Down
30 changes: 29 additions & 1 deletion clang/include/clang/Sema/SemaOpenACC.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ class SemaOpenACC : public SemaBase {
/// used to diagnose if there are multiple 'for' loops at any one level.
LLVM_PREFERRED_TYPE(bool)
unsigned CurLevelHasLoopAlready : 1;

} LoopInfo{/*TopLevelLoopSeen=*/false, /*CurLevelHasLoopAlready=*/false};

/// The 'collapse' clause requires quite a bit of checking while
Expand Down Expand Up @@ -109,6 +110,14 @@ class SemaOpenACC : public SemaBase {
bool TileDepthSatisfied = true;
} TileInfo;

/// A list of the active reduction clauses, which allows us to check that all
/// vars on nested constructs for the same reduction var have the same
/// reduction operator. Currently this is enforced against all constructs
/// despite the rule being in the 'loop' section. By current reading, this
/// should apply to all anyway, but we may need to make this more like the
/// 'loop' clause enforcement, where this is 'blocked' by a compute construct.
llvm::SmallVector<OpenACCReductionClause *> ActiveReductionClauses;

public:
ComputeConstructInfo &getActiveComputeConstructInfo() {
return ActiveComputeConstructInfo;
Expand Down Expand Up @@ -615,7 +624,9 @@ class SemaOpenACC : public SemaBase {

/// Called while semantically analyzing the reduction clause, ensuring the var
/// is the correct kind of reference.
ExprResult CheckReductionVar(Expr *VarExpr);
ExprResult CheckReductionVar(OpenACCDirectiveKind DirectiveKind,
OpenACCReductionOperator ReductionOp,
Expr *VarExpr);

/// Called to check the 'var' type is a variable of pointer type, necessary
/// for 'deviceptr' and 'attach' clauses. Returns true on success.
Expand All @@ -634,6 +645,22 @@ class SemaOpenACC : public SemaBase {
// Check a single expression on a gang clause.
ExprResult CheckGangExpr(OpenACCGangKind GK, Expr *E);

// Does the checking for a 'gang' clause that needs to be done in dependent
// and not dependent cases.
OpenACCClause *
CheckGangClause(ArrayRef<const OpenACCClause *> ExistingClauses,
SourceLocation BeginLoc, SourceLocation LParenLoc,
ArrayRef<OpenACCGangKind> GangKinds,
ArrayRef<Expr *> IntExprs, SourceLocation EndLoc);
// Does the checking for a 'reduction ' clause that needs to be done in
// dependent and not dependent cases.
OpenACCClause *
CheckReductionClause(ArrayRef<const OpenACCClause *> ExistingClauses,
OpenACCDirectiveKind DirectiveKind,
SourceLocation BeginLoc, SourceLocation LParenLoc,
OpenACCReductionOperator ReductionOp,
ArrayRef<Expr *> Vars, SourceLocation EndLoc);

ExprResult BuildOpenACCAsteriskSizeExpr(SourceLocation AsteriskLoc);
ExprResult ActOnOpenACCAsteriskSizeExpr(SourceLocation AsteriskLoc);

Expand Down Expand Up @@ -686,6 +713,7 @@ class SemaOpenACC : public SemaBase {
SourceLocation OldLoopWorkerClauseLoc;
SourceLocation OldLoopVectorClauseLoc;
llvm::SmallVector<OpenACCLoopConstruct *> ParentlessLoopConstructs;
llvm::SmallVector<OpenACCReductionClause *> ActiveReductionClauses;
LoopInConstructRAII LoopRAII;

public:
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/Serialization/ASTBitCodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ namespace serialization {
/// Version 4 of AST files also requires that the version control branch and
/// revision match exactly, since there is no backward compatibility of
/// AST files at this time.
const unsigned VERSION_MAJOR = 32;
const unsigned VERSION_MAJOR = 33;

/// AST file minor version number supported by this version of
/// Clang.
Expand Down
44 changes: 42 additions & 2 deletions clang/include/clang/Serialization/ASTReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
#include "llvm/ADT/iterator_range.h"
#include "llvm/Bitstream/BitstreamReader.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SaveAndRestore.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/VersionTuple.h"
#include <cassert>
Expand Down Expand Up @@ -1341,9 +1342,48 @@ class ASTReader
serialization::InputFile getInputFile(ModuleFile &F, unsigned ID,
bool Complain = true);

/// The buffer used as the temporary backing storage for resolved paths.
SmallString<0> PathBuf;

/// A wrapper around StringRef that temporarily borrows the underlying buffer.
class TemporarilyOwnedStringRef {
StringRef String;
llvm::SaveAndRestore<SmallString<0>> UnderlyingBuffer;

public:
TemporarilyOwnedStringRef(StringRef S, SmallString<0> &UnderlyingBuffer)
: String(S), UnderlyingBuffer(UnderlyingBuffer, {}) {}

/// Return the wrapped \c StringRef that must be outlived by \c this.
const StringRef *operator->() const & { return &String; }
const StringRef &operator*() const & { return String; }

/// Make it harder to get a \c StringRef that outlives \c this.
const StringRef *operator->() && = delete;
const StringRef &operator*() && = delete;
};

public:
void ResolveImportedPath(ModuleFile &M, std::string &Filename);
static void ResolveImportedPath(std::string &Filename, StringRef Prefix);
/// Get the buffer for resolving paths.
SmallString<0> &getPathBuf() { return PathBuf; }

/// Resolve \c Path in the context of module file \c M. The return value
/// must go out of scope before the next call to \c ResolveImportedPath.
static TemporarilyOwnedStringRef
ResolveImportedPath(SmallString<0> &Buf, StringRef Path, ModuleFile &ModF);
/// Resolve \c Path in the context of the \c Prefix directory. The return
/// value must go out of scope before the next call to \c ResolveImportedPath.
static TemporarilyOwnedStringRef
ResolveImportedPath(SmallString<0> &Buf, StringRef Path, StringRef Prefix);

/// Resolve \c Path in the context of module file \c M.
static std::string ResolveImportedPathAndAllocate(SmallString<0> &Buf,
StringRef Path,
ModuleFile &ModF);
/// Resolve \c Path in the context of the \c Prefix directory.
static std::string ResolveImportedPathAndAllocate(SmallString<0> &Buf,
StringRef Path,
StringRef Prefix);

/// Returns the first key declaration for the given declaration. This
/// is one that is formerly-canonical (or still canonical) and whose module
Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/Serialization/ASTRecordWriter.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,8 @@ class ASTRecordWriter
AddStmt(const_cast<Stmt*>(S));
}

void writeAttr(const Attr *A) { AddAttr(A); }

/// Write an BTFTypeTagAttr object.
void writeBTFTypeTagAttr(const BTFTypeTagAttr *A) { AddAttr(A); }

Expand Down
4 changes: 4 additions & 0 deletions clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
Original file line number Diff line number Diff line change
Expand Up @@ -1764,4 +1764,8 @@ def UncountedLocalVarsChecker : Checker<"UncountedLocalVarsChecker">,
HelpText<"Check uncounted local variables.">,
Documentation<HasDocumentation>;

def UncheckedLocalVarsChecker : Checker<"UncheckedLocalVarsChecker">,
HelpText<"Check unchecked local variables.">,
Documentation<HasDocumentation>;

} // end alpha.webkit
2 changes: 1 addition & 1 deletion clang/lib/APINotes/APINotesFormat.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const uint16_t VERSION_MAJOR = 0;
/// API notes file minor version number.
///
/// When the format changes IN ANY WAY, this number should be incremented.
const uint16_t VERSION_MINOR = 30; // fields
const uint16_t VERSION_MINOR = 31; // lifetimebound

const uint8_t kSwiftCopyable = 1;
const uint8_t kSwiftNonCopyable = 2;
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/APINotes/APINotesReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,9 @@ void ReadParamInfo(const uint8_t *&Data, ParamInfo &Info) {
Info.setRetainCountConvention(Convention);
}
Payload >>= 3;
if (Payload & 0x01)
Info.setLifetimebound(Payload & 0x02);
Payload >>= 2;
if (Payload & 0x01)
Info.setNoEscape(Payload & 0x02);
Payload >>= 2;
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/APINotes/APINotesTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ LLVM_DUMP_METHOD void ParamInfo::dump(llvm::raw_ostream &OS) const {
static_cast<const VariableInfo &>(*this).dump(OS);
if (NoEscapeSpecified)
OS << (NoEscape ? "[NoEscape] " : "");
if (LifetimeboundSpecified)
OS << (Lifetimebound ? "[Lifetimebound] " : "");
OS << "RawRetainCountConvention: " << RawRetainCountConvention << ' ';
OS << '\n';
}
Expand Down
6 changes: 6 additions & 0 deletions clang/lib/APINotes/APINotesWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1052,6 +1052,12 @@ void emitParamInfo(raw_ostream &OS, const ParamInfo &PI) {
if (*noescape)
flags |= 0x02;
}
flags <<= 2;
if (auto lifetimebound = PI.isLifetimebound()) {
flags |= 0x01;
if (*lifetimebound)
flags |= 0x02;
}
flags <<= 3;
if (auto RCC = PI.getRetainCountConvention())
flags |= static_cast<uint8_t>(RCC.value()) + 1;
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/APINotes/APINotesYAMLCompiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ namespace {
struct Param {
unsigned Position;
std::optional<bool> NoEscape = false;
std::optional<bool> Lifetimebound = false;
std::optional<NullabilityKind> Nullability;
std::optional<RetainCountConventionKind> RetainCountConvention;
StringRef Type;
Expand Down Expand Up @@ -121,6 +122,7 @@ template <> struct MappingTraits<Param> {
IO.mapOptional("Nullability", P.Nullability, std::nullopt);
IO.mapOptional("RetainCountConvention", P.RetainCountConvention);
IO.mapOptional("NoEscape", P.NoEscape);
IO.mapOptional("Lifetimebound", P.Lifetimebound);
IO.mapOptional("Type", P.Type, StringRef(""));
}
};
Expand Down Expand Up @@ -734,6 +736,7 @@ class YAMLConverter {
if (P.Nullability)
PI.setNullabilityAudited(*P.Nullability);
PI.setNoEscape(P.NoEscape);
PI.setLifetimebound(P.Lifetimebound);
PI.setType(std::string(P.Type));
PI.setRetainCountConvention(P.RetainCountConvention);
if (OutInfo.Params.size() <= P.Position)
Expand Down
57 changes: 49 additions & 8 deletions clang/lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -831,6 +831,15 @@ ASTContext::getCanonicalTemplateTemplateParmDecl(
return CanonTTP;
}

/// Check if a type can have its sanitizer instrumentation elided based on its
/// presence within an ignorelist.
bool ASTContext::isTypeIgnoredBySanitizer(const SanitizerMask &Mask,
const QualType &Ty) const {
std::string TyName = Ty.getUnqualifiedType().getAsString(getPrintingPolicy());
return NoSanitizeL->containsType(Mask, TyName) &&
!NoSanitizeL->containsType(Mask, TyName, "sanitize");
}

TargetCXXABI::Kind ASTContext::getCXXABIKind() const {
auto Kind = getTargetInfo().getCXXABI().getKind();
return getLangOpts().CXXABI.value_or(Kind);
Expand Down Expand Up @@ -3552,7 +3561,8 @@ ASTContext::adjustType(QualType Orig,
const auto *AT = dyn_cast<AttributedType>(Orig);
return getAttributedType(AT->getAttrKind(),
adjustType(AT->getModifiedType(), Adjust),
adjustType(AT->getEquivalentType(), Adjust));
adjustType(AT->getEquivalentType(), Adjust),
AT->getAttr());
}

case Type::BTFTagAttributed: {
Expand Down Expand Up @@ -5197,24 +5207,54 @@ QualType ASTContext::getUnresolvedUsingType(

QualType ASTContext::getAttributedType(attr::Kind attrKind,
QualType modifiedType,
QualType equivalentType) const {
QualType equivalentType,
const Attr *attr) const {
llvm::FoldingSetNodeID id;
AttributedType::Profile(id, attrKind, modifiedType, equivalentType);
AttributedType::Profile(id, attrKind, modifiedType, equivalentType, attr);

void *insertPos = nullptr;
AttributedType *type = AttributedTypes.FindNodeOrInsertPos(id, insertPos);
if (type) return QualType(type, 0);

assert(!attr || attr->getKind() == attrKind);

QualType canon = getCanonicalType(equivalentType);
type = new (*this, alignof(AttributedType))
AttributedType(canon, attrKind, modifiedType, equivalentType);
type = new (*this, alignof(AttributedType))
AttributedType(canon, attrKind, attr, modifiedType, equivalentType);

Types.push_back(type);
AttributedTypes.InsertNode(type, insertPos);

return QualType(type, 0);
}

QualType ASTContext::getAttributedType(const Attr *attr, QualType modifiedType,
QualType equivalentType) const {
return getAttributedType(attr->getKind(), modifiedType, equivalentType, attr);
}

QualType ASTContext::getAttributedType(NullabilityKind nullability,
QualType modifiedType,
QualType equivalentType) {
switch (nullability) {
case NullabilityKind::NonNull:
return getAttributedType(attr::TypeNonNull, modifiedType, equivalentType);

case NullabilityKind::Nullable:
return getAttributedType(attr::TypeNullable, modifiedType, equivalentType);

case NullabilityKind::NullableResult:
return getAttributedType(attr::TypeNullableResult, modifiedType,
equivalentType);

case NullabilityKind::Unspecified:
return getAttributedType(attr::TypeNullUnspecified, modifiedType,
equivalentType);
}

llvm_unreachable("Unknown nullability kind");
}

QualType ASTContext::getBTFTagAttributedType(const BTFTypeTagAttr *BTFAttr,
QualType Wrapped) const {
llvm::FoldingSetNodeID ID;
Expand Down Expand Up @@ -7537,8 +7577,8 @@ QualType ASTContext::getArrayDecayedType(QualType Ty) const {

// int x[_Nullable] -> int * _Nullable
if (auto Nullability = Ty->getNullability()) {
Result = const_cast<ASTContext *>(this)->getAttributedType(
AttributedType::getNullabilityAttrKind(*Nullability), Result, Result);
Result = const_cast<ASTContext *>(this)->getAttributedType(*Nullability,
Result, Result);
}
return Result;
}
Expand Down Expand Up @@ -13773,7 +13813,8 @@ static QualType getCommonSugarTypeNode(ASTContext &Ctx, const Type *X,
return QualType();
// FIXME: It's inefficient to have to unify the modified types.
return Ctx.getAttributedType(Kind, Ctx.getCommonSugaredType(MX, MY),
Ctx.getQualifiedType(Underlying));
Ctx.getQualifiedType(Underlying),
AX->getAttr());
}
case Type::BTFTagAttributed: {
const auto *BX = cast<BTFTagAttributedType>(X);
Expand Down
6 changes: 2 additions & 4 deletions clang/lib/AST/ASTDiagnostic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,7 @@ QualType clang::desugarForDiagnostic(ASTContext &Context, QualType QT,
QualType SugarRT = FT->getReturnType();
QualType RT = desugarForDiagnostic(Context, SugarRT, DesugarReturn);
if (auto nullability = AttributedType::stripOuterNullability(SugarRT)) {
RT = Context.getAttributedType(
AttributedType::getNullabilityAttrKind(*nullability), RT, RT);
RT = Context.getAttributedType(*nullability, RT, RT);
}

bool DesugarArgument = false;
Expand All @@ -97,8 +96,7 @@ QualType clang::desugarForDiagnostic(ASTContext &Context, QualType QT,
QualType PT = desugarForDiagnostic(Context, SugarPT, DesugarArgument);
if (auto nullability =
AttributedType::stripOuterNullability(SugarPT)) {
PT = Context.getAttributedType(
AttributedType::getNullabilityAttrKind(*nullability), PT, PT);
PT = Context.getAttributedType(*nullability, PT, PT);
}
Args.push_back(PT);
}
Expand Down
8 changes: 5 additions & 3 deletions clang/lib/AST/ASTImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1580,8 +1580,9 @@ ExpectedType ASTNodeImporter::VisitAttributedType(const AttributedType *T) {
if (!ToEquivalentTypeOrErr)
return ToEquivalentTypeOrErr.takeError();

return Importer.getToContext().getAttributedType(T->getAttrKind(),
*ToModifiedTypeOrErr, *ToEquivalentTypeOrErr);
return Importer.getToContext().getAttributedType(
T->getAttrKind(), *ToModifiedTypeOrErr, *ToEquivalentTypeOrErr,
T->getAttr());
}

ExpectedType
Expand Down Expand Up @@ -6189,7 +6190,8 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
ExpectedDecl ASTNodeImporter::VisitClassTemplateSpecializationDecl(
ClassTemplateSpecializationDecl *D) {
ClassTemplateDecl *ClassTemplate;
if (Error Err = importInto(ClassTemplate, D->getSpecializedTemplate()))
if (Error Err = importInto(ClassTemplate,
D->getSpecializedTemplate()->getCanonicalDecl()))
return std::move(Err);

// Import the context of this declaration.
Expand Down
10 changes: 10 additions & 0 deletions clang/lib/AST/ByteCode/Boolean.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,16 @@ class Boolean final {

Boolean truncate(unsigned TruncBits) const { return *this; }

static Boolean bitcastFromMemory(const std::byte *Buff, unsigned BitWidth) {
// Boolean width is currently always 8 for all supported targets. If this
// changes we need to get the bool width from the target info.
assert(BitWidth == 8);
bool Val = static_cast<bool>(*Buff);
return Boolean(Val);
}

void bitcastToMemory(std::byte *Buff) { std::memcpy(Buff, &V, sizeof(V)); }

void print(llvm::raw_ostream &OS) const { OS << (V ? "true" : "false"); }
std::string toDiagnosticString(const ASTContext &Ctx) const {
std::string NameStr;
Expand Down
61 changes: 61 additions & 0 deletions clang/lib/AST/ByteCode/Compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,9 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
return this->emitDecayPtr(*FromT, *ToT, CE);
}

case CK_LValueToRValueBitCast:
return this->emitBuiltinBitCast(CE);

case CK_IntegralToBoolean:
case CK_FixedPointToBoolean:
case CK_BooleanToSignedIntegral:
Expand Down Expand Up @@ -6426,6 +6429,64 @@ bool Compiler<Emitter>::emitDummyPtr(const DeclTy &D, const Expr *E) {
return this->emitDecayPtr(PT_Ptr, PT, E);
return false;
}
return true;
}

// This function is constexpr if and only if To, From, and the types of
// all subobjects of To and From are types T such that...
// (3.1) - is_union_v<T> is false;
// (3.2) - is_pointer_v<T> is false;
// (3.3) - is_member_pointer_v<T> is false;
// (3.4) - is_volatile_v<T> is false; and
// (3.5) - T has no non-static data members of reference type
template <class Emitter>
bool Compiler<Emitter>::emitBuiltinBitCast(const CastExpr *E) {
const Expr *SubExpr = E->getSubExpr();
QualType FromType = SubExpr->getType();
QualType ToType = E->getType();
std::optional<PrimType> ToT = classify(ToType);

assert(!DiscardResult && "Implement DiscardResult mode for bitcasts.");

if (ToType->isNullPtrType()) {
if (!this->discard(SubExpr))
return false;

return this->emitNullPtr(nullptr, E);
}

if (FromType->isNullPtrType() && ToT) {
if (!this->discard(SubExpr))
return false;

return visitZeroInitializer(*ToT, ToType, E);
}
assert(!ToType->isReferenceType());

// Get a pointer to the value-to-cast on the stack.
if (!this->visit(SubExpr))
return false;

if (!ToT || ToT == PT_Ptr)
return this->emitBitCastPtr(E);
assert(ToT);

const llvm::fltSemantics *TargetSemantics = nullptr;
if (ToT == PT_Float)
TargetSemantics = &Ctx.getFloatSemantics(ToType);

// Conversion to a primitive type. FromType can be another
// primitive type, or a record/array.
bool ToTypeIsUChar = (ToType->isSpecificBuiltinType(BuiltinType::UChar) ||
ToType->isSpecificBuiltinType(BuiltinType::Char_U));
uint32_t ResultBitWidth = std::max(Ctx.getBitWidth(ToType), 8u);

if (!this->emitBitCast(*ToT, ToTypeIsUChar || ToType->isStdByteType(),
ResultBitWidth, TargetSemantics, E))
return false;

if (DiscardResult)
return this->emitPop(*ToT, E);

return true;
}
Expand Down
1 change: 1 addition & 0 deletions clang/lib/AST/ByteCode/Compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,7 @@ class Compiler : public ConstStmtVisitor<Compiler<Emitter>, bool>,
unsigned collectBaseOffset(const QualType BaseType,
const QualType DerivedType);
bool emitLambdaStaticInvokerBody(const CXXMethodDecl *MD);
bool emitBuiltinBitCast(const CastExpr *E);
bool compileConstructor(const CXXConstructorDecl *Ctor);
bool compileDestructor(const CXXDestructorDecl *Dtor);

Expand Down
10 changes: 9 additions & 1 deletion clang/lib/AST/ByteCode/Descriptor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -411,8 +411,16 @@ QualType Descriptor::getElemQualType() const {
QualType T = getType();
if (T->isPointerOrReferenceType())
return T->getPointeeType();
if (const auto *AT = T->getAsArrayTypeUnsafe())
if (const auto *AT = T->getAsArrayTypeUnsafe()) {
// For primitive arrays, we don't save a QualType at all,
// just a PrimType. Try to figure out the QualType here.
if (isPrimitiveArray()) {
while (T->isArrayType())
T = T->getAsArrayTypeUnsafe()->getElementType();
return T;
}
return AT->getElementType();
}
if (const auto *CT = T->getAs<ComplexType>())
return CT->getElementType();
if (const auto *CT = T->getAs<VectorType>())
Expand Down
5 changes: 5 additions & 0 deletions clang/lib/AST/ByteCode/Floating.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,11 @@ class Floating final {
return Floating(APFloat(Sem, API));
}

void bitcastToMemory(std::byte *Buff) const {
llvm::APInt API = F.bitcastToAPInt();
llvm::StoreIntToMemory(API, (uint8_t *)Buff, bitWidth() / 8);
}

// === Serialization support ===
size_t bytesToSerialize() const {
return sizeof(llvm::fltSemantics *) +
Expand Down
13 changes: 13 additions & 0 deletions clang/lib/AST/ByteCode/Integral.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ template <unsigned Bits, bool Signed> class Integral final {
// The primitive representing the integral.
using ReprT = typename Repr<Bits, Signed>::Type;
ReprT V;
static_assert(std::is_trivially_copyable_v<ReprT>);

/// Primitive representing limits.
static const auto Min = std::numeric_limits<ReprT>::min();
Expand Down Expand Up @@ -154,6 +155,18 @@ template <unsigned Bits, bool Signed> class Integral final {
return Compare(V, RHS.V);
}

void bitcastToMemory(std::byte *Dest) const {
std::memcpy(Dest, &V, sizeof(V));
}

static Integral bitcastFromMemory(const std::byte *Src, unsigned BitWidth) {
assert(BitWidth == sizeof(ReprT) * 8);
ReprT V;

std::memcpy(&V, Src, sizeof(ReprT));
return Integral(V);
}

std::string toDiagnosticString(const ASTContext &Ctx) const {
std::string NameStr;
llvm::raw_string_ostream OS(NameStr);
Expand Down
10 changes: 10 additions & 0 deletions clang/lib/AST/ByteCode/IntegralAP.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,16 @@ template <bool Signed> class IntegralAP final {
return IntegralAP<false>(Copy);
}

void bitcastToMemory(std::byte *Dest) const {
llvm::StoreIntToMemory(V, (uint8_t *)Dest, bitWidth() / 8);
}

static IntegralAP bitcastFromMemory(const std::byte *Src, unsigned BitWidth) {
APInt V(BitWidth, static_cast<uint64_t>(0), Signed);
llvm::LoadIntFromMemory(V, (const uint8_t *)Src, BitWidth / 8);
return IntegralAP(V);
}

ComparisonCategoryResult compare(const IntegralAP &RHS) const {
assert(Signed == RHS.isSigned());
assert(bitWidth() == RHS.bitWidth());
Expand Down
17 changes: 17 additions & 0 deletions clang/lib/AST/ByteCode/Interp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1574,6 +1574,23 @@ bool CastPointerIntegralAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth) {
return true;
}

bool CheckBitCast(InterpState &S, CodePtr OpPC, bool HasIndeterminateBits,
bool TargetIsUCharOrByte) {
// This is always fine.
if (!HasIndeterminateBits)
return true;

// Indeterminate bits can only be bitcast to unsigned char or std::byte.
if (TargetIsUCharOrByte)
return true;

const Expr *E = S.Current->getExpr(OpPC);
QualType ExprType = E->getType();
S.FFDiag(E, diag::note_constexpr_bit_cast_indet_dest)
<< ExprType << S.getLangOpts().CharIsSigned << E->getSourceRange();
return false;
}

// https://github.com/llvm/llvm-project/issues/102513
#if defined(_WIN32) && !defined(__clang__) && !defined(NDEBUG)
#pragma optimize("", off)
Expand Down
61 changes: 59 additions & 2 deletions clang/lib/AST/ByteCode/Interp.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "Floating.h"
#include "Function.h"
#include "FunctionPointer.h"
#include "InterpBuiltinBitCast.h"
#include "InterpFrame.h"
#include "InterpStack.h"
#include "InterpState.h"
Expand Down Expand Up @@ -162,6 +163,8 @@ bool CallPtr(InterpState &S, CodePtr OpPC, uint32_t ArgSize,
const CallExpr *CE);
bool CheckLiteralType(InterpState &S, CodePtr OpPC, const Type *T);
bool InvalidShuffleVectorIndex(InterpState &S, CodePtr OpPC, uint32_t Index);
bool CheckBitCast(InterpState &S, CodePtr OpPC, bool HasIndeterminateBits,
bool TargetIsUCharOrByte);

template <typename T>
static bool handleOverflow(InterpState &S, CodePtr OpPC, const T &SrcValue) {
Expand Down Expand Up @@ -273,8 +276,14 @@ bool CheckArraySize(InterpState &S, CodePtr OpPC, SizeT *NumElements,
*NumElements > MaxElements) {
if (!IsNoThrow) {
const SourceInfo &Loc = S.Current->getSource(OpPC);
S.FFDiag(Loc, diag::note_constexpr_new_too_large)
<< NumElements->toDiagnosticString(S.getASTContext());

if (NumElements->isSigned() && NumElements->isNegative()) {
S.FFDiag(Loc, diag::note_constexpr_new_negative)
<< NumElements->toDiagnosticString(S.getASTContext());
} else {
S.FFDiag(Loc, diag::note_constexpr_new_too_large)
<< NumElements->toDiagnosticString(S.getASTContext());
}
}
return false;
}
Expand Down Expand Up @@ -3033,6 +3042,54 @@ bool CheckNewTypeMismatchArray(InterpState &S, CodePtr OpPC, const Expr *E) {
return CheckNewTypeMismatch(S, OpPC, E, static_cast<uint64_t>(Size));
}
bool InvalidNewDeleteExpr(InterpState &S, CodePtr OpPC, const Expr *E);

template <PrimType Name, class T = typename PrimConv<Name>::T>
inline bool BitCast(InterpState &S, CodePtr OpPC, bool TargetIsUCharOrByte,
uint32_t ResultBitWidth, const llvm::fltSemantics *Sem) {
const Pointer &FromPtr = S.Stk.pop<Pointer>();

if (!CheckLoad(S, OpPC, FromPtr))
return false;

size_t BuffSize = ResultBitWidth / 8;
llvm::SmallVector<std::byte> Buff(BuffSize);
bool HasIndeterminateBits = false;

if (!DoBitCast(S, OpPC, FromPtr, Buff.data(), BuffSize, HasIndeterminateBits))
return false;

if (!CheckBitCast(S, OpPC, HasIndeterminateBits, TargetIsUCharOrByte))
return false;

if constexpr (std::is_same_v<T, Floating>) {
assert(Sem);
ptrdiff_t Offset = 0;

if (llvm::sys::IsBigEndianHost) {
unsigned NumBits = llvm::APFloatBase::getSizeInBits(*Sem);
assert(NumBits % 8 == 0);
assert(NumBits <= ResultBitWidth);
Offset = (ResultBitWidth - NumBits) / 8;
}

S.Stk.push<Floating>(T::bitcastFromMemory(Buff.data() + Offset, *Sem));
} else {
assert(!Sem);
S.Stk.push<T>(T::bitcastFromMemory(Buff.data(), ResultBitWidth));
}
return true;
}

inline bool BitCastPtr(InterpState &S, CodePtr OpPC) {
const Pointer &FromPtr = S.Stk.pop<Pointer>();
Pointer &ToPtr = S.Stk.peek<Pointer>();

if (!DoBitCastPtr(S, OpPC, FromPtr, ToPtr))
return false;

return true;
}

//===----------------------------------------------------------------------===//
// Read opcode arguments
//===----------------------------------------------------------------------===//
Expand Down
17 changes: 11 additions & 6 deletions clang/lib/AST/ByteCode/InterpBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "Compiler.h"
#include "EvalEmitter.h"
#include "Interp.h"
#include "InterpBuiltinBitCast.h"
#include "PrimType.h"
#include "clang/AST/OSLog.h"
#include "clang/AST/RecordLayout.h"
Expand Down Expand Up @@ -1253,7 +1254,7 @@ static bool interp__builtin_ia32_bextr(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
const Function *Func,
const CallExpr *Call) {
if (!Call->getArg(0)->getType()->isIntegerType() ||
if (Call->getNumArgs() != 2 || !Call->getArg(0)->getType()->isIntegerType() ||
!Call->getArg(1)->getType()->isIntegerType())
return false;

Expand Down Expand Up @@ -1285,7 +1286,9 @@ static bool interp__builtin_ia32_bzhi(InterpState &S, CodePtr OpPC,
const Function *Func,
const CallExpr *Call) {
QualType CallType = Call->getType();
if (!CallType->isIntegerType())
if (Call->getNumArgs() != 2 || !Call->getArg(0)->getType()->isIntegerType() ||
!Call->getArg(1)->getType()->isIntegerType() ||
!CallType->isIntegerType())
return false;

PrimType ValT = *S.Ctx.classify(Call->getArg(0));
Expand All @@ -1310,7 +1313,8 @@ static bool interp__builtin_ia32_lzcnt(InterpState &S, CodePtr OpPC,
const Function *Func,
const CallExpr *Call) {
QualType CallType = Call->getType();
if (!CallType->isIntegerType())
if (!CallType->isIntegerType() ||
!Call->getArg(0)->getType()->isIntegerType())
return false;

APSInt Val = peekToAPSInt(S.Stk, *S.Ctx.classify(Call->getArg(0)));
Expand All @@ -1323,7 +1327,8 @@ static bool interp__builtin_ia32_tzcnt(InterpState &S, CodePtr OpPC,
const Function *Func,
const CallExpr *Call) {
QualType CallType = Call->getType();
if (!CallType->isIntegerType())
if (!CallType->isIntegerType() ||
!Call->getArg(0)->getType()->isIntegerType())
return false;

APSInt Val = peekToAPSInt(S.Stk, *S.Ctx.classify(Call->getArg(0)));
Expand All @@ -1335,7 +1340,7 @@ static bool interp__builtin_ia32_pdep(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
const Function *Func,
const CallExpr *Call) {
if (!Call->getArg(0)->getType()->isIntegerType() ||
if (Call->getNumArgs() != 2 || !Call->getArg(0)->getType()->isIntegerType() ||
!Call->getArg(1)->getType()->isIntegerType())
return false;

Expand All @@ -1360,7 +1365,7 @@ static bool interp__builtin_ia32_pext(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
const Function *Func,
const CallExpr *Call) {
if (!Call->getArg(0)->getType()->isIntegerType() ||
if (Call->getNumArgs() != 2 || !Call->getArg(0)->getType()->isIntegerType() ||
!Call->getArg(1)->getType()->isIntegerType())
return false;

Expand Down
420 changes: 420 additions & 0 deletions clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp

Large diffs are not rendered by default.

28 changes: 28 additions & 0 deletions clang/lib/AST/ByteCode/InterpBuiltinBitCast.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//===------------------ InterpBuiltinBitCast.h ------------------*- 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_AST_INTERP_BUILITN_BIT_CAST_H
#define LLVM_CLANG_AST_INTERP_BUILITN_BIT_CAST_H

#include <cstddef>

namespace clang {
namespace interp {
class Pointer;
class InterpState;
class CodePtr;

bool DoBitCast(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
std::byte *Buff, size_t BuffSize, bool &HasIndeterminateBits);
bool DoBitCastPtr(InterpState &S, CodePtr OpPC, const Pointer &FromPtr,
Pointer &ToPtr);

} // namespace interp
} // namespace clang

#endif
12 changes: 12 additions & 0 deletions clang/lib/AST/ByteCode/Opcodes.td
Original file line number Diff line number Diff line change
Expand Up @@ -837,3 +837,15 @@ def CheckNewTypeMismatchArray : Opcode {

def IsConstantContext: Opcode;
def CheckAllocations : Opcode;

def BitCastTypeClass : TypeClass {
let Types = [Uint8, Sint8, Uint16, Sint16, Uint32, Sint32, Uint64, Sint64, IntAP, IntAPS, Bool, Float];
}

def BitCast : Opcode {
let Types = [BitCastTypeClass];
let Args = [ArgBool, ArgUint32, ArgFltSemantics];
let HasGroup = 1;
}

def BitCastPtr : Opcode;
24 changes: 17 additions & 7 deletions clang/lib/AST/ByteCode/Pointer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -200,15 +200,26 @@ APValue Pointer::toAPValue(const ASTContext &ASTCtx) const {
// Build the path into the object.
Pointer Ptr = *this;
while (Ptr.isField() || Ptr.isArrayElement()) {

if (Ptr.isArrayRoot()) {
Path.push_back(APValue::LValuePathEntry(
{Ptr.getFieldDesc()->asDecl(), /*IsVirtual=*/false}));
// An array root may still be an array element itself.
if (Ptr.isArrayElement()) {
Ptr = Ptr.expand();
unsigned Index = Ptr.getIndex();
Path.push_back(APValue::LValuePathEntry::ArrayIndex(Index));
QualType ElemType = Ptr.getFieldDesc()->getElemQualType();
Offset += (Index * ASTCtx.getTypeSizeInChars(ElemType));
Ptr = Ptr.getArray();
} else {
Path.push_back(APValue::LValuePathEntry(
{Ptr.getFieldDesc()->asDecl(), /*IsVirtual=*/false}));

if (const auto *FD =
dyn_cast_if_present<FieldDecl>(Ptr.getFieldDesc()->asDecl()))
Offset += getFieldOffset(FD);
if (const auto *FD =
dyn_cast_if_present<FieldDecl>(Ptr.getFieldDesc()->asDecl()))
Offset += getFieldOffset(FD);

Ptr = Ptr.getBase();
Ptr = Ptr.getBase();
}
} else if (Ptr.isArrayElement()) {
Ptr = Ptr.expand();
unsigned Index;
Expand All @@ -219,7 +230,6 @@ APValue Pointer::toAPValue(const ASTContext &ASTCtx) const {

QualType ElemType = Ptr.getFieldDesc()->getElemQualType();
Offset += (Index * ASTCtx.getTypeSizeInChars(ElemType));

Path.push_back(APValue::LValuePathEntry::ArrayIndex(Index));
Ptr = Ptr.getArray();
} else {
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/AST/ByteCode/Program.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -399,10 +399,10 @@ Descriptor *Program::createDescriptor(const DeclTy &D, const Type *Ty,
}

// Arrays.
if (const auto ArrayType = Ty->getAsArrayTypeUnsafe()) {
if (const auto *ArrayType = Ty->getAsArrayTypeUnsafe()) {
QualType ElemTy = ArrayType->getElementType();
// Array of well-known bounds.
if (auto CAT = dyn_cast<ConstantArrayType>(ArrayType)) {
if (const auto *CAT = dyn_cast<ConstantArrayType>(ArrayType)) {
size_t NumElems = CAT->getZExtSize();
if (std::optional<PrimType> T = Ctx.classify(ElemTy)) {
// Arrays of primitives.
Expand Down
1 change: 1 addition & 0 deletions clang/lib/AST/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ add_clang_library(clangAST
ByteCode/Function.cpp
ByteCode/FunctionPointer.cpp
ByteCode/InterpBuiltin.cpp
ByteCode/InterpBuiltinBitCast.cpp
ByteCode/Floating.cpp
ByteCode/EvaluationResult.cpp
ByteCode/DynamicAllocator.cpp
Expand Down
10 changes: 5 additions & 5 deletions clang/lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2708,7 +2708,7 @@ VarDecl *VarDecl::getTemplateInstantiationPattern() const {
if (isTemplateInstantiation(VDTemplSpec->getTemplateSpecializationKind())) {
auto From = VDTemplSpec->getInstantiatedFrom();
if (auto *VTD = From.dyn_cast<VarTemplateDecl *>()) {
while (!VTD->hasMemberSpecialization()) {
while (!VTD->isMemberSpecialization()) {
if (auto *NewVTD = VTD->getInstantiatedFromMemberTemplate())
VTD = NewVTD;
else
Expand All @@ -2718,7 +2718,7 @@ VarDecl *VarDecl::getTemplateInstantiationPattern() const {
}
if (auto *VTPSD =
From.dyn_cast<VarTemplatePartialSpecializationDecl *>()) {
while (!VTPSD->hasMemberSpecialization()) {
while (!VTPSD->isMemberSpecialization()) {
if (auto *NewVTPSD = VTPSD->getInstantiatedFromMember())
VTPSD = NewVTPSD;
else
Expand All @@ -2732,7 +2732,7 @@ VarDecl *VarDecl::getTemplateInstantiationPattern() const {
// If this is the pattern of a variable template, find where it was
// instantiated from. FIXME: Is this necessary?
if (VarTemplateDecl *VTD = VD->getDescribedVarTemplate()) {
while (!VTD->hasMemberSpecialization()) {
while (!VTD->isMemberSpecialization()) {
if (auto *NewVTD = VTD->getInstantiatedFromMemberTemplate())
VTD = NewVTD;
else
Expand Down Expand Up @@ -4153,7 +4153,7 @@ FunctionDecl::getTemplateInstantiationPattern(bool ForDefinition) const {
if (FunctionTemplateDecl *Primary = getPrimaryTemplate()) {
// If we hit a point where the user provided a specialization of this
// template, we're done looking.
while (!ForDefinition || !Primary->hasMemberSpecialization()) {
while (!ForDefinition || !Primary->isMemberSpecialization()) {
if (auto *NewPrimary = Primary->getInstantiatedFromMemberTemplate())
Primary = NewPrimary;
else
Expand All @@ -4170,7 +4170,7 @@ FunctionTemplateDecl *FunctionDecl::getPrimaryTemplate() const {
if (FunctionTemplateSpecializationInfo *Info
= TemplateOrSpecialization
.dyn_cast<FunctionTemplateSpecializationInfo*>()) {
return Info->getTemplate();
return Info->getTemplate()->getMostRecentDecl();
}
return nullptr;
}
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/AST/DeclCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2030,7 +2030,7 @@ const CXXRecordDecl *CXXRecordDecl::getTemplateInstantiationPattern() const {
if (auto *TD = dyn_cast<ClassTemplateSpecializationDecl>(this)) {
auto From = TD->getInstantiatedFrom();
if (auto *CTD = From.dyn_cast<ClassTemplateDecl *>()) {
while (!CTD->hasMemberSpecialization()) {
while (!CTD->isMemberSpecialization()) {
if (auto *NewCTD = CTD->getInstantiatedFromMemberTemplate())
CTD = NewCTD;
else
Expand All @@ -2040,7 +2040,7 @@ const CXXRecordDecl *CXXRecordDecl::getTemplateInstantiationPattern() const {
}
if (auto *CTPSD =
From.dyn_cast<ClassTemplatePartialSpecializationDecl *>()) {
while (!CTPSD->hasMemberSpecialization()) {
while (!CTPSD->isMemberSpecialization()) {
if (auto *NewCTPSD = CTPSD->getInstantiatedFromMemberTemplate())
CTPSD = NewCTPSD;
else
Expand Down
56 changes: 54 additions & 2 deletions clang/lib/AST/DeclTemplate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -993,7 +993,17 @@ ClassTemplateSpecializationDecl::getSpecializedTemplate() const {
if (const auto *PartialSpec =
SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>())
return PartialSpec->PartialSpecialization->getSpecializedTemplate();
return SpecializedTemplate.get<ClassTemplateDecl*>();
return SpecializedTemplate.get<ClassTemplateDecl *>()->getMostRecentDecl();
}

llvm::PointerUnion<ClassTemplateDecl *,
ClassTemplatePartialSpecializationDecl *>
ClassTemplateSpecializationDecl::getSpecializedTemplateOrPartial() const {
if (const auto *PartialSpec =
SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization *>())
return PartialSpec->PartialSpecialization->getMostRecentDecl();

return SpecializedTemplate.get<ClassTemplateDecl *>()->getMostRecentDecl();
}

SourceRange
Expand Down Expand Up @@ -1283,6 +1293,39 @@ VarTemplateDecl::newCommon(ASTContext &C) const {
return CommonPtr;
}

void VarTemplateDecl::mergePrevDecl(VarTemplateDecl *Prev) {
// If we haven't created a common pointer yet, then it can just be created
// with the usual method.
if (!getCommonPtrInternal())
return;

Common *ThisCommon = static_cast<Common *>(getCommonPtrInternal());
Common *PrevCommon = nullptr;
SmallVector<VarTemplateDecl *, 8> PreviousDecls;
for (; Prev; Prev = Prev->getPreviousDecl()) {
if (CommonBase *C = Prev->getCommonPtrInternal()) {
PrevCommon = static_cast<Common *>(C);
break;
}
PreviousDecls.push_back(Prev);
}

// If the previous redecl chain hasn't created a common pointer yet, then just
// use this common pointer.
if (!PrevCommon) {
for (auto *D : PreviousDecls)
D->setCommonPtr(ThisCommon);
return;
}

// Ensure we don't leak any important state.
assert(ThisCommon->Specializations.empty() &&
ThisCommon->PartialSpecializations.empty() &&
"Can't merge incompatible declarations!");

setCommonPtr(PrevCommon);
}

VarTemplateSpecializationDecl *
VarTemplateDecl::findSpecialization(ArrayRef<TemplateArgument> Args,
void *&InsertPos) {
Expand Down Expand Up @@ -1405,7 +1448,16 @@ VarTemplateDecl *VarTemplateSpecializationDecl::getSpecializedTemplate() const {
if (const auto *PartialSpec =
SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization *>())
return PartialSpec->PartialSpecialization->getSpecializedTemplate();
return SpecializedTemplate.get<VarTemplateDecl *>();
return SpecializedTemplate.get<VarTemplateDecl *>()->getMostRecentDecl();
}

llvm::PointerUnion<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>
VarTemplateSpecializationDecl::getSpecializedTemplateOrPartial() const {
if (const auto *PartialSpec =
SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization *>())
return PartialSpec->PartialSpecialization->getMostRecentDecl();

return SpecializedTemplate.get<VarTemplateDecl *>()->getMostRecentDecl();
}

SourceRange VarTemplateSpecializationDecl::getSourceRange() const {
Expand Down
38 changes: 30 additions & 8 deletions clang/lib/AST/Type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
Expand Down Expand Up @@ -1241,8 +1242,8 @@ struct SimpleTransformVisitor : public TypeVisitor<Derived, QualType> {
== T->getEquivalentType().getAsOpaquePtr())
return QualType(T, 0);

return Ctx.getAttributedType(T->getAttrKind(), modifiedType,
equivalentType);
return Ctx.getAttributedType(T->getAttrKind(), modifiedType, equivalentType,
T->getAttr());
}

QualType VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T) {
Expand Down Expand Up @@ -1545,7 +1546,8 @@ struct SubstObjCTypeArgsVisitor

// Rebuild the attributed type.
return Ctx.getAttributedType(newAttrType->getAttrKind(),
newAttrType->getModifiedType(), newEquivType);
newAttrType->getModifiedType(), newEquivType,
newAttrType->getAttr());
}
};

Expand Down Expand Up @@ -4115,6 +4117,19 @@ bool RecordType::hasConstFields() const {
return false;
}

AttributedType::AttributedType(QualType canon, const Attr *attr,
QualType modified, QualType equivalent)
: AttributedType(canon, attr->getKind(), attr, modified, equivalent) {}

AttributedType::AttributedType(QualType canon, attr::Kind attrKind,
const Attr *attr, QualType modified,
QualType equivalent)
: Type(Attributed, canon, equivalent->getDependence()), Attribute(attr),
ModifiedType(modified), EquivalentType(equivalent) {
AttributedTypeBits.AttrKind = attrKind;
assert(!attr || attr->getKind() == attrKind);
}

bool AttributedType::isQualifier() const {
// FIXME: Generate this with TableGen.
switch (getAttrKind()) {
Expand Down Expand Up @@ -4760,7 +4775,10 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const {
->getTemplateName()
.getAsTemplateDecl())
if (auto *CTD = dyn_cast<ClassTemplateDecl>(templateDecl))
return CTD->getTemplatedDecl()->hasAttr<TypeNullableAttr>();
return llvm::any_of(
CTD->redecls(), [](const RedeclarableTemplateDecl *RTD) {
return RTD->getTemplatedDecl()->hasAttr<TypeNullableAttr>();
});
return ResultIfUnknown;

case Type::Builtin:
Expand Down Expand Up @@ -4827,10 +4845,14 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const {
// For template specializations, look only at primary template attributes.
// This is a consistent regardless of whether the instantiation is known.
if (const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(RD))
return CTSD->getSpecializedTemplate()
->getTemplatedDecl()
->hasAttr<TypeNullableAttr>();
return RD->hasAttr<TypeNullableAttr>();
return llvm::any_of(
CTSD->getSpecializedTemplate()->redecls(),
[](const RedeclarableTemplateDecl *RTD) {
return RTD->getTemplatedDecl()->hasAttr<TypeNullableAttr>();
});
return llvm::any_of(RD->redecls(), [](const TagDecl *RD) {
return RD->hasAttr<TypeNullableAttr>();
});
}

// Non-pointer types.
Expand Down
9 changes: 9 additions & 0 deletions clang/lib/AST/TypePrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1934,6 +1934,14 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
return;
}

if (T->getAttrKind() == attr::SwiftAttr) {
if (auto *swiftAttr = dyn_cast_or_null<SwiftAttrAttr>(T->getAttr())) {
OS << " __attribute__((swift_attr(\"" << swiftAttr->getAttribute()
<< "\")))";
}
return;
}

OS << " __attribute__((";
switch (T->getAttrKind()) {
#define TYPE_ATTR(NAME)
Expand Down Expand Up @@ -1994,6 +2002,7 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
case attr::NonAllocating:
case attr::Blocking:
case attr::Allocating:
case attr::SwiftAttr:
llvm_unreachable("This attribute should have been handled already");

case attr::NSReturnsRetained:
Expand Down
11 changes: 8 additions & 3 deletions clang/lib/Basic/DiagnosticIDs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,12 @@ DiagnosticIDs::getDiagnosticSeverity(unsigned DiagID, SourceLocation Loc,
DiagID != diag::fatal_too_many_errors && Diag.FatalsAsError)
Result = diag::Severity::Error;

// Rest of the mappings are only applicable for diagnostics associated with a
// SourceLocation, bail out early for others.
if (!Diag.hasSourceManager())
return Result;

const auto &SM = Diag.getSourceManager();
// Custom diagnostics always are emitted in system headers.
bool ShowInSystemHeader =
!GetDiagInfo(DiagID) || GetDiagInfo(DiagID)->WarnShowInSystemHeader;
Expand All @@ -583,15 +589,14 @@ DiagnosticIDs::getDiagnosticSeverity(unsigned DiagID, SourceLocation Loc,
// because we also want to ignore extensions and warnings in -Werror and
// -pedantic-errors modes, which *map* warnings/extensions to errors.
if (State->SuppressSystemWarnings && !ShowInSystemHeader && Loc.isValid() &&
Diag.getSourceManager().isInSystemHeader(
Diag.getSourceManager().getExpansionLoc(Loc)))
SM.isInSystemHeader(SM.getExpansionLoc(Loc)))
return diag::Severity::Ignored;

// We also ignore warnings due to system macros
bool ShowInSystemMacro =
!GetDiagInfo(DiagID) || GetDiagInfo(DiagID)->WarnShowInSystemMacro;
if (State->SuppressSystemWarnings && !ShowInSystemMacro && Loc.isValid() &&
Diag.getSourceManager().isInSystemMacro(Loc))
SM.isInSystemMacro(Loc))
return diag::Severity::Ignored;

return Result;
Expand Down
Loading