56 changes: 29 additions & 27 deletions clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,13 @@ class UseAfterMoveFinder {
// occurs after 'MovingCall' (the expression that performs the move). If a
// use-after-move is found, writes information about it to 'TheUseAfterMove'.
// Returns whether a use-after-move was found.
bool find(Stmt *CodeBlock, const Expr *MovingCall,
const DeclRefExpr *MovedVariable, UseAfterMove *TheUseAfterMove);
std::optional<UseAfterMove> find(Stmt *CodeBlock, const Expr *MovingCall,
const DeclRefExpr *MovedVariable);

private:
bool findInternal(const CFGBlock *Block, const Expr *MovingCall,
const ValueDecl *MovedVariable,
UseAfterMove *TheUseAfterMove);
std::optional<UseAfterMove> findInternal(const CFGBlock *Block,
const Expr *MovingCall,
const ValueDecl *MovedVariable);
void getUsesAndReinits(const CFGBlock *Block, const ValueDecl *MovedVariable,
llvm::SmallVectorImpl<const DeclRefExpr *> *Uses,
llvm::SmallPtrSetImpl<const Stmt *> *Reinits);
Expand Down Expand Up @@ -95,9 +95,9 @@ static StatementMatcher inDecltypeOrTemplateArg() {
UseAfterMoveFinder::UseAfterMoveFinder(ASTContext *TheContext)
: Context(TheContext) {}

bool UseAfterMoveFinder::find(Stmt *CodeBlock, const Expr *MovingCall,
const DeclRefExpr *MovedVariable,
UseAfterMove *TheUseAfterMove) {
std::optional<UseAfterMove>
UseAfterMoveFinder::find(Stmt *CodeBlock, const Expr *MovingCall,
const DeclRefExpr *MovedVariable) {
// Generate the CFG manually instead of through an AnalysisDeclContext because
// it seems the latter can't be used to generate a CFG for the body of a
// lambda.
Expand All @@ -111,7 +111,7 @@ bool UseAfterMoveFinder::find(Stmt *CodeBlock, const Expr *MovingCall,
std::unique_ptr<CFG> TheCFG =
CFG::buildCFG(nullptr, CodeBlock, Context, Options);
if (!TheCFG)
return false;
return std::nullopt;

Sequence = std::make_unique<ExprSequence>(TheCFG.get(), CodeBlock, Context);
BlockMap = std::make_unique<StmtToBlockMap>(TheCFG.get(), Context);
Expand All @@ -125,10 +125,10 @@ bool UseAfterMoveFinder::find(Stmt *CodeBlock, const Expr *MovingCall,
MoveBlock = &TheCFG->getEntry();
}

bool Found = findInternal(MoveBlock, MovingCall, MovedVariable->getDecl(),
TheUseAfterMove);
auto TheUseAfterMove =
findInternal(MoveBlock, MovingCall, MovedVariable->getDecl());

if (Found) {
if (TheUseAfterMove) {
if (const CFGBlock *UseBlock =
BlockMap->blockContainingStmt(TheUseAfterMove->DeclRef)) {
// Does the use happen in a later loop iteration than the move?
Expand All @@ -142,15 +142,14 @@ bool UseAfterMoveFinder::find(Stmt *CodeBlock, const Expr *MovingCall,
: CFA.isReachable(UseBlock, MoveBlock);
}
}
return Found;
return TheUseAfterMove;
}

bool UseAfterMoveFinder::findInternal(const CFGBlock *Block,
const Expr *MovingCall,
const ValueDecl *MovedVariable,
UseAfterMove *TheUseAfterMove) {
std::optional<UseAfterMove>
UseAfterMoveFinder::findInternal(const CFGBlock *Block, const Expr *MovingCall,
const ValueDecl *MovedVariable) {
if (Visited.count(Block))
return false;
return std::nullopt;

// Mark the block as visited (except if this is the block containing the
// std::move() and it's being visited the first time).
Expand Down Expand Up @@ -189,17 +188,18 @@ bool UseAfterMoveFinder::findInternal(const CFGBlock *Block,
}

if (!HaveSavingReinit) {
TheUseAfterMove->DeclRef = Use;
UseAfterMove TheUseAfterMove;
TheUseAfterMove.DeclRef = Use;

// Is this a use-after-move that depends on order of evaluation?
// This is the case if the move potentially comes after the use (and we
// already know that use potentially comes after the move, which taken
// together tells us that the ordering is unclear).
TheUseAfterMove->EvaluationOrderUndefined =
TheUseAfterMove.EvaluationOrderUndefined =
MovingCall != nullptr &&
Sequence->potentiallyAfter(MovingCall, Use);

return true;
return TheUseAfterMove;
}
}
}
Expand All @@ -208,12 +208,15 @@ bool UseAfterMoveFinder::findInternal(const CFGBlock *Block,
// successors.
if (Reinits.empty()) {
for (const auto &Succ : Block->succs()) {
if (Succ && findInternal(Succ, nullptr, MovedVariable, TheUseAfterMove))
return true;
if (Succ) {
if (auto Found = findInternal(Succ, nullptr, MovedVariable)) {
return Found;
}
}
}
}

return false;
return std::nullopt;
}

void UseAfterMoveFinder::getUsesAndReinits(
Expand Down Expand Up @@ -518,9 +521,8 @@ void UseAfterMoveCheck::check(const MatchFinder::MatchResult &Result) {

for (Stmt *CodeBlock : CodeBlocks) {
UseAfterMoveFinder Finder(Result.Context);
UseAfterMove Use;
if (Finder.find(CodeBlock, MovingCall, Arg, &Use))
emitDiagnostic(MovingCall, Arg, Use, this, Result.Context,
if (auto Use = Finder.find(CodeBlock, MovingCall, Arg))
emitDiagnostic(MovingCall, Arg, *Use, this, Result.Context,
determineMoveType(MoveDecl));
}
}
Expand Down
6 changes: 6 additions & 0 deletions clang-tools-extra/clang-tidy/misc/UseInternalLinkageCheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,12 @@ void UseInternalLinkageCheck::check(const MatchFinder::MatchResult &Result) {
return;
}
if (const auto *VD = Result.Nodes.getNodeAs<VarDecl>("var")) {
// In C++, const variables at file scope have implicit internal linkage,
// so we should not warn there. This is not the case in C.
// https://eel.is/c++draft/diff#basic-3
if (getLangOpts().CPlusPlus && VD->getType().isConstQualified())
return;

DiagnosticBuilder DB = diag(VD->getLocation(), Message) << "variable" << VD;
SourceLocation FixLoc = VD->getTypeSpecStartLoc();
if (FixLoc.isInvalid() || FixLoc.isMacroID())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,6 @@ int global_in_extern_c_1;
}

extern "C" int global_in_extern_c_2;

const int const_global = 123;
constexpr int constexpr_global = 123;
2 changes: 1 addition & 1 deletion clang/cmake/caches/Fuchsia-stage2.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ if(WIN32 OR LLVM_WINSYSROOT)
set(RUNTIMES_${target}_CMAKE_MODULE_LINKER_FLAGS ${WINDOWS_LINK_FLAGS} CACHE STRING "")
endif()

foreach(target aarch64-linux-gnu;armv7-linux-gnueabihf;i386-linux-gnu;riscv64-linux-gnu;x86_64-linux-gnu)
foreach(target aarch64-unknown-linux-gnu;armv7-unknown-linux-gnueabihf;i386-unknown-linux-gnu;riscv64-unknown-linux-gnu;x86_64-unknown-linux-gnu)
if(LINUX_${target}_SYSROOT)
# Set the per-target builtins options.
list(APPEND BUILTIN_TARGETS "${target}")
Expand Down
6 changes: 6 additions & 0 deletions clang/docs/CommandGuide/clang.rst
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,12 @@ number of cross compilers, or may only support a native target.
allowed to generate instructions that are valid on i486 and later processors,
but which may not exist on earlier ones.

.. option:: --print-enabled-extensions

Prints the list of extensions that are enabled for the target specified by the
combination of `--target`, `-march`, and `-mcpu` values. Currently, this
option is only supported on AArch64 and RISC-V. On RISC-V, this option also
prints out the ISA string of enabled extensions.

Code Generation Options
~~~~~~~~~~~~~~~~~~~~~~~
Expand Down
89 changes: 81 additions & 8 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ code bases.
C/C++ Language Potentially Breaking Changes
-------------------------------------------

- Clang now supports raw string literals in ``-std=gnuXY`` mode as an extension in
C99 and later. This behaviour can also be overridden using ``-f[no-]raw-string-literals``.
Support of raw string literals in C++ is not affected. Fixes (#GH85703).

C++ Specific Potentially Breaking Changes
-----------------------------------------
- Clang now diagnoses function/variable templates that shadow their own template parameters, e.g. ``template<class T> void T();``.
Expand Down Expand Up @@ -351,6 +355,9 @@ C23 Feature Support
- Clang now supports `N3017 <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3017.htm>`_
``#embed`` - a scannable, tooling-friendly binary resource inclusion mechanism.

- Added the ``FLT_NORM_MAX``, ``DBL_NORM_MAX``, and ``LDBL_NORM_MAX`` to the
freestanding implementation of ``<float.h>`` that ships with Clang.

Non-comprehensive list of changes in this release
-------------------------------------------------

Expand Down Expand Up @@ -445,6 +452,14 @@ New Compiler Flags
- ``-Wc++2c-compat`` group was added to help migrating existing codebases
to upcoming C++26.

- ``-fdisable-block-signature-string`` instructs clang not to emit the signature
string for blocks. Disabling the string can potentially break existing code
that relies on it. Users should carefully consider this possibiilty when using
the flag.

- For the ARM target, added ``-Warm-interrupt-vfp-clobber`` that will emit a
diagnostic when an interrupt handler is declared and VFP is enabled.

Deprecated Compiler Flags
-------------------------

Expand Down Expand Up @@ -487,6 +502,13 @@ Modified Compiler Flags
now include dianostics about C++26 features that are not present in older
versions.

- Removed the "arm interrupt calling convention" warning that was included in
``-Wextra`` without its own flag. This warning suggested adding
``__attribute__((interrupt))`` to functions that are called from interrupt
handlers to prevent clobbering VFP registers. Following this suggestion leads
to unpredictable behavior by causing multiple exception returns from one
exception. Fixes #GH34876.

Removed Compiler Flags
-------------------------

Expand Down Expand Up @@ -549,6 +571,19 @@ Attribute Changes in Clang
size_t count;
};
- The attributes ``sized_by``, ``counted_by_or_null`` and ``sized_by_or_null```
have been added as variants on ``counted_by``, each with slightly different semantics.
``sized_by`` takes a byte size parameter instead of an element count, allowing pointees
with unknown size. The ``counted_by_or_null`` and ``sized_by_or_null`` variants are equivalent
to their base variants, except the pointer can be null regardless of count/size value.
If the pointer is null the size is effectively 0. ``sized_by_or_null`` is needed to properly
annotate allocator functions like ``malloc`` that return a buffer of a given byte size, but can
also return null.

- The ``guarded_by``, ``pt_guarded_by``, ``acquired_after``, ``acquired_before``
attributes now support referencing struct members in C. The arguments are also
now late parsed when ``-fexperimental-late-parse-attributes`` is passed like
for ``counted_by``.

- Introduced new function type attributes ``[[clang::nonblocking]]``, ``[[clang::nonallocating]]``,
``[[clang::blocking]]``, and ``[[clang::allocating]]``, with GNU-style variants as well.
Expand Down Expand Up @@ -665,6 +700,11 @@ Improvements to Clang's diagnostics

- Clang now shows implicit deduction guides when diagnosing overload resolution failure. #GH92393.

- Clang no longer emits a "no previous prototype" warning for Win32 entry points under ``-Wmissing-prototypes``.
Fixes #GH94366.

- For the ARM target, calling an interrupt handler from another function is now an error. #GH95359.

Improvements to Clang's time-trace
----------------------------------

Expand Down Expand Up @@ -773,6 +813,8 @@ Bug Fixes in This Version

- Fixed `static_cast` to array of unknown bound. Fixes (#GH62863).

- Fixed Clang crashing when failing to perform some C++ Initialization Sequences. (#GH98102)

Bug Fixes to Compiler Builtins
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Expand Down Expand Up @@ -962,6 +1004,7 @@ Bug Fixes to C++ Support
- Fix a crash caused by improper use of ``__array_extent``. (#GH80474)
- Fixed several bugs in capturing variables within unevaluated contexts. (#GH63845), (#GH67260), (#GH69307),
(#GH88081), (#GH89496), (#GH90669) and (#GH91633).
- Fixed a crash in constraint instantiation under nested lambdas with dependent parameters.
- Fixed handling of brace ellison when building deduction guides. (#GH64625), (#GH83368).
- Clang now instantiates local constexpr functions eagerly for constant evaluators. (#GH35052), (#GH94849)
- Fixed a failed assertion when attempting to convert an integer representing the difference
Expand All @@ -978,6 +1021,7 @@ Bug Fixes to C++ Support
evaluated to an integer. (#GH96670).
- Fixed a bug where references to lambda capture inside a ``noexcept`` specifier were not correctly
instantiated. (#GH95735).
- Fixed a CTAD substitution bug involving type aliases that reference outer template parameters. (#GH94614).

Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down Expand Up @@ -1170,27 +1214,56 @@ libclang
Static Analyzer
---------------

New features
^^^^^^^^^^^^

- The attribute ``[[clang::suppress]]`` can now be applied to declarations.
(#GH80371)

- Support C++23 static operator calls. (#GH84972)

Crash and bug fixes
^^^^^^^^^^^^^^^^^^^

- Fixed crashing on loops if the loop variable was declared in switch blocks
but not under any case blocks if ``unroll-loops=true`` analyzer config is
set. (#GH68819)
- Support C++23 static operator calls. (#GH84972)

- Fixed a crash in ``security.cert.env.InvalidPtr`` checker when accidentally
matched user-defined ``strerror`` and similar library functions. (GH#88181)
matched user-defined ``strerror`` and similar library functions. (#GH88181)

- Fixed a crash when storing through an address that refers to the address of
a label. (GH#89185)
a label. (#GH89185)

New features
^^^^^^^^^^^^

Crash and bug fixes
^^^^^^^^^^^^^^^^^^^
- Z3 crosschecking (aka. Z3 refutation) is now bounded, and can't consume
more total time than the eymbolic execution itself. (#GH97298)

Improvements
^^^^^^^^^^^^

Moved checkers
^^^^^^^^^^^^^^

- Moved ``alpha.cplusplus.ArrayDelete`` out of the ``alpha`` package
to ``cplusplus.ArrayDelete``. (#GH83985)
`Documentation <https://clang.llvm.org/docs/analyzer/checkers.html#cplusplus-arraydelete-c>`__.

- Moved ``alpha.unix.Stream`` out of the ``alpha`` package to
``unix.Stream``. (#GH89247)
`Documentation <https://clang.llvm.org/docs/analyzer/checkers.html#unix-stream-c>`__.

- Moved ``alpha.unix.BlockInCriticalSection`` out of the ``alpha`` package to
``unix.BlockInCriticalSection``. (#GH93815)
`Documentation <https://clang.llvm.org/docs/analyzer/checkers.html#unix-blockincriticalsection-c-c>`__.

- Moved ``alpha.security.cert.pos.34c`` out of the ``alpha`` package to
``security.PutenvStackArray``. (#GH92424, #GH93815)
`Documentation <https://clang.llvm.org/docs/analyzer/checkers.html#security-putenvstackarray-c>`__.

- Moved ``alpha.core.SizeofPtr`` into ``clang-tidy``
``bugprone-sizeof-expression``. (#GH95118, #GH94356)
`Documentation <https://clang.llvm.org/extra/clang-tidy/checks/bugprone/sizeof-expression.html>`__.

.. _release-notes-sanitizers:

Sanitizers
Expand Down
68 changes: 68 additions & 0 deletions clang/docs/StandardCPlusPlusModules.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1092,6 +1092,74 @@ A high-level overview of support for standards features, including modules, can
be found on the `C++ Feature Status <https://clang.llvm.org/cxx_status.html>`_
page.

Missing VTables for classes attached to modules
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Now the compiler may miss emitting the definition of vtables
for classes attached to modules, if the definition of the class
doesn't contain any key function in that module units
(The key function is the first non-pure virtual function that is
not inline at the point of class definition.)

(Note: technically, the key function is not a thing for modules.
We use the concept here for convinient.)

For example,

.. code-block:: c++

// layer1.cppm
export module foo:layer1;
struct Fruit {
virtual ~Fruit() = default;
virtual void eval() = 0;
};
struct Banana : public Fruit {
Banana() {}
void eval() override;
};

// layer2.cppm
export module foo:layer2;
import :layer1;
export void layer2_fun() {
Banana *b = new Banana();
b->eval();
}
void Banana::eval() {
}
For the above example, we can't find the definition for the vtable of
class ``Banana`` in any object files.

The expected behavior is, for dynamic classes attached to named modules,
the vtable should always be emitted to the module units the class attaches
to.

To workaround the problem, users can add the key function manually in the
corresponding module units. e.g.,

.. code-block:: c++

// layer1.cppm
export module foo:layer1;
struct Fruit {
virtual ~Fruit() = default;
virtual void eval() = 0;
};
struct Banana : public Fruit {
// Hack a key function to hint the compiler to emit the virtual table.
virtual void anchor();

Banana() {}
void eval() override;
};

void Banana::anchor() {}

This is tracked by
`#70585 <https://github.com/llvm/llvm-project/issues/70585>`_.

Including headers after import is not well-supported
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Expand Down
7 changes: 4 additions & 3 deletions clang/docs/ThreadSafetyAnalysis.rst
Original file line number Diff line number Diff line change
Expand Up @@ -764,10 +764,11 @@ doesn't know that munl.mu == mutex. The SCOPED_CAPABILITY attribute handles
aliasing for MutexLocker, but does so only for that particular pattern.


ACQUIRED_BEFORE(...) and ACQUIRED_AFTER(...) are currently unimplemented.
-------------------------------------------------------------------------
ACQUIRED_BEFORE(...) and ACQUIRED_AFTER(...) support is still experimental.
---------------------------------------------------------------------------

To be fixed in a future update.
ACQUIRED_BEFORE(...) and ACQUIRED_AFTER(...) are currently being developed under
the ``-Wthread-safety-beta`` flag.


.. _mutexheader:
Expand Down
6 changes: 6 additions & 0 deletions clang/docs/UsersManual.rst
Original file line number Diff line number Diff line change
Expand Up @@ -913,6 +913,12 @@ Clang options that don't fit neatly into other categories.
binary compatibility issues on older x86_64 targets, however, so use it with
caution.

.. option:: -fdisable-block-signature-string

Instruct clang not to emit the signature string for blocks. Disabling the
string can potentially break existing code that relies on it. Users should
carefully consider this possibiilty when using the flag.

.. _configuration-files:

Configuration files
Expand Down
11 changes: 4 additions & 7 deletions clang/docs/analyzer/checkers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1003,17 +1003,14 @@ array new C++ operator is tainted (potentially attacker controlled).
If an attacker can inject a large value as the size parameter, memory exhaustion
denial of service attack can be carried out.
The ``alpha.security.taint.TaintPropagation`` checker also needs to be enabled for
this checker to give warnings.
The analyzer emits warning only if it cannot prove that the size parameter is
within reasonable bounds (``<= SIZE_MAX/4``). This functionality partially
covers the SEI Cert coding standard rule `INT04-C
<https://wiki.sei.cmu.edu/confluence/display/c/INT04-C.+Enforce+limits+on+integer+values+originating+from+tainted+sources>`_.
You can silence this warning either by bound checking the ``size`` parameter, or
by explicitly marking the ``size`` parameter as sanitized. See the
:ref:`alpha-security-taint-TaintPropagation` checker for more details.
:ref:`alpha-security-taint-GenericTaint` checker for an example.
.. code-block:: c
Expand Down Expand Up @@ -3011,10 +3008,10 @@ alpha.security.taint
Checkers implementing
`taint analysis <https://en.wikipedia.org/wiki/Taint_checking>`_.
.. _alpha-security-taint-TaintPropagation:
.. _alpha-security-taint-GenericTaint:
alpha.security.taint.TaintPropagation (C, C++)
""""""""""""""""""""""""""""""""""""""""""""""
alpha.security.taint.GenericTaint (C, C++)
""""""""""""""""""""""""""""""""""""""""""
Taint analysis identifies potential security vulnerabilities where the
attacker can inject malicious data to the program to execute an attack
Expand Down
13 changes: 8 additions & 5 deletions clang/docs/analyzer/user-docs/TaintAnalysisConfiguration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@
Taint Analysis Configuration
============================

The Clang Static Analyzer uses taint analysis to detect security-related issues in code.
The backbone of taint analysis in the Clang SA is the `GenericTaintChecker`, which the user can access via the :ref:`alpha-security-taint-TaintPropagation` checker alias and this checker has a default taint-related configuration.
The built-in default settings are defined in code, and they are always in effect once the checker is enabled, either directly or via the alias.
The checker also provides a configuration interface for extending the default settings by providing a configuration file in `YAML <http://llvm.org/docs/YamlIO.html#introduction-to-yaml>`_ format.
The Clang Static Analyzer uses taint analysis to detect injection vulnerability related issues in code.
The backbone of taint analysis in the Clang SA is the ``TaintPropagation`` modeling checker.
The reports are emitted via the :ref:`alpha-security-taint-GenericTaint` checker.
The ``TaintPropagation`` checker has a default taint-related configuration.
The built-in default settings are defined in code, and they are always in effect.
The checker also provides a configuration interface for extending the default settings via the ``alpha.security.taint.TaintPropagation:Config`` checker config parameter
by providing a configuration file to the in `YAML <http://llvm.org/docs/YamlIO.html#introduction-to-yaml>`_ format.
This documentation describes the syntax of the configuration file and gives the informal semantics of the configuration options.

.. contents::
Expand All @@ -18,7 +21,7 @@ ________

Taint analysis works by checking for the occurrence of special operations during the symbolic execution of the program.
Taint analysis defines sources, sinks, and propagation rules. It identifies errors by detecting a flow of information that originates from a taint source, reaches a taint sink, and propagates through the program paths via propagation rules.
A source, sink, or an operation that propagates taint is mainly domain-specific knowledge, but there are some built-in defaults provided by :ref:`alpha-security-taint-TaintPropagation`.
A source, sink, or an operation that propagates taint is mainly domain-specific knowledge, but there are some built-in defaults provided by the ``TaintPropagation`` checker.
It is possible to express that a statement sanitizes tainted values by providing a ``Filters`` section in the external configuration (see :ref:`clangsa-taint-configuration-example` and :ref:`clangsa-taint-filter-details`).
There are no default filters defined in the built-in settings.
The checker's documentation also specifies how to provide a custom taint configuration with command-line options.
Expand Down
4 changes: 2 additions & 2 deletions clang/include/clang/APINotes/APINotesReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ class APINotesReader {
/// \param Name The name of the class we're looking for.
///
/// \returns The information about the class, if known.
VersionedInfo<ObjCContextInfo> lookupObjCClassInfo(llvm::StringRef Name);
VersionedInfo<ContextInfo> lookupObjCClassInfo(llvm::StringRef Name);

/// Look for the context ID of the given Objective-C protocol.
///
Expand All @@ -115,7 +115,7 @@ class APINotesReader {
/// \param Name The name of the protocol we're looking for.
///
/// \returns The information about the protocol, if known.
VersionedInfo<ObjCContextInfo> lookupObjCProtocolInfo(llvm::StringRef Name);
VersionedInfo<ContextInfo> lookupObjCProtocolInfo(llvm::StringRef Name);

/// Look for information regarding the given Objective-C property in
/// the given context.
Expand Down
8 changes: 4 additions & 4 deletions clang/include/clang/APINotes/APINotesWriter.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,10 @@ class APINotesWriter {
///
/// \returns the ID of the class, protocol, or namespace, which can be used to
/// add properties and methods to the class/protocol/namespace.
ContextID addObjCContext(std::optional<ContextID> ParentCtxID,
llvm::StringRef Name, ContextKind Kind,
const ObjCContextInfo &Info,
llvm::VersionTuple SwiftVersion);
ContextID addContext(std::optional<ContextID> ParentCtxID,
llvm::StringRef Name, ContextKind Kind,
const ContextInfo &Info,
llvm::VersionTuple SwiftVersion);

/// Add information about a specific Objective-C property.
///
Expand Down
19 changes: 10 additions & 9 deletions clang/include/clang/APINotes/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -192,8 +192,9 @@ inline bool operator!=(const CommonTypeInfo &LHS, const CommonTypeInfo &RHS) {
return !(LHS == RHS);
}

/// Describes API notes data for an Objective-C class or protocol.
class ObjCContextInfo : public CommonTypeInfo {
/// Describes API notes data for an Objective-C class or protocol or a C++
/// namespace.
class ContextInfo : public CommonTypeInfo {
/// Whether this class has a default nullability.
LLVM_PREFERRED_TYPE(bool)
unsigned HasDefaultNullability : 1;
Expand All @@ -217,7 +218,7 @@ class ObjCContextInfo : public CommonTypeInfo {
unsigned SwiftObjCMembers : 1;

public:
ObjCContextInfo()
ContextInfo()
: HasDefaultNullability(0), DefaultNullability(0), HasDesignatedInits(0),
SwiftImportAsNonGenericSpecified(false), SwiftImportAsNonGeneric(false),
SwiftObjCMembersSpecified(false), SwiftObjCMembers(false) {}
Expand Down Expand Up @@ -269,9 +270,9 @@ class ObjCContextInfo : public CommonTypeInfo {
DefaultNullability = 0;
}

friend bool operator==(const ObjCContextInfo &, const ObjCContextInfo &);
friend bool operator==(const ContextInfo &, const ContextInfo &);

ObjCContextInfo &operator|=(const ObjCContextInfo &RHS) {
ContextInfo &operator|=(const ContextInfo &RHS) {
// Merge inherited info.
static_cast<CommonTypeInfo &>(*this) |= RHS;

Expand All @@ -294,15 +295,15 @@ class ObjCContextInfo : public CommonTypeInfo {
LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS);
};

inline bool operator==(const ObjCContextInfo &LHS, const ObjCContextInfo &RHS) {
inline bool operator==(const ContextInfo &LHS, const ContextInfo &RHS) {
return static_cast<const CommonTypeInfo &>(LHS) == RHS &&
LHS.getDefaultNullability() == RHS.getDefaultNullability() &&
LHS.HasDesignatedInits == RHS.HasDesignatedInits &&
LHS.getSwiftImportAsNonGeneric() == RHS.getSwiftImportAsNonGeneric() &&
LHS.getSwiftObjCMembers() == RHS.getSwiftObjCMembers();
}

inline bool operator!=(const ObjCContextInfo &LHS, const ObjCContextInfo &RHS) {
inline bool operator!=(const ContextInfo &LHS, const ContextInfo &RHS) {
return !(LHS == RHS);
}

Expand Down Expand Up @@ -387,7 +388,7 @@ class ObjCPropertyInfo : public VariableInfo {
friend bool operator==(const ObjCPropertyInfo &, const ObjCPropertyInfo &);

/// Merge class-wide information into the given property.
ObjCPropertyInfo &operator|=(const ObjCContextInfo &RHS) {
ObjCPropertyInfo &operator|=(const ContextInfo &RHS) {
static_cast<CommonEntityInfo &>(*this) |= RHS;

// Merge nullability.
Expand Down Expand Up @@ -626,7 +627,7 @@ class ObjCMethodInfo : public FunctionInfo {

friend bool operator==(const ObjCMethodInfo &, const ObjCMethodInfo &);

ObjCMethodInfo &operator|=(const ObjCContextInfo &RHS) {
ObjCMethodInfo &operator|=(const ContextInfo &RHS) {
// Merge Nullability.
if (!NullabilityAudited) {
if (auto Nullable = RHS.getDefaultNullability()) {
Expand Down
10 changes: 0 additions & 10 deletions clang/include/clang/AST/DeclBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -670,16 +670,6 @@ class alignas(8) Decl {
/// Whether this declaration comes from another module unit.
bool isInAnotherModuleUnit() const;

/// Whether this declaration comes from the same module unit being compiled.
bool isInCurrentModuleUnit() const;

/// Whether the definition of the declaration should be emitted in external
/// sources.
bool shouldEmitInExternalSource() const;

/// Whether this declaration comes from a named module;
bool isInNamedModule() const;

/// Whether this declaration comes from explicit global module.
bool isFromExplicitGlobalModule() const;

Expand Down
38 changes: 34 additions & 4 deletions clang/include/clang/Basic/Attr.td
Original file line number Diff line number Diff line change
Expand Up @@ -2292,6 +2292,36 @@ def CountedBy : DeclOrTypeAttr {
let LangOpts = [COnly];
}

def CountedByOrNull : DeclOrTypeAttr {
let Spellings = [Clang<"counted_by_or_null">];
let Subjects = SubjectList<[Field], ErrorDiag>;
let Args = [ExprArgument<"Count">, IntArgument<"NestedLevel", 1>];
let LateParsed = LateAttrParseExperimentalExt;
let ParseArgumentsAsUnevaluated = 1;
let Documentation = [CountedByDocs];
let LangOpts = [COnly];
}

def SizedBy : DeclOrTypeAttr {
let Spellings = [Clang<"sized_by">];
let Subjects = SubjectList<[Field], ErrorDiag>;
let Args = [ExprArgument<"Size">, IntArgument<"NestedLevel", 1>];
let LateParsed = LateAttrParseExperimentalExt;
let ParseArgumentsAsUnevaluated = 1;
let Documentation = [CountedByDocs];
let LangOpts = [COnly];
}

def SizedByOrNull : DeclOrTypeAttr {
let Spellings = [Clang<"sized_by_or_null">];
let Subjects = SubjectList<[Field], ErrorDiag>;
let Args = [ExprArgument<"Size">, IntArgument<"NestedLevel", 1>];
let LateParsed = LateAttrParseExperimentalExt;
let ParseArgumentsAsUnevaluated = 1;
let Documentation = [CountedByDocs];
let LangOpts = [COnly];
}

// This is a marker used to indicate that an __unsafe_unretained qualifier was
// ignored because ARC is not enabled. The usual representation for this
// qualifier is as an ObjCOwnership attribute with Kind == "none".
Expand Down Expand Up @@ -3660,7 +3690,7 @@ def NoThreadSafetyAnalysis : InheritableAttr {
def GuardedBy : InheritableAttr {
let Spellings = [GNU<"guarded_by">];
let Args = [ExprArgument<"Arg">];
let LateParsed = LateAttrParseStandard;
let LateParsed = LateAttrParseExperimentalExt;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
let InheritEvenIfAlreadyPresent = 1;
Expand All @@ -3671,7 +3701,7 @@ def GuardedBy : InheritableAttr {
def PtGuardedBy : InheritableAttr {
let Spellings = [GNU<"pt_guarded_by">];
let Args = [ExprArgument<"Arg">];
let LateParsed = LateAttrParseStandard;
let LateParsed = LateAttrParseExperimentalExt;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
let InheritEvenIfAlreadyPresent = 1;
Expand All @@ -3682,7 +3712,7 @@ def PtGuardedBy : InheritableAttr {
def AcquiredAfter : InheritableAttr {
let Spellings = [GNU<"acquired_after">];
let Args = [VariadicExprArgument<"Args">];
let LateParsed = LateAttrParseStandard;
let LateParsed = LateAttrParseExperimentalExt;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
let InheritEvenIfAlreadyPresent = 1;
Expand All @@ -3693,7 +3723,7 @@ def AcquiredAfter : InheritableAttr {
def AcquiredBefore : InheritableAttr {
let Spellings = [GNU<"acquired_before">];
let Args = [VariadicExprArgument<"Args">];
let LateParsed = LateAttrParseStandard;
let LateParsed = LateAttrParseExperimentalExt;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
let InheritEvenIfAlreadyPresent = 1;
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/CodeGenOptions.def
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ CODEGENOPT(NoImplicitFloat , 1, 0) ///< Set when -mno-implicit-float is enable
CODEGENOPT(NullPointerIsValid , 1, 0) ///< Assume Null pointer deference is defined.
CODEGENOPT(OpenCLCorrectlyRoundedDivSqrt, 1, 0) ///< -cl-fp32-correctly-rounded-divide-sqrt
CODEGENOPT(HIPCorrectlyRoundedDivSqrt, 1, 1) ///< -fno-hip-fp32-correctly-rounded-divide-sqrt
CODEGENOPT(DisableBlockSignatureString, 1, 0) ///< Set when -fdisable-block-signature-string is enabled.
CODEGENOPT(HIPSaveKernelArgName, 1, 0) ///< Set when -fhip-kernel-arg-name is enabled.
CODEGENOPT(UniqueInternalLinkageNames, 1, 0) ///< Internal Linkage symbols get unique names.
CODEGENOPT(SplitMachineFunctions, 1, 0) ///< Split machine functions using profile information.
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Basic/DiagnosticDriverKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,9 @@ def err_drv_negative_columns : Error<
"invalid value '%1' in '%0', value must be 'none' or a positive integer">;
def err_drv_small_columns : Error<
"invalid value '%1' in '%0', value must be '%2' or greater">;
def warn_drv_fraw_string_literals_in_cxx11 : Warning<
"ignoring '-f%select{no-|}0raw-string-literals', which is only valid for C and C++ standards before C++11">,
InGroup<UnusedCommandLineArgument>;

def err_drv_invalid_malign_branch_EQ : Error<
"invalid argument '%0' to -malign-branch=; each element must be one of: %1">;
Expand Down
39 changes: 21 additions & 18 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -336,9 +336,12 @@ def warn_anyx86_excessive_regsave : Warning<
" with attribute 'no_caller_saved_registers'"
" or be compiled with '-mgeneral-regs-only'">,
InGroup<DiagGroup<"excessive-regsave">>;
def warn_arm_interrupt_calling_convention : Warning<
"call to function without interrupt attribute could clobber interruptee's VFP registers">,
InGroup<Extra>;
def warn_arm_interrupt_vfp_clobber : Warning<
"interrupt service routine with vfp enabled may clobber the "
"interruptee's vfp state">,
InGroup<DiagGroup<"arm-interrupt-vfp-clobber">>;
def err_arm_interrupt_called : Error<
"interrupt service routine cannot be called directly">;
def warn_interrupt_attribute_invalid : Warning<
"%select{MIPS|MSP430|RISC-V}0 'interrupt' attribute only applies to "
"functions that have %select{no parameters|a 'void' return type}1">,
Expand Down Expand Up @@ -6567,28 +6570,28 @@ def warn_superclass_variable_sized_type_not_at_end : Warning<
"field %0 can overwrite instance variable %1 with variable sized type %2"
" in superclass %3">, InGroup<ObjCFlexibleArray>;

def err_flexible_array_count_not_in_same_struct : Error<
"'counted_by' field %0 isn't within the same struct as the flexible array">;
def err_counted_by_attr_not_on_ptr_or_flexible_array_member : Error<
"'counted_by' only applies to pointers or C99 flexible array members">;
def err_count_attr_param_not_in_same_struct : Error<
"'%select{counted_by|sized_by|counted_by_or_null|sized_by_or_null}1' field %0 isn't within the same struct as the annotated %select{pointer|flexible array}2">;
def err_count_attr_not_on_ptr_or_flexible_array_member : Error<
"'%select{counted_by|sized_by|counted_by_or_null|sized_by_or_null}0' only applies to pointers%select{ or C99 flexible array members|||}0%select{|; did you mean to use 'counted_by'?}1">;
def err_counted_by_attr_on_array_not_flexible_array_member : Error<
"'counted_by' on arrays only applies to C99 flexible array members">;
def err_counted_by_attr_refer_to_itself : Error<
"'counted_by' cannot refer to the flexible array member %0">;
def err_counted_by_must_be_in_structure : Error<
"field %0 in 'counted_by' not inside structure">;
def err_counted_by_attr_argument_not_integer : Error<
"'counted_by' requires a non-boolean integer type argument">;
def err_counted_by_attr_only_support_simple_decl_reference : Error<
"'counted_by' argument must be a simple declaration reference">;
def err_counted_by_attr_in_union : Error<
"'counted_by' cannot be applied to a union member">;
def err_counted_by_attr_refer_to_union : Error<
"'counted_by' argument cannot refer to a union member">;
def err_count_attr_must_be_in_structure : Error<
"field %0 in '%select{counted_by|sized_by|counted_by_or_null|sized_by_or_null}1' not inside structure">;
def err_count_attr_argument_not_integer : Error<
"'%select{counted_by|sized_by|counted_by_or_null|sized_by_or_null}0' requires a non-boolean integer type argument">;
def err_count_attr_only_support_simple_decl_reference : Error<
"'%select{counted_by|sized_by|counted_by_or_null|sized_by_or_null}0' argument must be a simple declaration reference">;
def err_count_attr_in_union : Error<
"'%select{counted_by|sized_by|counted_by_or_null|sized_by_or_null}0' cannot be applied to a union member">;
def err_count_attr_refer_to_union : Error<
"'%select{counted_by|sized_by|counted_by_or_null|sized_by_or_null}0' argument cannot refer to a union member">;
def note_flexible_array_counted_by_attr_field : Note<
"field %0 declared here">;
def err_counted_by_attr_pointee_unknown_size : Error<
"'counted_by' %select{cannot|should not}3 be applied to %select{"
"'%select{counted_by|sized_by|counted_by_or_null|sized_by_or_null}4' %select{cannot|should not}3 be applied to %select{"
"a pointer with pointee|" // pointer
"an array with element}0" // array
" of unknown size because %1 is %select{"
Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/Basic/LangOptions.def
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,8 @@ LANGOPT(MatrixTypes, 1, 0, "Enable or disable the builtin matrix type")

LANGOPT(CXXAssumptions, 1, 1, "Enable or disable codegen and compile-time checks for C++23's [[assume]] attribute")

LANGOPT(RawStringLiterals, 1, 1, "Enable or disable raw string literals")

ENUM_LANGOPT(StrictFlexArraysLevel, StrictFlexArraysLevelKind, 2,
StrictFlexArraysLevelKind::Default,
"Rely on strict definition of flexible arrays")
Expand Down
7 changes: 7 additions & 0 deletions clang/include/clang/Basic/LangStandard.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,13 @@ struct LangStandard {
/// hasDigraphs - Language supports digraphs.
bool hasDigraphs() const { return Flags & Digraphs; }

/// hasRawStringLiterals - Language supports R"()" raw string literals.
bool hasRawStringLiterals() const {
// GCC supports raw string literals in C99 and later, but not in C++
// before C++11.
return isCPlusPlus11() || (!isCPlusPlus() && isC99() && isGNUMode());
}

/// isGNUMode - Language includes GNU extensions.
bool isGNUMode() const { return Flags & GNUMode; }

Expand Down
49 changes: 46 additions & 3 deletions clang/include/clang/Basic/TargetInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Frontend/OpenMP/OMPGridValues.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/VersionTuple.h"
Expand Down Expand Up @@ -1400,15 +1402,15 @@ class TargetInfo : public TransferrableTargetInfo,
return true;
}

struct BranchProtectionInfo {
class BranchProtectionInfo {
public:
LangOptions::SignReturnAddressScopeKind SignReturnAddr;
LangOptions::SignReturnAddressKeyKind SignKey;
bool BranchTargetEnforcement;
bool BranchProtectionPAuthLR;
bool GuardedControlStack;

BranchProtectionInfo() = default;

protected:
const char *getSignReturnAddrStr() const {
switch (SignReturnAddr) {
case LangOptions::SignReturnAddressScopeKind::None:
Expand All @@ -1430,6 +1432,47 @@ class TargetInfo : public TransferrableTargetInfo,
}
llvm_unreachable("Unexpected SignReturnAddressKeyKind");
}

public:
BranchProtectionInfo()
: SignReturnAddr(LangOptions::SignReturnAddressScopeKind::None),
SignKey(LangOptions::SignReturnAddressKeyKind::AKey),
BranchTargetEnforcement(false), BranchProtectionPAuthLR(false),
GuardedControlStack(false) {}

BranchProtectionInfo(const LangOptions &LangOpts) {
SignReturnAddr =
LangOpts.hasSignReturnAddress()
? (LangOpts.isSignReturnAddressScopeAll()
? LangOptions::SignReturnAddressScopeKind::All
: LangOptions::SignReturnAddressScopeKind::NonLeaf)
: LangOptions::SignReturnAddressScopeKind::None;
SignKey = LangOpts.isSignReturnAddressWithAKey()
? LangOptions::SignReturnAddressKeyKind::AKey
: LangOptions::SignReturnAddressKeyKind::BKey;
BranchTargetEnforcement = LangOpts.BranchTargetEnforcement;
BranchProtectionPAuthLR = LangOpts.BranchProtectionPAuthLR;
GuardedControlStack = LangOpts.GuardedControlStack;
}

void setFnAttributes(llvm::Function &F) {
llvm::AttrBuilder FuncAttrs(F.getContext());
setFnAttributes(FuncAttrs);
F.addFnAttrs(FuncAttrs);
}

void setFnAttributes(llvm::AttrBuilder &FuncAttrs) {
if (SignReturnAddr != LangOptions::SignReturnAddressScopeKind::None) {
FuncAttrs.addAttribute("sign-return-address", getSignReturnAddrStr());
FuncAttrs.addAttribute("sign-return-address-key", getSignKeyStr());
}
if (BranchTargetEnforcement)
FuncAttrs.addAttribute("branch-target-enforcement");
if (BranchProtectionPAuthLR)
FuncAttrs.addAttribute("branch-protection-pauth-lr");
if (GuardedControlStack)
FuncAttrs.addAttribute("guarded-control-stack");
}
};

/// Determine if the Architecture in this TargetInfo supports branch
Expand Down
21 changes: 16 additions & 5 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -1618,6 +1618,7 @@ def shared_libsan : Flag<["-"], "shared-libsan">,
def static_libsan : Flag<["-"], "static-libsan">,
HelpText<"Statically link the sanitizer runtime (Not supported for ASan, TSan or UBSan on darwin)">;
def : Flag<["-"], "shared-libasan">, Alias<shared_libsan>;
def : Flag<["-"], "static-libasan">, Alias<static_libsan>;
def fasm : Flag<["-"], "fasm">, Group<f_Group>;

defm assume_unique_vtables : BoolFOption<"assume-unique-vtables",
Expand Down Expand Up @@ -3477,6 +3478,11 @@ defm objc_avoid_heapify_local_blocks : BoolFOption<"objc-avoid-heapify-local-blo
PosFlag<SetTrue, [], [ClangOption], "Try">,
NegFlag<SetFalse, [], [ClangOption], "Don't try">,
BothFlags<[], [CC1Option], " to avoid heapifying local blocks">>;
defm disable_block_signature_string : BoolFOption<"disable-block-signature-string",
CodeGenOpts<"DisableBlockSignatureString">, DefaultFalse,
PosFlag<SetTrue, [], [ClangOption], "Disable">,
NegFlag<SetFalse, [], [ClangOption], "Don't disable">,
BothFlags<[], [CC1Option], " block signature string)">>;

def fomit_frame_pointer : Flag<["-"], "fomit-frame-pointer">, Group<f_Group>,
Visibility<[ClangOption, FlangOption]>,
Expand Down Expand Up @@ -4235,6 +4241,12 @@ def fenable_matrix : Flag<["-"], "fenable-matrix">, Group<f_Group>,
HelpText<"Enable matrix data type and related builtin functions">,
MarshallingInfoFlag<LangOpts<"MatrixTypes">>;

defm raw_string_literals : BoolFOption<"raw-string-literals",
LangOpts<"RawStringLiterals">, Default<std#".hasRawStringLiterals()">,
PosFlag<SetTrue, [], [], "Enable">,
NegFlag<SetFalse, [], [], "Disable">,
BothFlags<[], [ClangOption, CC1Option], " raw string literals">>;

def fzero_call_used_regs_EQ
: Joined<["-"], "fzero-call-used-regs=">, Group<f_Group>,
Visibility<[ClangOption, CC1Option]>,
Expand Down Expand Up @@ -4917,6 +4929,9 @@ foreach i = {1-31} in
def ffixed_x#i : Flag<["-"], "ffixed-x"#i>, Group<m_Group>,
HelpText<"Reserve the x"#i#" register (AArch64/RISC-V only)">;

def mlr_for_calls_only : Flag<["-"], "mlr-for-calls-only">, Group<m_aarch64_Features_Group>,
HelpText<"Do not allocate the LR register for general purpose usage, only for calls. (AArch64 only)">;

foreach i = {8-15,18} in
def fcall_saved_x#i : Flag<["-"], "fcall-saved-x"#i>, Group<m_aarch64_Features_Group>,
HelpText<"Make the x"#i#" register call-saved (AArch64 only)">;
Expand Down Expand Up @@ -5504,10 +5519,6 @@ def pg : Flag<["-"], "pg">, HelpText<"Enable mcount instrumentation">,
MarshallingInfoFlag<CodeGenOpts<"InstrumentForProfiling">>;
def pipe : Flag<["-", "--"], "pipe">,
HelpText<"Use pipes between commands, when possible">;
// Facebook T92898286
def post_link_optimize : Flag<["--"], "post-link-optimize">,
HelpText<"Apply post-link optimizations using BOLT">;
// End Facebook T92898286
def prebind__all__twolevel__modules : Flag<["-"], "prebind_all_twolevel_modules">;
def prebind : Flag<["-"], "prebind">;
def preload : Flag<["-"], "preload">;
Expand Down Expand Up @@ -5723,7 +5734,7 @@ def print_supported_extensions : Flag<["-", "--"], "print-supported-extensions">
def print_enabled_extensions : Flag<["-", "--"], "print-enabled-extensions">,
Visibility<[ClangOption, CC1Option, CLOption]>,
HelpText<"Print the extensions enabled by the given target and -march/-mcpu options."
" (AArch64 only)">,
" (AArch64 and RISC-V only)">,
MarshallingInfoFlag<FrontendOpts<"PrintEnabledExtensions">>;
def : Flag<["-"], "mcpu=help">, Alias<print_supported_cpus>;
def : Flag<["-"], "mtune=help">, Alias<print_supported_cpus>;
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Driver/aarch64-mlr-for-calls-only.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// RUN: %clang --target=aarch64-none-gnu -mlr-for-calls-only -### %s 2> %t
// RUN: FileCheck --check-prefix=CHECK < %t %s
// CHECK: "-target-feature" "+reserve-lr-for-ra"
11 changes: 6 additions & 5 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -6341,7 +6341,7 @@ class Sema final : public SemaBase {
enum ExpressionKind {
EK_Decltype,
EK_TemplateArgument,
EK_BoundsAttrArgument,
EK_AttrArgument,
EK_Other
} ExprContext;

Expand Down Expand Up @@ -6454,10 +6454,9 @@ class Sema final : public SemaBase {
return const_cast<Sema *>(this)->parentEvaluationContext();
};

bool isBoundsAttrContext() const {
bool isAttrContext() const {
return ExprEvalContexts.back().ExprContext ==
ExpressionEvaluationContextRecord::ExpressionKind::
EK_BoundsAttrArgument;
ExpressionEvaluationContextRecord::ExpressionKind::EK_AttrArgument;
}

/// Increment when we find a reference; decrement when we find an ignored
Expand Down Expand Up @@ -14604,7 +14603,9 @@ class Sema final : public SemaBase {
SourceLocation AttrLoc);

QualType BuildCountAttributedArrayOrPointerType(QualType WrappedTy,
Expr *CountExpr);
Expr *CountExpr,
bool CountInBytes,
bool OrNull);

/// BuildAddressSpaceAttr - Builds a DependentAddressSpaceType if an
/// expression is uninstantiated. If instantiated it will apply the
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Sema/Template.h
Original file line number Diff line number Diff line change
Expand Up @@ -711,6 +711,7 @@ enum class TemplateSubstitutionKind : char {
VarTemplateSpecializationDecl *PrevDecl = nullptr);

Decl *InstantiateTypedefNameDecl(TypedefNameDecl *D, bool IsTypeAlias);
Decl *InstantiateTypeAliasTemplateDecl(TypeAliasTemplateDecl *D);
ClassTemplatePartialSpecializationDecl *
InstantiateClassTemplatePartialSpecialization(
ClassTemplateDecl *ClassTemplate,
Expand Down
3 changes: 0 additions & 3 deletions clang/include/clang/Serialization/ASTBitCodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -721,9 +721,6 @@ enum ASTRecordTypes {

/// Record code for \#pragma clang unsafe_buffer_usage begin/end
PP_UNSAFE_BUFFER_USAGE = 69,

/// Record code for vtables to emit.
VTABLES_TO_EMIT = 70,
};

/// Record types used within a source manager block.
Expand Down
6 changes: 0 additions & 6 deletions clang/include/clang/Serialization/ASTReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -790,11 +790,6 @@ class ASTReader
/// the consumer eagerly.
SmallVector<GlobalDeclID, 16> EagerlyDeserializedDecls;

/// The IDs of all vtables to emit. The referenced declarations are passed
/// to the consumers's HandleVTable eagerly after passing
/// EagerlyDeserializedDecls.
SmallVector<GlobalDeclID, 16> VTablesToEmit;

/// The IDs of all tentative definitions stored in the chain.
///
/// Sema keeps track of all tentative definitions in a TU because it has to
Expand Down Expand Up @@ -1505,7 +1500,6 @@ class ASTReader
bool isConsumerInterestedIn(Decl *D);
void PassInterestingDeclsToConsumer();
void PassInterestingDeclToConsumer(Decl *D);
void PassVTableToConsumer(CXXRecordDecl *RD);

void finishPendingActions();
void diagnoseOdrViolations();
Expand Down
7 changes: 0 additions & 7 deletions clang/include/clang/Serialization/ASTWriter.h
Original file line number Diff line number Diff line change
Expand Up @@ -500,10 +500,6 @@ class ASTWriter : public ASTDeserializationListener,
std::vector<SourceRange> NonAffectingRanges;
std::vector<SourceLocation::UIntTy> NonAffectingOffsetAdjustments;

/// A list of classes which need to emit the VTable in the corresponding
/// object file.
llvm::SmallVector<CXXRecordDecl *> PendingEmittingVTables;

/// Computes input files that didn't affect compilation of the current module,
/// and initializes data structures necessary for leaving those files out
/// during \c SourceManager serialization.
Expand Down Expand Up @@ -861,8 +857,6 @@ class ASTWriter : public ASTDeserializationListener,
return PredefinedDecls.count(D);
}

void handleVTable(CXXRecordDecl *RD);

private:
// ASTDeserializationListener implementation
void ReaderInitialized(ASTReader *Reader) override;
Expand Down Expand Up @@ -957,7 +951,6 @@ class PCHGenerator : public SemaConsumer {

void InitializeSema(Sema &S) override { SemaPtr = &S; }
void HandleTranslationUnit(ASTContext &Ctx) override;
void HandleVTable(CXXRecordDecl *RD) override { Writer.handleVTable(RD); }
ASTMutationListener *GetASTMutationListener() override;
ASTDeserializationListener *GetASTDeserializationListener() override;
bool hasEmittedPCH() const { return Buffer->IsComplete; }
Expand Down
12 changes: 8 additions & 4 deletions clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
Original file line number Diff line number Diff line change
Expand Up @@ -1071,7 +1071,7 @@ def ReturnPointerRangeChecker : Checker<"ReturnPtrRange">,

let ParentPackage = Taint in {

def GenericTaintChecker : Checker<"TaintPropagation">,
def TaintPropagationChecker : Checker<"TaintPropagation">, // Modelling checker
HelpText<"Generate taint information used by other checkers">,
CheckerOptions<[
CmdLineOption<String,
Expand All @@ -1080,6 +1080,12 @@ def GenericTaintChecker : Checker<"TaintPropagation">,
"",
InAlpha>,
]>,
Documentation<NotDocumented>,
Hidden;

def GenericTaintChecker : Checker<"GenericTaint">,
HelpText<"Reports potential injection vulnerabilities">,
Dependencies<[TaintPropagationChecker]>,
Documentation<HasDocumentation>;

} // end "alpha.security.taint"
Expand Down Expand Up @@ -1717,9 +1723,7 @@ let ParentPackage = TaintOptIn in {
def TaintedAllocChecker: Checker<"TaintedAlloc">,
HelpText<"Check for memory allocations, where the size parameter "
"might be a tainted (attacker controlled) value.">,
Dependencies<[DynamicMemoryModeling]>,
//FIXME: GenericTaintChecker should be a dependency, but only after it
//is transformed into a modeling checker
Dependencies<[DynamicMemoryModeling, TaintPropagationChecker]>,
Documentation<HasDocumentation>;

} // end "optin.taint"
Expand Down
20 changes: 10 additions & 10 deletions clang/lib/APINotes/APINotesFormat.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,26 +132,26 @@ using IdentifierDataLayout = llvm::BCRecordLayout<
>;
} // namespace identifier_block

namespace objc_context_block {
namespace context_block {
enum {
OBJC_CONTEXT_ID_DATA = 1,
OBJC_CONTEXT_INFO_DATA = 2,
CONTEXT_ID_DATA = 1,
CONTEXT_INFO_DATA = 2,
};

using ObjCContextIDLayout =
llvm::BCRecordLayout<OBJC_CONTEXT_ID_DATA, // record ID
using ContextIDLayout =
llvm::BCRecordLayout<CONTEXT_ID_DATA, // record ID
llvm::BCVBR<16>, // table offset within the blob (see
// below)
llvm::BCBlob // map from ObjC class names/protocol (as
// IDs) to context IDs
>;

using ObjCContextInfoLayout = llvm::BCRecordLayout<
OBJC_CONTEXT_INFO_DATA, // record ID
llvm::BCVBR<16>, // table offset within the blob (see below)
llvm::BCBlob // map from ObjC context IDs to context information.
using ContextInfoLayout = llvm::BCRecordLayout<
CONTEXT_INFO_DATA, // record ID
llvm::BCVBR<16>, // table offset within the blob (see below)
llvm::BCBlob // map from ObjC context IDs to context information.
>;
} // namespace objc_context_block
} // namespace context_block

namespace objc_property_block {
enum {
Expand Down
93 changes: 46 additions & 47 deletions clang/lib/APINotes/APINotesReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -176,8 +176,9 @@ class IdentifierTableInfo {
}
};

/// Used to deserialize the on-disk Objective-C class table.
class ObjCContextIDTableInfo {
/// Used to deserialize the on-disk table of Objective-C classes and C++
/// namespaces.
class ContextIDTableInfo {
public:
using internal_key_type = ContextTableKey;
using external_key_type = internal_key_type;
Expand Down Expand Up @@ -221,9 +222,8 @@ class ObjCContextIDTableInfo {
};

/// Used to deserialize the on-disk Objective-C property table.
class ObjCContextInfoTableInfo
: public VersionedTableInfo<ObjCContextInfoTableInfo, unsigned,
ObjCContextInfo> {
class ContextInfoTableInfo
: public VersionedTableInfo<ContextInfoTableInfo, unsigned, ContextInfo> {
public:
static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
return endian::readNext<uint32_t, llvm::endianness::little>(Data);
Expand All @@ -233,9 +233,9 @@ class ObjCContextInfoTableInfo
return static_cast<size_t>(llvm::hash_value(Key));
}

static ObjCContextInfo readUnversioned(internal_key_type Key,
const uint8_t *&Data) {
ObjCContextInfo Info;
static ContextInfo readUnversioned(internal_key_type Key,
const uint8_t *&Data) {
ContextInfo Info;
ReadCommonTypeInfo(Data, Info);
uint8_t Payload = *Data++;

Expand Down Expand Up @@ -614,17 +614,17 @@ class APINotesReader::Implementation {
/// The identifier table.
std::unique_ptr<SerializedIdentifierTable> IdentifierTable;

using SerializedObjCContextIDTable =
llvm::OnDiskIterableChainedHashTable<ObjCContextIDTableInfo>;
using SerializedContextIDTable =
llvm::OnDiskIterableChainedHashTable<ContextIDTableInfo>;

/// The Objective-C context ID table.
std::unique_ptr<SerializedObjCContextIDTable> ObjCContextIDTable;
/// The Objective-C / C++ context ID table.
std::unique_ptr<SerializedContextIDTable> ContextIDTable;

using SerializedObjCContextInfoTable =
llvm::OnDiskIterableChainedHashTable<ObjCContextInfoTableInfo>;
using SerializedContextInfoTable =
llvm::OnDiskIterableChainedHashTable<ContextInfoTableInfo>;

/// The Objective-C context info table.
std::unique_ptr<SerializedObjCContextInfoTable> ObjCContextInfoTable;
std::unique_ptr<SerializedContextInfoTable> ContextInfoTable;

using SerializedObjCPropertyTable =
llvm::OnDiskIterableChainedHashTable<ObjCPropertyTableInfo>;
Expand Down Expand Up @@ -685,8 +685,8 @@ class APINotesReader::Implementation {
llvm::SmallVectorImpl<uint64_t> &Scratch);
bool readIdentifierBlock(llvm::BitstreamCursor &Cursor,
llvm::SmallVectorImpl<uint64_t> &Scratch);
bool readObjCContextBlock(llvm::BitstreamCursor &Cursor,
llvm::SmallVectorImpl<uint64_t> &Scratch);
bool readContextBlock(llvm::BitstreamCursor &Cursor,
llvm::SmallVectorImpl<uint64_t> &Scratch);
bool readObjCPropertyBlock(llvm::BitstreamCursor &Cursor,
llvm::SmallVectorImpl<uint64_t> &Scratch);
bool readObjCMethodBlock(llvm::BitstreamCursor &Cursor,
Expand Down Expand Up @@ -906,7 +906,7 @@ bool APINotesReader::Implementation::readIdentifierBlock(
return false;
}

bool APINotesReader::Implementation::readObjCContextBlock(
bool APINotesReader::Implementation::readContextBlock(
llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
if (Cursor.EnterSubBlock(OBJC_CONTEXT_BLOCK_ID))
return true;
Expand Down Expand Up @@ -950,31 +950,30 @@ bool APINotesReader::Implementation::readObjCContextBlock(
}
unsigned Kind = MaybeKind.get();
switch (Kind) {
case objc_context_block::OBJC_CONTEXT_ID_DATA: {
// Already saw Objective-C context ID table.
if (ObjCContextIDTable)
case context_block::CONTEXT_ID_DATA: {
// Already saw Objective-C / C++ context ID table.
if (ContextIDTable)
return true;

uint32_t tableOffset;
objc_context_block::ObjCContextIDLayout::readRecord(Scratch, tableOffset);
context_block::ContextIDLayout::readRecord(Scratch, tableOffset);
auto base = reinterpret_cast<const uint8_t *>(BlobData.data());

ObjCContextIDTable.reset(SerializedObjCContextIDTable::Create(
ContextIDTable.reset(SerializedContextIDTable::Create(
base + tableOffset, base + sizeof(uint32_t), base));
break;
}

case objc_context_block::OBJC_CONTEXT_INFO_DATA: {
// Already saw Objective-C context info table.
if (ObjCContextInfoTable)
case context_block::CONTEXT_INFO_DATA: {
// Already saw Objective-C / C++ context info table.
if (ContextInfoTable)
return true;

uint32_t tableOffset;
objc_context_block::ObjCContextInfoLayout::readRecord(Scratch,
tableOffset);
context_block::ContextInfoLayout::readRecord(Scratch, tableOffset);
auto base = reinterpret_cast<const uint8_t *>(BlobData.data());

ObjCContextInfoTable.reset(SerializedObjCContextInfoTable::Create(
ContextInfoTable.reset(SerializedContextInfoTable::Create(
base + tableOffset, base + sizeof(uint32_t), base));
break;
}
Expand Down Expand Up @@ -1678,7 +1677,7 @@ APINotesReader::APINotesReader(llvm::MemoryBuffer *InputBuffer,

case OBJC_CONTEXT_BLOCK_ID:
if (!HasValidControlBlock ||
Implementation->readObjCContextBlock(Cursor, Scratch)) {
Implementation->readContextBlock(Cursor, Scratch)) {
Failed = true;
return;
}
Expand Down Expand Up @@ -1815,7 +1814,7 @@ APINotesReader::VersionedInfo<T>::VersionedInfo(

auto APINotesReader::lookupObjCClassID(llvm::StringRef Name)
-> std::optional<ContextID> {
if (!Implementation->ObjCContextIDTable)
if (!Implementation->ContextIDTable)
return std::nullopt;

std::optional<IdentifierID> ClassID = Implementation->getIdentifier(Name);
Expand All @@ -1824,33 +1823,33 @@ auto APINotesReader::lookupObjCClassID(llvm::StringRef Name)

// ObjC classes can't be declared in C++ namespaces, so use -1 as the global
// context.
auto KnownID = Implementation->ObjCContextIDTable->find(
auto KnownID = Implementation->ContextIDTable->find(
ContextTableKey(-1, (uint8_t)ContextKind::ObjCClass, *ClassID));
if (KnownID == Implementation->ObjCContextIDTable->end())
if (KnownID == Implementation->ContextIDTable->end())
return std::nullopt;

return ContextID(*KnownID);
}

auto APINotesReader::lookupObjCClassInfo(llvm::StringRef Name)
-> VersionedInfo<ObjCContextInfo> {
if (!Implementation->ObjCContextInfoTable)
-> VersionedInfo<ContextInfo> {
if (!Implementation->ContextInfoTable)
return std::nullopt;

std::optional<ContextID> CtxID = lookupObjCClassID(Name);
if (!CtxID)
return std::nullopt;

auto KnownInfo = Implementation->ObjCContextInfoTable->find(CtxID->Value);
if (KnownInfo == Implementation->ObjCContextInfoTable->end())
auto KnownInfo = Implementation->ContextInfoTable->find(CtxID->Value);
if (KnownInfo == Implementation->ContextInfoTable->end())
return std::nullopt;

return {Implementation->SwiftVersion, *KnownInfo};
}

auto APINotesReader::lookupObjCProtocolID(llvm::StringRef Name)
-> std::optional<ContextID> {
if (!Implementation->ObjCContextIDTable)
if (!Implementation->ContextIDTable)
return std::nullopt;

std::optional<IdentifierID> classID = Implementation->getIdentifier(Name);
Expand All @@ -1859,25 +1858,25 @@ auto APINotesReader::lookupObjCProtocolID(llvm::StringRef Name)

// ObjC classes can't be declared in C++ namespaces, so use -1 as the global
// context.
auto KnownID = Implementation->ObjCContextIDTable->find(
auto KnownID = Implementation->ContextIDTable->find(
ContextTableKey(-1, (uint8_t)ContextKind::ObjCProtocol, *classID));
if (KnownID == Implementation->ObjCContextIDTable->end())
if (KnownID == Implementation->ContextIDTable->end())
return std::nullopt;

return ContextID(*KnownID);
}

auto APINotesReader::lookupObjCProtocolInfo(llvm::StringRef Name)
-> VersionedInfo<ObjCContextInfo> {
if (!Implementation->ObjCContextInfoTable)
-> VersionedInfo<ContextInfo> {
if (!Implementation->ContextInfoTable)
return std::nullopt;

std::optional<ContextID> CtxID = lookupObjCProtocolID(Name);
if (!CtxID)
return std::nullopt;

auto KnownInfo = Implementation->ObjCContextInfoTable->find(CtxID->Value);
if (KnownInfo == Implementation->ObjCContextInfoTable->end())
auto KnownInfo = Implementation->ContextInfoTable->find(CtxID->Value);
if (KnownInfo == Implementation->ContextInfoTable->end())
return std::nullopt;

return {Implementation->SwiftVersion, *KnownInfo};
Expand Down Expand Up @@ -2014,7 +2013,7 @@ auto APINotesReader::lookupTypedef(llvm::StringRef Name,
auto APINotesReader::lookupNamespaceID(
llvm::StringRef Name, std::optional<ContextID> ParentNamespaceID)
-> std::optional<ContextID> {
if (!Implementation->ObjCContextIDTable)
if (!Implementation->ContextIDTable)
return std::nullopt;

std::optional<IdentifierID> NamespaceID = Implementation->getIdentifier(Name);
Expand All @@ -2023,9 +2022,9 @@ auto APINotesReader::lookupNamespaceID(

uint32_t RawParentNamespaceID =
ParentNamespaceID ? ParentNamespaceID->Value : -1;
auto KnownID = Implementation->ObjCContextIDTable->find(
auto KnownID = Implementation->ContextIDTable->find(
{RawParentNamespaceID, (uint8_t)ContextKind::Namespace, *NamespaceID});
if (KnownID == Implementation->ObjCContextIDTable->end())
if (KnownID == Implementation->ContextIDTable->end())
return std::nullopt;

return ContextID(*KnownID);
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/APINotes/APINotesTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ LLVM_DUMP_METHOD void CommonTypeInfo::dump(llvm::raw_ostream &OS) const {
OS << '\n';
}

LLVM_DUMP_METHOD void ObjCContextInfo::dump(llvm::raw_ostream &OS) {
LLVM_DUMP_METHOD void ContextInfo::dump(llvm::raw_ostream &OS) {
static_cast<CommonTypeInfo &>(*this).dump(OS);
if (HasDefaultNullability)
OS << "DefaultNullability: " << DefaultNullability << ' ';
Expand Down
71 changes: 35 additions & 36 deletions clang/lib/APINotes/APINotesWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,16 @@ class APINotesWriter::Implementation {
/// this context and provides both the context ID and information describing
/// the context within that module.
llvm::DenseMap<ContextTableKey,
std::pair<unsigned, VersionedSmallVector<ObjCContextInfo>>>
ObjCContexts;
std::pair<unsigned, VersionedSmallVector<ContextInfo>>>
Contexts;

/// Information about parent contexts for each context.
///
/// Indexed by context ID, provides the parent context ID.
llvm::DenseMap<uint32_t, uint32_t> ParentContexts;

/// Mapping from context IDs to the identifier ID holding the name.
llvm::DenseMap<unsigned, unsigned> ObjCContextNames;
llvm::DenseMap<unsigned, unsigned> ContextNames;

/// Information about Objective-C properties.
///
Expand Down Expand Up @@ -147,7 +147,7 @@ class APINotesWriter::Implementation {
void writeBlockInfoBlock(llvm::BitstreamWriter &Stream);
void writeControlBlock(llvm::BitstreamWriter &Stream);
void writeIdentifierBlock(llvm::BitstreamWriter &Stream);
void writeObjCContextBlock(llvm::BitstreamWriter &Stream);
void writeContextBlock(llvm::BitstreamWriter &Stream);
void writeObjCPropertyBlock(llvm::BitstreamWriter &Stream);
void writeObjCMethodBlock(llvm::BitstreamWriter &Stream);
void writeObjCSelectorBlock(llvm::BitstreamWriter &Stream);
Expand Down Expand Up @@ -178,7 +178,7 @@ void APINotesWriter::Implementation::writeToStream(llvm::raw_ostream &OS) {
writeBlockInfoBlock(Stream);
writeControlBlock(Stream);
writeIdentifierBlock(Stream);
writeObjCContextBlock(Stream);
writeContextBlock(Stream);
writeObjCPropertyBlock(Stream);
writeObjCMethodBlock(Stream);
writeObjCSelectorBlock(Stream);
Expand Down Expand Up @@ -240,7 +240,7 @@ void APINotesWriter::Implementation::writeBlockInfoBlock(
BLOCK_RECORD(identifier_block, IDENTIFIER_DATA);

BLOCK(OBJC_CONTEXT_BLOCK);
BLOCK_RECORD(objc_context_block, OBJC_CONTEXT_ID_DATA);
BLOCK_RECORD(context_block, CONTEXT_ID_DATA);

BLOCK(OBJC_PROPERTY_BLOCK);
BLOCK_RECORD(objc_property_block, OBJC_PROPERTY_DATA);
Expand Down Expand Up @@ -337,7 +337,7 @@ void APINotesWriter::Implementation::writeIdentifierBlock(

namespace {
/// Used to serialize the on-disk Objective-C context table.
class ObjCContextIDTableInfo {
class ContextIDTableInfo {
public:
using key_type = ContextTableKey;
using key_type_ref = key_type;
Expand Down Expand Up @@ -552,9 +552,8 @@ void emitCommonTypeInfo(raw_ostream &OS, const CommonTypeInfo &CTI) {
}

/// Used to serialize the on-disk Objective-C property table.
class ObjCContextInfoTableInfo
: public VersionedTableInfo<ObjCContextInfoTableInfo, unsigned,
ObjCContextInfo> {
class ContextInfoTableInfo
: public VersionedTableInfo<ContextInfoTableInfo, unsigned, ContextInfo> {
public:
unsigned getKeyLength(key_type_ref) { return sizeof(uint32_t); }

Expand All @@ -567,11 +566,11 @@ class ObjCContextInfoTableInfo
return static_cast<size_t>(llvm::hash_value(Key));
}

unsigned getUnversionedInfoSize(const ObjCContextInfo &OCI) {
unsigned getUnversionedInfoSize(const ContextInfo &OCI) {
return getCommonTypeInfoSize(OCI) + 1;
}

void emitUnversionedInfo(raw_ostream &OS, const ObjCContextInfo &OCI) {
void emitUnversionedInfo(raw_ostream &OS, const ContextInfo &OCI) {
emitCommonTypeInfo(OS, OCI);

uint8_t payload = 0;
Expand All @@ -590,19 +589,19 @@ class ObjCContextInfoTableInfo
};
} // namespace

void APINotesWriter::Implementation::writeObjCContextBlock(
void APINotesWriter::Implementation::writeContextBlock(
llvm::BitstreamWriter &Stream) {
llvm::BCBlockRAII restoreBlock(Stream, OBJC_CONTEXT_BLOCK_ID, 3);

if (ObjCContexts.empty())
if (Contexts.empty())
return;

{
llvm::SmallString<4096> HashTableBlob;
uint32_t Offset;
{
llvm::OnDiskChainedHashTableGenerator<ObjCContextIDTableInfo> Generator;
for (auto &OC : ObjCContexts)
llvm::OnDiskChainedHashTableGenerator<ContextIDTableInfo> Generator;
for (auto &OC : Contexts)
Generator.insert(OC.first, OC.second.first);

llvm::raw_svector_ostream BlobStream(HashTableBlob);
Expand All @@ -612,16 +611,16 @@ void APINotesWriter::Implementation::writeObjCContextBlock(
Offset = Generator.Emit(BlobStream);
}

objc_context_block::ObjCContextIDLayout ObjCContextID(Stream);
ObjCContextID.emit(Scratch, Offset, HashTableBlob);
context_block::ContextIDLayout ContextID(Stream);
ContextID.emit(Scratch, Offset, HashTableBlob);
}

{
llvm::SmallString<4096> HashTableBlob;
uint32_t Offset;
{
llvm::OnDiskChainedHashTableGenerator<ObjCContextInfoTableInfo> Generator;
for (auto &OC : ObjCContexts)
llvm::OnDiskChainedHashTableGenerator<ContextInfoTableInfo> Generator;
for (auto &OC : Contexts)
Generator.insert(OC.second.first, OC.second.second);

llvm::raw_svector_ostream BlobStream(HashTableBlob);
Expand All @@ -631,8 +630,8 @@ void APINotesWriter::Implementation::writeObjCContextBlock(
Offset = Generator.Emit(BlobStream);
}

objc_context_block::ObjCContextInfoLayout ObjCContextInfo(Stream);
ObjCContextInfo.emit(Scratch, Offset, HashTableBlob);
context_block::ContextInfoLayout ContextInfo(Stream);
ContextInfo.emit(Scratch, Offset, HashTableBlob);
}
}

Expand Down Expand Up @@ -1263,25 +1262,25 @@ void APINotesWriter::writeToStream(llvm::raw_ostream &OS) {
Implementation->writeToStream(OS);
}

ContextID APINotesWriter::addObjCContext(std::optional<ContextID> ParentCtxID,
StringRef Name, ContextKind Kind,
const ObjCContextInfo &Info,
VersionTuple SwiftVersion) {
ContextID APINotesWriter::addContext(std::optional<ContextID> ParentCtxID,
llvm::StringRef Name, ContextKind Kind,
const ContextInfo &Info,
llvm::VersionTuple SwiftVersion) {
IdentifierID NameID = Implementation->getIdentifier(Name);

uint32_t RawParentCtxID = ParentCtxID ? ParentCtxID->Value : -1;
ContextTableKey Key(RawParentCtxID, static_cast<uint8_t>(Kind), NameID);
auto Known = Implementation->ObjCContexts.find(Key);
if (Known == Implementation->ObjCContexts.end()) {
unsigned NextID = Implementation->ObjCContexts.size() + 1;
auto Known = Implementation->Contexts.find(Key);
if (Known == Implementation->Contexts.end()) {
unsigned NextID = Implementation->Contexts.size() + 1;

Implementation::VersionedSmallVector<ObjCContextInfo> EmptyVersionedInfo;
Known = Implementation->ObjCContexts
Implementation::VersionedSmallVector<ContextInfo> EmptyVersionedInfo;
Known = Implementation->Contexts
.insert(std::make_pair(
Key, std::make_pair(NextID, EmptyVersionedInfo)))
.first;

Implementation->ObjCContextNames[NextID] = NameID;
Implementation->ContextNames[NextID] = NameID;
Implementation->ParentContexts[NextID] = RawParentCtxID;
}

Expand Down Expand Up @@ -1328,9 +1327,9 @@ void APINotesWriter::addObjCMethod(ContextID CtxID, ObjCSelectorRef Selector,
uint32_t ParentCtxID = Implementation->ParentContexts[CtxID.Value];
ContextTableKey CtxKey(ParentCtxID,
static_cast<uint8_t>(ContextKind::ObjCClass),
Implementation->ObjCContextNames[CtxID.Value]);
assert(Implementation->ObjCContexts.contains(CtxKey));
auto &VersionedVec = Implementation->ObjCContexts[CtxKey].second;
Implementation->ContextNames[CtxID.Value]);
assert(Implementation->Contexts.contains(CtxKey));
auto &VersionedVec = Implementation->Contexts[CtxKey].second;
bool Found = false;
for (auto &Versioned : VersionedVec) {
if (Versioned.first == SwiftVersion) {
Expand All @@ -1341,7 +1340,7 @@ void APINotesWriter::addObjCMethod(ContextID CtxID, ObjCSelectorRef Selector,
}

if (!Found) {
VersionedVec.push_back({SwiftVersion, ObjCContextInfo()});
VersionedVec.push_back({SwiftVersion, ContextInfo()});
VersionedVec.back().second.setHasDesignatedInits(true);
}
}
Expand Down
10 changes: 5 additions & 5 deletions clang/lib/APINotes/APINotesYAMLCompiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -786,7 +786,7 @@ class YAMLConverter {
void convertContext(std::optional<ContextID> ParentContextID, const Class &C,
ContextKind Kind, VersionTuple SwiftVersion) {
// Write the class.
ObjCContextInfo CI;
ContextInfo CI;
convertCommonType(C, CI, C.Name);

if (C.AuditedForNullability)
Expand All @@ -797,7 +797,7 @@ class YAMLConverter {
CI.setSwiftObjCMembers(*C.SwiftObjCMembers);

ContextID CtxID =
Writer.addObjCContext(ParentContextID, C.Name, Kind, CI, SwiftVersion);
Writer.addContext(ParentContextID, C.Name, Kind, CI, SwiftVersion);

// Write all methods.
llvm::StringMap<std::pair<bool, bool>> KnownMethods;
Expand Down Expand Up @@ -863,12 +863,12 @@ class YAMLConverter {
const Namespace &TheNamespace,
VersionTuple SwiftVersion) {
// Write the namespace.
ObjCContextInfo CI;
ContextInfo CI;
convertCommonEntity(TheNamespace, CI, TheNamespace.Name);

ContextID CtxID =
Writer.addObjCContext(ParentContextID, TheNamespace.Name,
ContextKind::Namespace, CI, SwiftVersion);
Writer.addContext(ParentContextID, TheNamespace.Name,
ContextKind::Namespace, CI, SwiftVersion);

convertTopLevelItems(Context(CtxID, ContextKind::Namespace),
TheNamespace.Items, SwiftVersion);
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12116,7 +12116,7 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) {
return false;

// Variables in other module units shouldn't be forced to be emitted.
if (VD->shouldEmitInExternalSource())
if (VD->isInAnotherModuleUnit())
return false;

// Variables that can be needed in other TUs are required.
Expand Down
11 changes: 9 additions & 2 deletions clang/lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1181,6 +1181,13 @@ Linkage NamedDecl::getLinkageInternal() const {
.getLinkage();
}

/// Determine whether D is attached to a named module.
static bool isInNamedModule(const NamedDecl *D) {
if (auto *M = D->getOwningModule())
return M->isNamedModule();
return false;
}

static bool isExportedFromModuleInterfaceUnit(const NamedDecl *D) {
// FIXME: Handle isModulePrivate.
switch (D->getModuleOwnershipKind()) {
Expand All @@ -1190,7 +1197,7 @@ static bool isExportedFromModuleInterfaceUnit(const NamedDecl *D) {
return false;
case Decl::ModuleOwnershipKind::Visible:
case Decl::ModuleOwnershipKind::VisibleWhenImported:
return D->isInNamedModule();
return isInNamedModule(D);
}
llvm_unreachable("unexpected module ownership kind");
}
Expand All @@ -1208,7 +1215,7 @@ Linkage NamedDecl::getFormalLinkage() const {
// [basic.namespace.general]/p2
// A namespace is never attached to a named module and never has a name with
// module linkage.
if (isInNamedModule() && InternalLinkage == Linkage::External &&
if (isInNamedModule(this) && InternalLinkage == Linkage::External &&
!isExportedFromModuleInterfaceUnit(
cast<NamedDecl>(this->getCanonicalDecl())) &&
!isa<NamespaceDecl>(this))
Expand Down
30 changes: 11 additions & 19 deletions clang/lib/AST/DeclBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1122,31 +1122,23 @@ bool Decl::isInExportDeclContext() const {
bool Decl::isInAnotherModuleUnit() const {
auto *M = getOwningModule();

if (!M || !M->isNamedModule())
if (!M)
return false;

return M != getASTContext().getCurrentNamedModule();
}

bool Decl::isInCurrentModuleUnit() const {
auto *M = getOwningModule();

if (!M || !M->isNamedModule())
M = M->getTopLevelModule();
// FIXME: It is problematic if the header module lives in another module
// unit. Consider to fix this by techniques like
// ExternalASTSource::hasExternalDefinitions.
if (M->isHeaderLikeModule())
return false;

return M == getASTContext().getCurrentNamedModule();
}

bool Decl::shouldEmitInExternalSource() const {
ExternalASTSource *Source = getASTContext().getExternalSource();
if (!Source)
// A global module without parent implies that we're parsing the global
// module. So it can't be in another module unit.
if (M->isGlobalModule())
return false;

return Source->hasExternalDefinitions(this) == ExternalASTSource::EK_Always;
}

bool Decl::isInNamedModule() const {
return getOwningModule() && getOwningModule()->isNamedModule();
assert(M->isNamedModule() && "New module kind?");
return M != getASTContext().getCurrentNamedModule();
}

bool Decl::isFromExplicitGlobalModule() const {
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/Interp/ByteCodeEmitter.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class ByteCodeEmitter {
/// Methods implemented by the compiler.
virtual bool visitFunc(const FunctionDecl *E) = 0;
virtual bool visitExpr(const Expr *E) = 0;
virtual bool visitDecl(const VarDecl *E, bool ConstantContext) = 0;
virtual bool visitDeclAndReturn(const VarDecl *E, bool ConstantContext) = 0;

/// Emits jumps.
bool jumpTrue(const LabelTy &Label);
Expand Down
153 changes: 86 additions & 67 deletions clang/lib/AST/Interp/Compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ namespace clang {
namespace interp {

/// Scope used to handle temporaries in toplevel variable declarations.
template <class Emitter> class DeclScope final : public VariableScope<Emitter> {
template <class Emitter> class DeclScope final : public LocalScope<Emitter> {
public:
DeclScope(Compiler<Emitter> *Ctx, const ValueDecl *VD)
: VariableScope<Emitter>(Ctx, nullptr), Scope(Ctx->P, VD),
: LocalScope<Emitter>(Ctx, VD), Scope(Ctx->P, VD),
OldGlobalDecl(Ctx->GlobalDecl),
OldInitializingDecl(Ctx->InitializingDecl) {
Ctx->GlobalDecl = Context::shouldBeGloballyIndexed(VD);
Expand Down Expand Up @@ -1794,6 +1794,8 @@ bool Compiler<Emitter>::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E) {

if (!this->visitArrayElemInit(I, SubExpr))
return false;
if (!BS.destroyLocals())
return false;
}
return true;
}
Expand Down Expand Up @@ -2204,7 +2206,7 @@ bool Compiler<Emitter>::VisitCompoundAssignOperator(

template <class Emitter>
bool Compiler<Emitter>::VisitExprWithCleanups(const ExprWithCleanups *E) {
ExprScope<Emitter> ES(this);
LocalScope<Emitter> ES(this);
const Expr *SubExpr = E->getSubExpr();

assert(E->getNumObjects() == 0 && "TODO: Implement cleanups");
Expand Down Expand Up @@ -3080,7 +3082,7 @@ bool Compiler<Emitter>::VisitStmtExpr(const StmtExpr *E) {
return false;
}

return true;
return BS.destroyLocals();
}

template <class Emitter> bool Compiler<Emitter>::discard(const Expr *E) {
Expand Down Expand Up @@ -3425,7 +3427,7 @@ const Function *Compiler<Emitter>::getFunction(const FunctionDecl *FD) {
}

template <class Emitter> bool Compiler<Emitter>::visitExpr(const Expr *E) {
ExprScope<Emitter> RootScope(this);
LocalScope<Emitter> RootScope(this);
// Void expressions.
if (E->getType()->isVoidType()) {
if (!visit(E))
Expand Down Expand Up @@ -3462,40 +3464,52 @@ template <class Emitter> bool Compiler<Emitter>::visitExpr(const Expr *E) {
return false;
}

/// Toplevel visitDecl().
template <class Emitter>
VarCreationState Compiler<Emitter>::visitDecl(const VarDecl *VD) {

auto R = this->visitVarDecl(VD, /*Toplevel=*/true);

if (R.notCreated())
return R;

if (R)
return true;

if (!R && Context::shouldBeGloballyIndexed(VD)) {
if (auto GlobalIndex = P.getGlobal(VD)) {
Block *GlobalBlock = P.getGlobal(*GlobalIndex);
GlobalInlineDescriptor &GD =
*reinterpret_cast<GlobalInlineDescriptor *>(GlobalBlock->rawData());

GD.InitState = GlobalInitState::InitializerFailed;
GlobalBlock->invokeDtor();
}
}

return R;
}

/// Toplevel visitDeclAndReturn().
/// We get here from evaluateAsInitializer().
/// We need to evaluate the initializer and return its value.
template <class Emitter>
bool Compiler<Emitter>::visitDecl(const VarDecl *VD, bool ConstantContext) {
assert(!VD->isInvalidDecl() && "Trying to constant evaluate an invalid decl");

bool Compiler<Emitter>::visitDeclAndReturn(const VarDecl *VD,
bool ConstantContext) {
std::optional<PrimType> VarT = classify(VD->getType());

// We only create variables if we're evaluating in a constant context.
// Otherwise, just evaluate the initializer and return it.
if (!ConstantContext) {
DeclScope<Emitter> LocalScope(this, VD);
DeclScope<Emitter> LS(this, VD);
if (!this->visit(VD->getAnyInitializer()))
return false;
return this->emitRet(VarT.value_or(PT_Ptr), VD);
}

// If we've seen the global variable already and the initializer failed,
// just return false immediately.
if (std::optional<unsigned> Index = P.getGlobal(VD)) {
const Pointer &Ptr = P.getPtrGlobal(*Index);
const GlobalInlineDescriptor &GD =
*reinterpret_cast<const GlobalInlineDescriptor *>(
Ptr.block()->rawData());
if (GD.InitState == GlobalInitState::InitializerFailed)
return false;
return this->emitRet(VarT.value_or(PT_Ptr), VD) && LS.destroyLocals();
}

// Create and initialize the variable.
LocalScope<Emitter> VDScope(this, VD);
if (!this->visitVarDecl(VD, /*Toplevel=*/true))
return false;

// Get a pointer to the variable
if (Context::shouldBeGloballyIndexed(VD)) {
auto GlobalIndex = P.getGlobal(VD);
assert(GlobalIndex); // visitVarDecl() didn't return false.
Expand Down Expand Up @@ -3535,7 +3549,7 @@ bool Compiler<Emitter>::visitDecl(const VarDecl *VD, bool ConstantContext) {
return false;
}

return true;
return VDScope.destroyLocals();
}

template <class Emitter>
Expand All @@ -3552,12 +3566,12 @@ VarCreationState Compiler<Emitter>::visitVarDecl(const VarDecl *VD, bool Topleve
const Expr *Init = VD->getInit();
std::optional<PrimType> VarT = classify(VD->getType());

auto checkDecl = [&]() -> bool {
bool NeedsOp = !Toplevel && VD->isLocalVarDecl() && VD->isStaticLocal();
return !NeedsOp || this->emitCheckDecl(VD, VD);
};

if (Context::shouldBeGloballyIndexed(VD)) {
auto checkDecl = [&]() -> bool {
bool NeedsOp = !Toplevel && VD->isLocalVarDecl() && VD->isStaticLocal();
return !NeedsOp || this->emitCheckDecl(VD, VD);
};

auto initGlobal = [&](unsigned GlobalIndex) -> bool {
assert(Init);
DeclScope<Emitter> LocalScope(this, VD);
Expand Down Expand Up @@ -3589,26 +3603,34 @@ VarCreationState Compiler<Emitter>::visitVarDecl(const VarDecl *VD, bool Topleve

return !Init || (checkDecl() && initGlobal(*GlobalIndex));
} else {
VariableScope<Emitter> LocalScope(this, VD);
InitLinkScope<Emitter> ILS(this, InitLink::Decl(VD));

if (VarT) {
unsigned Offset = this->allocateLocalPrimitive(
VD, *VarT, VD->getType().isConstQualified());
if (Init) {
// Compile the initializer in its own scope.
ExprScope<Emitter> Scope(this);
if (!this->visit(Init))
return false;

return this->emitSetLocal(*VarT, Offset, VD);
// If this is a toplevel declaration, create a scope for the
// initializer.
if (Toplevel) {
LocalScope<Emitter> Scope(this);
if (!this->visit(Init))
return false;
return this->emitSetLocal(*VarT, Offset, VD) && Scope.destroyLocals();
} else {
if (!this->visit(Init))
return false;
return this->emitSetLocal(*VarT, Offset, VD);
}
}
} else {
if (std::optional<unsigned> Offset = this->allocateLocal(VD))
return !Init || this->visitLocalInitializer(Init, *Offset);
if (std::optional<unsigned> Offset = this->allocateLocal(VD)) {
if (!Init)
return true;

return this->visitLocalInitializer(Init, *Offset);
}
return false;
}

return true;
}

Expand Down Expand Up @@ -4074,7 +4096,7 @@ bool Compiler<Emitter>::visitCompoundStmt(const CompoundStmt *S) {
for (const auto *InnerStmt : S->body())
if (!visitStmt(InnerStmt))
return false;
return true;
return Scope.destroyLocals();
}

template <class Emitter>
Expand All @@ -4100,7 +4122,7 @@ bool Compiler<Emitter>::visitReturnStmt(const ReturnStmt *RS) {
return this->emitUnsupported(RS);

if (const Expr *RE = RS->getRetValue()) {
ExprScope<Emitter> RetScope(this);
LocalScope<Emitter> RetScope(this);
if (ReturnType) {
// Primitive types are simply returned.
if (!this->visit(RE))
Expand Down Expand Up @@ -4170,7 +4192,7 @@ template <class Emitter> bool Compiler<Emitter>::visitIfStmt(const IfStmt *IS) {
this->emitLabel(LabelEnd);
}

return true;
return IfScope.destroyLocals();
}

template <class Emitter>
Expand Down Expand Up @@ -4636,6 +4658,9 @@ bool Compiler<Emitter>::visitFunc(const FunctionDecl *F) {
if (!this->emitPopPtr(InitExpr))
return false;
}

if (!Scope.destroyLocals())
return false;
}
}

Expand Down Expand Up @@ -5010,6 +5035,18 @@ bool Compiler<Emitter>::visitDeclRef(const ValueDecl *D, const Expr *E) {
}
}

// In case we need to re-visit a declaration.
auto revisit = [&](const VarDecl *VD) -> bool {
auto VarState = this->visitDecl(VD);

if (VarState.notCreated())
return true;
if (!VarState)
return false;
// Retry.
return this->visitDeclRef(D, E);
};

// Handle lambda captures.
if (auto It = this->LambdaCaptures.find(D);
It != this->LambdaCaptures.end()) {
Expand All @@ -5020,12 +5057,8 @@ bool Compiler<Emitter>::visitDeclRef(const ValueDecl *D, const Expr *E) {
return this->emitGetPtrThisField(Offset, E);
} else if (const auto *DRE = dyn_cast<DeclRefExpr>(E);
DRE && DRE->refersToEnclosingVariableOrCapture()) {
if (const auto *VD = dyn_cast<VarDecl>(D); VD && VD->isInitCapture()) {
if (!this->visitVarDecl(cast<VarDecl>(D)))
return false;
// Retry.
return this->visitDeclRef(D, E);
}
if (const auto *VD = dyn_cast<VarDecl>(D); VD && VD->isInitCapture())
return revisit(VD);
}

if (D != InitializingDecl) {
Expand All @@ -5044,28 +5077,14 @@ bool Compiler<Emitter>::visitDeclRef(const ValueDecl *D, const Expr *E) {
// Visit local const variables like normal.
if ((VD->hasGlobalStorage() || VD->isLocalVarDecl() ||
VD->isStaticDataMember()) &&
typeShouldBeVisited(VD->getType())) {
auto VarState = this->visitVarDecl(VD, true);
if (VarState.notCreated())
return true;
if (!VarState)
return false;
// Retry.
return this->visitDeclRef(VD, E);
}
typeShouldBeVisited(VD->getType()))
return revisit(VD);
}
} else {
if (const auto *VD = dyn_cast<VarDecl>(D);
VD && VD->getAnyInitializer() &&
VD->getType().isConstant(Ctx.getASTContext()) && !VD->isWeak()) {
auto VarState = this->visitVarDecl(VD, true);
if (VarState.notCreated())
return true;
if (!VarState)
return false;
// Retry.
return this->visitDeclRef(VD, E);
}
VD->getType().isConstant(Ctx.getASTContext()) && !VD->isWeak())
return revisit(VD);
}
}

Expand Down
25 changes: 7 additions & 18 deletions clang/lib/AST/Interp/Compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -212,9 +212,10 @@ class Compiler : public ConstStmtVisitor<Compiler<Emitter>, bool>,
protected:
bool visitStmt(const Stmt *S);
bool visitExpr(const Expr *E) override;
bool visitDecl(const VarDecl *VD, bool ConstantContext) override;
bool visitFunc(const FunctionDecl *F) override;

bool visitDeclAndReturn(const VarDecl *VD, bool ConstantContext) override;

protected:
/// Emits scope cleanup instructions.
void emitCleanup();
Expand Down Expand Up @@ -267,6 +268,7 @@ class Compiler : public ConstStmtVisitor<Compiler<Emitter>, bool>,
bool delegate(const Expr *E);
/// Creates and initializes a variable from the given decl.
VarCreationState visitVarDecl(const VarDecl *VD, bool Toplevel = false);
VarCreationState visitDecl(const VarDecl *VD);
/// Visit an APValue.
bool visitAPValue(const APValue &Val, PrimType ValType, const Expr *E);
bool visitAPValueInitializer(const APValue &Val, const Expr *E);
Expand Down Expand Up @@ -496,6 +498,8 @@ template <class Emitter> class VariableScope {
template <class Emitter> class LocalScope : public VariableScope<Emitter> {
public:
LocalScope(Compiler<Emitter> *Ctx) : VariableScope<Emitter>(Ctx, nullptr) {}
LocalScope(Compiler<Emitter> *Ctx, const ValueDecl *VD)
: VariableScope<Emitter>(Ctx, VD) {}

/// Emit a Destroy op for this scope.
~LocalScope() override {
Expand Down Expand Up @@ -585,20 +589,10 @@ template <class Emitter> class DestructorScope final {
LocalScope<Emitter> &OtherScope;
};

/// Like a regular LocalScope, except that the destructors of all local
/// variables are automatically emitted when the AutoScope is destroyed.
template <class Emitter> class AutoScope : public LocalScope<Emitter> {
public:
AutoScope(Compiler<Emitter> *Ctx) : LocalScope<Emitter>(Ctx), DS(*this) {}

private:
DestructorScope<Emitter> DS;
};

/// Scope for storage declared in a compound statement.
template <class Emitter> class BlockScope final : public AutoScope<Emitter> {
template <class Emitter> class BlockScope final : public LocalScope<Emitter> {
public:
BlockScope(Compiler<Emitter> *Ctx) : AutoScope<Emitter>(Ctx) {}
BlockScope(Compiler<Emitter> *Ctx) : LocalScope<Emitter>(Ctx) {}

void addExtended(const Scope::Local &Local) override {
// If we to this point, just add the variable as a normal local
Expand All @@ -608,11 +602,6 @@ template <class Emitter> class BlockScope final : public AutoScope<Emitter> {
}
};

template <class Emitter> class ExprScope final : public AutoScope<Emitter> {
public:
ExprScope(Compiler<Emitter> *Ctx) : AutoScope<Emitter>(Ctx) {}
};

template <class Emitter> class ArrayIndexScope final {
public:
ArrayIndexScope(Compiler<Emitter> *Ctx, uint64_t Index) : Ctx(Ctx) {
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/Interp/EvalEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ EvaluationResult EvalEmitter::interpretDecl(const VarDecl *VD,

EvalResult.setSource(VD);

if (!this->visitDecl(VD, S.inConstantContext()) && EvalResult.empty())
if (!this->visitDeclAndReturn(VD, S.inConstantContext()))
EvalResult.setInvalid();

S.EvaluatingDecl = nullptr;
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/Interp/EvalEmitter.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class EvalEmitter : public SourceMapper {

/// Methods implemented by the compiler.
virtual bool visitExpr(const Expr *E) = 0;
virtual bool visitDecl(const VarDecl *VD, bool ConstantContext) = 0;
virtual bool visitDeclAndReturn(const VarDecl *VD, bool ConstantContext) = 0;
virtual bool visitFunc(const FunctionDecl *F) = 0;

/// Emits jumps.
Expand Down
11 changes: 6 additions & 5 deletions clang/lib/AST/Interp/Pointer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,9 @@ Pointer::~Pointer() {
if (isIntegralPointer())
return;

if (PointeeStorage.BS.Pointee) {
PointeeStorage.BS.Pointee->removePointer(this);
PointeeStorage.BS.Pointee->cleanup();
if (Block *Pointee = PointeeStorage.BS.Pointee) {
Pointee->removePointer(this);
Pointee->cleanup();
}
}

Expand Down Expand Up @@ -188,6 +188,7 @@ APValue Pointer::toAPValue() const {
void Pointer::print(llvm::raw_ostream &OS) const {
OS << PointeeStorage.BS.Pointee << " (";
if (isBlockPointer()) {
const Block *B = PointeeStorage.BS.Pointee;
OS << "Block) {";

if (isRoot())
Expand All @@ -200,8 +201,8 @@ void Pointer::print(llvm::raw_ostream &OS) const {
else
OS << Offset << ", ";

if (PointeeStorage.BS.Pointee)
OS << PointeeStorage.BS.Pointee->getSize();
if (B)
OS << B->getSize();
else
OS << "nullptr";
} else {
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/AST/TypePrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1934,6 +1934,9 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
break;

case attr::CountedBy:
case attr::CountedByOrNull:
case attr::SizedBy:
case attr::SizedByOrNull:
case attr::LifetimeBound:
case attr::TypeNonNull:
case attr::TypeNullable:
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Basic/LangOptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ void LangOptions::setLangDefaults(LangOptions &Opts, Language Lang,
Opts.HexFloats = Std.hasHexFloats();
Opts.WChar = Std.isCPlusPlus();
Opts.Digraphs = Std.hasDigraphs();
Opts.RawStringLiterals = Std.hasRawStringLiterals();

Opts.HLSL = Lang == Language::HLSL;
if (Opts.HLSL && Opts.IncludeDefaultHeader)
Expand Down
12 changes: 9 additions & 3 deletions clang/lib/Basic/Targets/AMDGPU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,9 +187,15 @@ bool AMDGPUTargetInfo::initFeatureMap(
return false;

// TODO: Should move this logic into TargetParser
std::string ErrorMsg;
if (!insertWaveSizeFeature(CPU, getTriple(), Features, ErrorMsg)) {
Diags.Report(diag::err_invalid_feature_combination) << ErrorMsg;
auto HasError = insertWaveSizeFeature(CPU, getTriple(), Features);
switch (HasError.first) {
default:
break;
case llvm::AMDGPU::INVALID_FEATURE_COMBINATION:
Diags.Report(diag::err_invalid_feature_combination) << HasError.second;
return false;
case llvm::AMDGPU::UNSUPPORTED_TARGET_FEATURE:
Diags.Report(diag::err_opt_not_valid_on_target) << HasError.second;
return false;
}

Expand Down
12 changes: 12 additions & 0 deletions clang/lib/Basic/Targets/Hexagon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,18 @@ static constexpr CPUSuffix Suffixes[] = {
{{"hexagonv73"}, {"73"}},
};

std::optional<unsigned> HexagonTargetInfo::getHexagonCPURev(StringRef Name) {
StringRef Arch = Name;
Arch.consume_front("hexagonv");
Arch.consume_back("t");

unsigned Val;
if (!Arch.getAsInteger(0, Val))
return Val;

return std::nullopt;
}

const char *HexagonTargetInfo::getHexagonCPUSuffix(StringRef Name) {
const CPUSuffix *Item = llvm::find_if(
Suffixes, [Name](const CPUSuffix &S) { return S.Name == Name; });
Expand Down
10 changes: 10 additions & 0 deletions clang/lib/Basic/Targets/Hexagon.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "clang/Basic/TargetOptions.h"
#include "llvm/Support/Compiler.h"
#include "llvm/TargetParser/Triple.h"
#include <optional>

namespace clang {
namespace targets {
Expand Down Expand Up @@ -115,6 +116,7 @@ class LLVM_LIBRARY_VISIBILITY HexagonTargetInfo : public TargetInfo {
std::string_view getClobbers() const override { return ""; }

static const char *getHexagonCPUSuffix(StringRef Name);
static std::optional<unsigned> getHexagonCPURev(StringRef Name);

bool isValidCPUName(StringRef Name) const override {
return getHexagonCPUSuffix(Name);
Expand All @@ -139,6 +141,14 @@ class LLVM_LIBRARY_VISIBILITY HexagonTargetInfo : public TargetInfo {
}

bool hasBitIntType() const override { return true; }

std::pair<unsigned, unsigned> hardwareInterferenceSizes() const override {
std::optional<unsigned> Rev = getHexagonCPURev(CPU);

// V73 and later have 64-byte cache lines.
unsigned CacheLineSizeBytes = Rev >= 73U ? 64 : 32;
return std::make_pair(CacheLineSizeBytes, CacheLineSizeBytes);
}
};
} // namespace targets
} // namespace clang
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/Basic/Targets/NVPTX.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ class LLVM_LIBRARY_VISIBILITY NVPTXTargetInfo : public TargetInfo {

ArrayRef<Builtin::Info> getTargetBuiltins() const override;

bool useFP16ConversionIntrinsics() const override { return false; }

bool
initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
StringRef CPU,
Expand Down
31 changes: 21 additions & 10 deletions clang/lib/CodeGen/CGBlocks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,11 +121,15 @@ static std::string getBlockDescriptorName(const CGBlockInfo &BlockInfo,
Name += "_";
}

std::string TypeAtEncoding =
CGM.getContext().getObjCEncodingForBlock(BlockInfo.getBlockExpr());
/// Replace occurrences of '@' with '\1'. '@' is reserved on ELF platforms as
/// a separator between symbol name and symbol version.
std::replace(TypeAtEncoding.begin(), TypeAtEncoding.end(), '@', '\1');
std::string TypeAtEncoding;

if (!CGM.getCodeGenOpts().DisableBlockSignatureString) {
TypeAtEncoding =
CGM.getContext().getObjCEncodingForBlock(BlockInfo.getBlockExpr());
/// Replace occurrences of '@' with '\1'. '@' is reserved on ELF platforms
/// as a separator between symbol name and symbol version.
std::replace(TypeAtEncoding.begin(), TypeAtEncoding.end(), '@', '\1');
}
Name += "e" + llvm::to_string(TypeAtEncoding.size()) + "_" + TypeAtEncoding;
Name += "l" + CGM.getObjCRuntime().getRCBlockLayoutStr(CGM, BlockInfo);
return Name;
Expand Down Expand Up @@ -201,9 +205,13 @@ static llvm::Constant *buildBlockDescriptor(CodeGenModule &CGM,
}

// Signature. Mandatory ObjC-style method descriptor @encode sequence.
std::string typeAtEncoding =
CGM.getContext().getObjCEncodingForBlock(blockInfo.getBlockExpr());
elements.add(CGM.GetAddrOfConstantCString(typeAtEncoding).getPointer());
if (CGM.getCodeGenOpts().DisableBlockSignatureString) {
elements.addNullPointer(i8p);
} else {
std::string typeAtEncoding =
CGM.getContext().getObjCEncodingForBlock(blockInfo.getBlockExpr());
elements.add(CGM.GetAddrOfConstantCString(typeAtEncoding).getPointer());
}

// GC layout.
if (C.getLangOpts().ObjC) {
Expand Down Expand Up @@ -814,7 +822,8 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
descriptor = buildBlockDescriptor(CGM, blockInfo);

// Compute the initial on-stack block flags.
flags = BLOCK_HAS_SIGNATURE;
if (!CGM.getCodeGenOpts().DisableBlockSignatureString)
flags = BLOCK_HAS_SIGNATURE;
if (blockInfo.HasCapturedVariableLayout)
flags |= BLOCK_HAS_EXTENDED_LAYOUT;
if (blockInfo.NeedsCopyDispose)
Expand Down Expand Up @@ -1300,7 +1309,9 @@ static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM,
fields.add(CGM.getNSConcreteGlobalBlock());

// __flags
BlockFlags flags = BLOCK_IS_GLOBAL | BLOCK_HAS_SIGNATURE;
BlockFlags flags = BLOCK_IS_GLOBAL;
if (!CGM.getCodeGenOpts().DisableBlockSignatureString)
flags |= BLOCK_HAS_SIGNATURE;
if (blockInfo.UsesStret)
flags |= BLOCK_USE_STRET;

Expand Down
61 changes: 21 additions & 40 deletions clang/lib/CodeGen/CGVTables.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1079,38 +1079,28 @@ CodeGenModule::getVTableLinkage(const CXXRecordDecl *RD) {
if (!RD->isExternallyVisible())
return llvm::GlobalVariable::InternalLinkage;

bool IsInNamedModule = RD->isInNamedModule();
// If the CXXRecordDecl are not in a module unit, we need to get
// its key function. We're at the end of the translation unit, so the current
// key function is fully correct.
const CXXMethodDecl *keyFunction =
IsInNamedModule ? nullptr : Context.getCurrentKeyFunction(RD);
if (IsInNamedModule || (keyFunction && !RD->hasAttr<DLLImportAttr>())) {
// We're at the end of the translation unit, so the current key
// function is fully correct.
const CXXMethodDecl *keyFunction = Context.getCurrentKeyFunction(RD);
if (keyFunction && !RD->hasAttr<DLLImportAttr>()) {
// If this class has a key function, use that to determine the
// linkage of the vtable.
const FunctionDecl *def = nullptr;
if (keyFunction && keyFunction->hasBody(def))
if (keyFunction->hasBody(def))
keyFunction = cast<CXXMethodDecl>(def);

bool IsExternalDefinition =
IsInNamedModule ? RD->shouldEmitInExternalSource() : !def;

TemplateSpecializationKind Kind =
IsInNamedModule ? RD->getTemplateSpecializationKind()
: keyFunction->getTemplateSpecializationKind();

switch (Kind) {
case TSK_Undeclared:
case TSK_ExplicitSpecialization:
switch (keyFunction->getTemplateSpecializationKind()) {
case TSK_Undeclared:
case TSK_ExplicitSpecialization:
assert(
(IsInNamedModule || def || CodeGenOpts.OptimizationLevel > 0 ||
(def || CodeGenOpts.OptimizationLevel > 0 ||
CodeGenOpts.getDebugInfo() != llvm::codegenoptions::NoDebugInfo) &&
"Shouldn't query vtable linkage without the class in module units, "
"key function, optimizations, or debug info");
if (IsExternalDefinition && CodeGenOpts.OptimizationLevel > 0)
"Shouldn't query vtable linkage without key function, "
"optimizations, or debug info");
if (!def && CodeGenOpts.OptimizationLevel > 0)
return llvm::GlobalVariable::AvailableExternallyLinkage;

if (keyFunction && keyFunction->isInlined())
if (keyFunction->isInlined())
return !Context.getLangOpts().AppleKext
? llvm::GlobalVariable::LinkOnceODRLinkage
: llvm::Function::InternalLinkage;
Expand All @@ -1129,7 +1119,7 @@ CodeGenModule::getVTableLinkage(const CXXRecordDecl *RD) {

case TSK_ExplicitInstantiationDeclaration:
llvm_unreachable("Should not have been asked to emit this");
}
}
}

// -fapple-kext mode does not support weak linkage, so we must use
Expand Down Expand Up @@ -1223,21 +1213,6 @@ bool CodeGenVTables::isVTableExternal(const CXXRecordDecl *RD) {
TSK == TSK_ExplicitInstantiationDefinition)
return false;

// Itanium C++ ABI [5.2.3]:
// Virtual tables for dynamic classes are emitted as follows:
//
// - If the class is templated, the tables are emitted in every object that
// references any of them.
// - Otherwise, if the class is attached to a module, the tables are uniquely
// emitted in the object for the module unit in which it is defined.
// - Otherwise, if the class has a key function (see below), the tables are
// emitted in the object for the translation unit containing the definition of
// the key function. This is unique if the key function is not inline.
// - Otherwise, the tables are emitted in every object that references any of
// them.
if (RD->isInNamedModule())
return RD->shouldEmitInExternalSource();

// Otherwise, if the class doesn't have a key function (possibly
// anymore), the vtable must be defined here.
const CXXMethodDecl *keyFunction = CGM.getContext().getCurrentKeyFunction(RD);
Expand All @@ -1247,7 +1222,13 @@ bool CodeGenVTables::isVTableExternal(const CXXRecordDecl *RD) {
const FunctionDecl *Def;
// Otherwise, if we don't have a definition of the key function, the
// vtable must be defined somewhere else.
return !keyFunction->hasBody(Def);
if (!keyFunction->hasBody(Def))
return true;

assert(Def && "The body of the key function is not assigned to Def?");
// If the non-inline key function comes from another module unit, the vtable
// must be defined there.
return Def->isInAnotherModuleUnit() && !Def->isInlineSpecified();
}

/// Given that we're currently at the end of the translation unit, and
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/CodeGen/CodeGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7165,6 +7165,9 @@ void CodeGenModule::AddDeferredUnusedCoverageMapping(Decl *D) {
SourceManager &SM = getContext().getSourceManager();
if (LimitedCoverage && SM.getMainFileID() != SM.getFileID(D->getBeginLoc()))
break;
if (!llvm::coverage::SystemHeadersCoverage &&
SM.isInSystemHeader(D->getBeginLoc()))
break;
DeferredEmptyCoverageMappingDecls.try_emplace(D, true);
break;
}
Expand Down
10 changes: 6 additions & 4 deletions clang/lib/CodeGen/CodeGenPGO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@ static llvm::cl::opt<bool>
llvm::cl::desc("Enable value profiling"),
llvm::cl::Hidden, llvm::cl::init(false));

extern llvm::cl::opt<bool> SystemHeadersCoverage;

using namespace clang;
using namespace CodeGen;

Expand Down Expand Up @@ -1046,13 +1044,17 @@ void CodeGenPGO::assignRegionCounters(GlobalDecl GD, llvm::Function *Fn) {
if (Fn->hasFnAttribute(llvm::Attribute::SkipProfile))
return;

SourceManager &SM = CGM.getContext().getSourceManager();
if (!llvm::coverage::SystemHeadersCoverage &&
SM.isInSystemHeader(D->getLocation()))
return;

setFuncName(Fn);

mapRegionCounters(D);
if (CGM.getCodeGenOpts().CoverageMapping)
emitCounterRegionMapping(D);
if (PGOReader) {
SourceManager &SM = CGM.getContext().getSourceManager();
loadRegionCounts(PGOReader, SM.isInMainFile(D->getLocation()));
computeRegionCounts(D);
applyFunctionAttributes(PGOReader, Fn);
Expand Down Expand Up @@ -1118,7 +1120,7 @@ bool CodeGenPGO::skipRegionMappingForDecl(const Decl *D) {
// Don't map the functions in system headers.
const auto &SM = CGM.getContext().getSourceManager();
auto Loc = D->getBody()->getBeginLoc();
return !SystemHeadersCoverage && SM.isInSystemHeader(Loc);
return !llvm::coverage::SystemHeadersCoverage && SM.isInSystemHeader(Loc);
}

void CodeGenPGO::emitCounterRegionMapping(const Decl *D) {
Expand Down
8 changes: 5 additions & 3 deletions clang/lib/CodeGen/CoverageMappingGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,12 @@ static llvm::cl::opt<bool> EmptyLineCommentCoverage(
"disable it on test)"),
llvm::cl::init(true), llvm::cl::Hidden);

llvm::cl::opt<bool> SystemHeadersCoverage(
namespace llvm::coverage {
cl::opt<bool> SystemHeadersCoverage(
"system-headers-coverage",
llvm::cl::desc("Enable collecting coverage from system headers"),
llvm::cl::init(false), llvm::cl::Hidden);
cl::desc("Enable collecting coverage from system headers"), cl::init(false),
cl::Hidden);
}

using namespace clang;
using namespace CodeGen;
Expand Down
5 changes: 5 additions & 0 deletions clang/lib/CodeGen/CoverageMappingGen.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,13 @@
#include "clang/Lex/Preprocessor.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/raw_ostream.h"

namespace llvm::coverage {
extern cl::opt<bool> SystemHeadersCoverage;
}

namespace clang {

class LangOptions;
Expand Down
3 changes: 0 additions & 3 deletions clang/lib/CodeGen/ItaniumCXXABI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2161,9 +2161,6 @@ bool ItaniumCXXABI::canSpeculativelyEmitVTable(const CXXRecordDecl *RD) const {
if (!canSpeculativelyEmitVTableAsBaseClass(RD))
return false;

if (RD->shouldEmitInExternalSource())
return false;

// For a complete-object vtable (or more specifically, for the VTT), we need
// to be able to speculatively emit the vtables of all dynamic virtual bases.
for (const auto &B : RD->vbases()) {
Expand Down
Loading