8 changes: 4 additions & 4 deletions clang-tools-extra/docs/clang-tidy/checks/list.rst
Original file line number Diff line number Diff line change
Expand Up @@ -341,9 +341,9 @@ Clang-Tidy Checks
:doc:`portability-std-allocator-const <portability/std-allocator-const>`,
:doc:`readability-avoid-const-params-in-decls <readability/avoid-const-params-in-decls>`, "Yes"
:doc:`readability-avoid-nested-conditional-operator <readability/avoid-nested-conditional-operator>`,
:doc:`readability-avoid-return-with-void-value <readability/avoid-return-with-void-value>`,
:doc:`readability-avoid-return-with-void-value <readability/avoid-return-with-void-value>`, "Yes"
:doc:`readability-avoid-unconditional-preprocessor-if <readability/avoid-unconditional-preprocessor-if>`,
:doc:`readability-braces-around-statements <readability/braces-around-statements>`, "Yes"
:doc:`readability-braces-around-statements <readability/braces-around-statements>`,
:doc:`readability-const-return-type <readability/const-return-type>`, "Yes"
:doc:`readability-container-contains <readability/container-contains>`, "Yes"
:doc:`readability-container-data-pointer <readability/container-data-pointer>`, "Yes"
Expand Down Expand Up @@ -529,12 +529,12 @@ Clang-Tidy Checks
:doc:`cppcoreguidelines-non-private-member-variables-in-classes <cppcoreguidelines/non-private-member-variables-in-classes>`, :doc:`misc-non-private-member-variables-in-classes <misc/non-private-member-variables-in-classes>`,
:doc:`cppcoreguidelines-use-default-member-init <cppcoreguidelines/use-default-member-init>`, :doc:`modernize-use-default-member-init <modernize/use-default-member-init>`, "Yes"
:doc:`fuchsia-header-anon-namespaces <fuchsia/header-anon-namespaces>`, :doc:`google-build-namespaces <google/build-namespaces>`,
:doc:`google-readability-braces-around-statements <google/readability-braces-around-statements>`, :doc:`readability-braces-around-statements <readability/braces-around-statements>`, "Yes"
:doc:`google-readability-braces-around-statements <google/readability-braces-around-statements>`, :doc:`readability-braces-around-statements <readability/braces-around-statements>`,
:doc:`google-readability-function-size <google/readability-function-size>`, :doc:`readability-function-size <readability/function-size>`,
:doc:`google-readability-namespace-comments <google/readability-namespace-comments>`, :doc:`llvm-namespace-comment <llvm/namespace-comment>`,
:doc:`hicpp-avoid-c-arrays <hicpp/avoid-c-arrays>`, :doc:`modernize-avoid-c-arrays <modernize/avoid-c-arrays>`,
:doc:`hicpp-avoid-goto <hicpp/avoid-goto>`, :doc:`cppcoreguidelines-avoid-goto <cppcoreguidelines/avoid-goto>`,
:doc:`hicpp-braces-around-statements <hicpp/braces-around-statements>`, :doc:`readability-braces-around-statements <readability/braces-around-statements>`, "Yes"
:doc:`hicpp-braces-around-statements <hicpp/braces-around-statements>`, :doc:`readability-braces-around-statements <readability/braces-around-statements>`,
:doc:`hicpp-deprecated-headers <hicpp/deprecated-headers>`, :doc:`modernize-deprecated-headers <modernize/deprecated-headers>`, "Yes"
:doc:`hicpp-explicit-conversions <hicpp/explicit-conversions>`, :doc:`google-explicit-constructor <google/explicit-constructor>`, "Yes"
:doc:`hicpp-function-size <hicpp/function-size>`, :doc:`readability-function-size <readability/function-size>`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,22 @@ void Positives() {
// CHECK-MESSAGES-NO-CONFIG: :[[@LINE-1]]:8: warning: inside a lambda, '__FUNCTION__' expands to the name of the function call operator; consider capturing the name of the enclosing function explicitly [bugprone-lambda-function-name]
[] { EMBED_IN_ANOTHER_MACRO1; }();
// CHECK-MESSAGES-NO-CONFIG: :[[@LINE-1]]:8: warning: inside a lambda, '__func__' expands to the name of the function call operator; consider capturing the name of the enclosing function explicitly [bugprone-lambda-function-name]
[] {
__func__;
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: inside a lambda, '__func__' expands to the name of the function call operator; consider capturing the name of the enclosing function explicitly [bugprone-lambda-function-name]
struct S {
void f() {
__func__;
[] {
__func__;
// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: inside a lambda, '__func__' expands to the name of the function call operator; consider capturing the name of the enclosing function explicitly [bugprone-lambda-function-name]
}();
__func__;
}
};
__func__;
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: inside a lambda, '__func__' expands to the name of the function call operator; consider capturing the name of the enclosing function explicitly [bugprone-lambda-function-name]
}();
}

#define FUNC_MACRO_WITH_FILE_AND_LINE Foo(__func__, __FILE__, __LINE__)
Expand All @@ -40,4 +56,7 @@ void Negatives() {
[] { FUNC_MACRO_WITH_FILE_AND_LINE; }();
[] { FUNCTION_MACRO_WITH_FILE_AND_LINE; }();
[] { EMBED_IN_ANOTHER_MACRO2; }();

[] (const char* func = __func__) { func; }();
[func=__func__] { func; }();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
InheritParentConfig: true
Checks: 'misc-throw-by-value-catch-by-reference'
CheckOptions:
misc-throw-by-value-catch-by-reference.MaxSize: '1152921504606846976'
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,11 @@

// Validate that check options are printed in alphabetical order:
// RUN: clang-tidy --checks="-*,readability-identifier-naming" --dump-config %S/Inputs/config-files/- -- | grep "readability-identifier-naming\." | sort --check

// Dumped config does not overflow for unsigned options
// RUN: clang-tidy --dump-config \
// RUN: --checks="-*,misc-throw-by-value-catch-by-reference" \
// RUN: -- | grep -v -q "misc-throw-by-value-catch-by-reference.MaxSize: '-1'"

// RUN: clang-tidy --dump-config %S/Inputs/config-files/5/- \
// RUN: -- | grep -q "misc-throw-by-value-catch-by-reference.MaxSize: '1152921504606846976'"
12 changes: 12 additions & 0 deletions clang-tools-extra/test/clang-tidy/infrastructure/verify-config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,15 @@
// CHECK-VERIFY: command-line option '-checks': warning: check glob 'bad*glob' doesn't match any known check [-verify-config]
// CHECK-VERIFY: command-line option '-checks': warning: unknown check 'llvm-includeorder'; did you mean 'llvm-include-order' [-verify-config]
// CHECK-VERIFY: command-line option '-checks': warning: unknown check 'my-made-up-check' [-verify-config]

// RUN: echo -e 'Checks: |\n bugprone-argument-comment\n bugprone-assert-side-effect,\n bugprone-bool-pointer-implicit-conversion\n readability-use-anyof*' > %T/MyClangTidyConfig
// RUN: clang-tidy -verify-config \
// RUN: --config-file=%T/MyClangTidyConfig | FileCheck %s -check-prefix=CHECK-VERIFY-BLOCK-OK
// CHECK-VERIFY-BLOCK-OK: No config errors detected.

// RUN: echo -e 'Checks: |\n bugprone-arguments-*\n bugprone-assert-side-effects\n bugprone-bool-pointer-implicit-conversion' > %T/MyClangTidyConfigBad
// RUN: not clang-tidy -verify-config \
// RUN: --config-file=%T/MyClangTidyConfigBad 2>&1 | FileCheck %s -check-prefix=CHECK-VERIFY-BLOCK-BAD
// CHECK-VERIFY-BLOCK-BAD: command-line option '-config': warning: check glob 'bugprone-arguments-*' doesn't match any known check [-verify-config]
// CHECK-VERIFY-BLOCK-BAD: command-line option '-config': warning: unknown check 'bugprone-assert-side-effects'; did you mean 'bugprone-assert-side-effect' [-verify-config]

1 change: 1 addition & 0 deletions clang/cmake/caches/Apple-stage2.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ set(LLVM_ENABLE_BACKTRACES OFF CACHE BOOL "")
set(LLVM_ENABLE_MODULES ON CACHE BOOL "")
set(LLVM_EXTERNALIZE_DEBUGINFO ON CACHE BOOL "")
set(LLVM_ENABLE_EXPORTED_SYMBOLS_IN_EXECUTABLES OFF CACHE BOOL "")
set(LLVM_PLUGIN_SUPPORT OFF CACHE BOOL "")
set(CLANG_PLUGIN_SUPPORT OFF CACHE BOOL "")
set(CLANG_SPAWN_CC1 ON CACHE BOOL "")
set(BUG_REPORT_URL "http://developer.apple.com/bugreporter/" CACHE STRING "")
Expand Down
5 changes: 4 additions & 1 deletion clang/docs/ClangOffloadBundler.rst
Original file line number Diff line number Diff line change
Expand Up @@ -518,11 +518,14 @@ The compressed offload bundle begins with a header followed by the compressed bi
This is a unique identifier to distinguish compressed offload bundles. The value is the string 'CCOB' (Compressed Clang Offload Bundle).

- **Version Number (16-bit unsigned int)**:
This denotes the version of the compressed offload bundle format. The current version is `1`.
This denotes the version of the compressed offload bundle format. The current version is `2`.

- **Compression Method (16-bit unsigned int)**:
This field indicates the compression method used. The value corresponds to either `zlib` or `zstd`, represented as a 16-bit unsigned integer cast from the LLVM compression enumeration.

- **Total File Size (32-bit unsigned int)**:
This is the total size (in bytes) of the file, including the header. Available in version 2 and above.

- **Uncompressed Binary Size (32-bit unsigned int)**:
This is the size (in bytes) of the binary data before it was compressed.

Expand Down
3 changes: 2 additions & 1 deletion clang/docs/LanguageExtensions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1642,7 +1642,8 @@ The following type trait primitives are supported by Clang. Those traits marked
were made trivially relocatable via the ``clang::trivial_abi`` attribute.
* ``__is_trivially_equality_comparable`` (Clang): Returns true if comparing two
objects of the provided type is known to be equivalent to comparing their
value representations.
object representations. Note that types containing padding bytes are never
trivially equality comparable.
* ``__is_unbounded_array`` (C++, GNU, Microsoft, Embarcadero)
* ``__is_union`` (C++, GNU, Microsoft, Embarcadero)
* ``__is_unsigned`` (C++, Embarcadero):
Expand Down
24 changes: 24 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ sections with improvements to Clang's support for those languages.

C++ Language Changes
--------------------
- Implemented ``_BitInt`` literal suffixes ``__wb`` or ``__WB`` as a Clang extension with ``unsigned`` modifiers also allowed. (#GH85223).

C++20 Feature Support
^^^^^^^^^^^^^^^^^^^^^
Expand Down Expand Up @@ -179,6 +180,9 @@ C23 Feature Support
- Clang now supports `N3018 The constexpr specifier for object definitions`
<https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3018.htm>`_.

- Properly promote bit-fields of bit-precise integer types to the field's type
rather than to ``int``. #GH87641

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

Expand Down Expand Up @@ -248,6 +252,8 @@ Modified Compiler Flags
f3 *c = (f3 *)x;
}
- Carved out ``-Wformat`` warning about scoped enums into a subwarning and
make it controlled by ``-Wformat-pedantic``. Fixes #GH88595.

Removed Compiler Flags
-------------------------
Expand Down Expand Up @@ -538,6 +544,8 @@ Bug Fixes to C++ Support
- Fix an issue caused by not handling invalid cases when substituting into the parameter mapping of a constraint. Fixes (#GH86757).
- Fixed a bug that prevented member function templates of class templates declared with a deduced return type
from being explicitly specialized for a given implicit instantiation of the class template.
- Fixed a crash when ``this`` is used in a dependent class scope function template specialization
that instantiates to a static member function.

- Fix crash when inheriting from a cv-qualified type. Fixes #GH35603
- Fix a crash when the using enum declaration uses an anonymous enumeration. Fixes (#GH86790).
Expand All @@ -549,6 +557,11 @@ Bug Fixes to C++ Support
- Fix a crash in requires expression with templated base class member function. Fixes (#GH84020).
- Fix a crash caused by defined struct in a type alias template when the structure
has fields with dependent type. Fixes (#GH75221).
- Fix placement new initializes typedef array with correct size. Fixes (#GH41441).
- Fix the Itanium mangling of lambdas defined in a member of a local class (#GH88906)
- Fixed a crash when trying to evaluate a user-defined ``static_assert`` message whose ``size()``
function returns a large or negative value. Fixes (#GH89407).
- Fixed a use-after-free bug in parsing of type constraints with default arguments that involve lambdas. (#GH67235)

Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -558,6 +571,9 @@ Bug Fixes to AST Handling
Miscellaneous Bug Fixes
^^^^^^^^^^^^^^^^^^^^^^^

- Fixed an infinite recursion in ASTImporter, on return type declared inside
body of C++11 lambda without trailing return (#GH68775).

Miscellaneous Clang Crashes Fixed
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Expand Down Expand Up @@ -645,6 +661,12 @@ CUDA Support
AIX Support
^^^^^^^^^^^

- Introduced the ``-maix-small-local-dynamic-tls`` option to produce a faster
access sequence for local-dynamic TLS variables where the offset from the TLS
base is encoded as an immediate operand.
This access sequence is not used for TLS variables larger than 32KB, and is
currently only supported on 64-bit mode.

WebAssembly Support
^^^^^^^^^^^^^^^^^^^

Expand Down Expand Up @@ -695,6 +717,8 @@ Static Analyzer
- 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)
- Fixed a crash when storing through an address that refers to the address of
a label. (GH#89185)

New features
^^^^^^^^^^^^
Expand Down
3 changes: 3 additions & 0 deletions clang/docs/UsersManual.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4921,6 +4921,9 @@ directory. Using the example installation above, this would mean passing
If the user links the program with the ``clang`` or ``clang-cl`` drivers, the
driver will pass this flag for them.

The auto-linking can be disabled with -fno-rtlib-defaultlib. If that flag is
used, pass the complete flag to required libraries as described for ASan below.

If the linker cannot find the appropriate library, it will emit an error like
this::

Expand Down
4 changes: 2 additions & 2 deletions clang/include/clang/AST/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// initialization of another module).
struct PerModuleInitializers {
llvm::SmallVector<Decl*, 4> Initializers;
llvm::SmallVector<uint32_t, 4> LazyInitializers;
llvm::SmallVector<Decl::DeclID, 4> LazyInitializers;

void resolve(ASTContext &Ctx);
};
Expand Down Expand Up @@ -1059,7 +1059,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// or an ImportDecl nominating another module that has initializers.
void addModuleInitializer(Module *M, Decl *Init);

void addLazyModuleInitializers(Module *M, ArrayRef<uint32_t> IDs);
void addLazyModuleInitializers(Module *M, ArrayRef<Decl::DeclID> IDs);

/// Get the initializations to perform when importing a module, if any.
ArrayRef<Decl*> getModuleInitializers(Module *M);
Expand Down
6 changes: 6 additions & 0 deletions clang/include/clang/AST/ASTNodeTraverser.h
Original file line number Diff line number Diff line change
Expand Up @@ -851,6 +851,12 @@ class ASTNodeTraverser
Visit(R);
}

void VisitTypeTraitExpr(const TypeTraitExpr *E) {
// Argument types are not children of the TypeTraitExpr.
for (auto *A : E->getArgs())
Visit(A->getType());
}

void VisitLambdaExpr(const LambdaExpr *Node) {
if (Traversal == TK_IgnoreUnlessSpelledInSource) {
for (unsigned I = 0, N = Node->capture_size(); I != N; ++I) {
Expand Down
9 changes: 5 additions & 4 deletions clang/include/clang/AST/DeclBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,9 @@ class alignas(8) Decl {
ModulePrivate
};

/// An ID number that refers to a declaration in an AST file.
using DeclID = uint32_t;

protected:
/// The next declaration within the same lexical
/// DeclContext. These pointers form the linked list that is
Expand Down Expand Up @@ -349,8 +352,6 @@ class alignas(8) Decl {
LLVM_PREFERRED_TYPE(Linkage)
mutable unsigned CacheValidAndLinkage : 3;

using DeclID = uint32_t;

/// Allocate memory for a deserialized declaration.
///
/// This routine must be used to allocate memory for any declaration that is
Expand Down Expand Up @@ -778,9 +779,9 @@ class alignas(8) Decl {

/// Retrieve the global declaration ID associated with this
/// declaration, which specifies where this Decl was loaded from.
unsigned getGlobalID() const {
DeclID getGlobalID() const {
if (isFromASTFile())
return *((const unsigned*)this - 1);
return *((const DeclID *)this - 1);
return 0;
}

Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/AST/DeclTemplate.h
Original file line number Diff line number Diff line change
Expand Up @@ -797,7 +797,7 @@ class RedeclarableTemplateDecl : public TemplateDecl,
///
/// The first value in the array is the number of specializations/partial
/// specializations that follow.
uint32_t *LazySpecializations = nullptr;
Decl::DeclID *LazySpecializations = nullptr;

/// The set of "injected" template arguments used within this
/// template.
Expand Down
9 changes: 3 additions & 6 deletions clang/include/clang/AST/ExprCXX.h
Original file line number Diff line number Diff line change
Expand Up @@ -3198,7 +3198,6 @@ class UnresolvedLookupExpr final
NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateKWLoc,
const DeclarationNameInfo &NameInfo, bool RequiresADL,
bool Overloaded,
const TemplateArgumentListInfo *TemplateArgs,
UnresolvedSetIterator Begin, UnresolvedSetIterator End,
bool KnownDependent);
Expand All @@ -3218,8 +3217,9 @@ class UnresolvedLookupExpr final
static UnresolvedLookupExpr *
Create(const ASTContext &Context, CXXRecordDecl *NamingClass,
NestedNameSpecifierLoc QualifierLoc,
const DeclarationNameInfo &NameInfo, bool RequiresADL, bool Overloaded,
UnresolvedSetIterator Begin, UnresolvedSetIterator End);
const DeclarationNameInfo &NameInfo, bool RequiresADL,
UnresolvedSetIterator Begin, UnresolvedSetIterator End,
bool KnownDependent);

// After canonicalization, there may be dependent template arguments in
// CanonicalConverted But none of Args is dependent. When any of
Expand All @@ -3240,9 +3240,6 @@ class UnresolvedLookupExpr final
/// argument-dependent lookup.
bool requiresADL() const { return UnresolvedLookupExprBits.RequiresADL; }

/// True if this lookup is overloaded.
bool isOverloaded() const { return UnresolvedLookupExprBits.Overloaded; }

/// Gets the 'naming class' (in the sense of C++0x
/// [class.access.base]p5) of the lookup. This is the scope
/// that was looked in to find these results.
Expand Down
4 changes: 2 additions & 2 deletions clang/include/clang/AST/ExternalASTSource.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ class ExternalASTSource : public RefCountedBase<ExternalASTSource> {
/// passes back decl sets as VisibleDeclaration objects.
///
/// The default implementation of this method is a no-op.
virtual Decl *GetExternalDecl(uint32_t ID);
virtual Decl *GetExternalDecl(Decl::DeclID ID);

/// Resolve a selector ID into a selector.
///
Expand Down Expand Up @@ -579,7 +579,7 @@ using LazyDeclStmtPtr =

/// A lazy pointer to a declaration.
using LazyDeclPtr =
LazyOffsetPtr<Decl, uint32_t, &ExternalASTSource::GetExternalDecl>;
LazyOffsetPtr<Decl, Decl::DeclID, &ExternalASTSource::GetExternalDecl>;

/// A lazy pointer to a set of CXXCtorInitializers.
using LazyCXXCtorInitializersPtr =
Expand Down
87 changes: 71 additions & 16 deletions clang/include/clang/AST/OpenACCClause.h
Original file line number Diff line number Diff line change
Expand Up @@ -156,33 +156,88 @@ class OpenACCSelfClause : public OpenACCClauseWithCondition {
Expr *ConditionExpr, SourceLocation EndLoc);
};

/// Represents oen of a handful of classes that have a single integer
/// Represents a clause that has one or more IntExprs. It does not own the
/// IntExprs, but provides 'children' and other accessors.
class OpenACCClauseWithIntExprs : public OpenACCClauseWithParams {
MutableArrayRef<Expr *> IntExprs;

protected:
OpenACCClauseWithIntExprs(OpenACCClauseKind K, SourceLocation BeginLoc,
SourceLocation LParenLoc, SourceLocation EndLoc)
: OpenACCClauseWithParams(K, BeginLoc, LParenLoc, EndLoc) {}

/// Used only for initialization, the leaf class can initialize this to
/// trailing storage.
void setIntExprs(MutableArrayRef<Expr *> NewIntExprs) {
assert(IntExprs.empty() && "Cannot change IntExprs list");
IntExprs = NewIntExprs;
}

/// Gets the entire list of integer expressions, but leave it to the
/// individual clauses to expose this how they'd like.
llvm::ArrayRef<Expr *> getIntExprs() const { return IntExprs; }

public:
child_range children() {
return child_range(reinterpret_cast<Stmt **>(IntExprs.begin()),
reinterpret_cast<Stmt **>(IntExprs.end()));
}

const_child_range children() const {
child_range Children =
const_cast<OpenACCClauseWithIntExprs *>(this)->children();
return const_child_range(Children.begin(), Children.end());
}
};

class OpenACCNumGangsClause final
: public OpenACCClauseWithIntExprs,
public llvm::TrailingObjects<OpenACCNumGangsClause, Expr *> {

OpenACCNumGangsClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
ArrayRef<Expr *> IntExprs, SourceLocation EndLoc)
: OpenACCClauseWithIntExprs(OpenACCClauseKind::NumGangs, BeginLoc,
LParenLoc, EndLoc) {
std::uninitialized_copy(IntExprs.begin(), IntExprs.end(),
getTrailingObjects<Expr *>());
setIntExprs(MutableArrayRef(getTrailingObjects<Expr *>(), IntExprs.size()));
}

public:
static OpenACCNumGangsClause *
Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
ArrayRef<Expr *> IntExprs, SourceLocation EndLoc);

llvm::ArrayRef<Expr *> getIntExprs() {
return OpenACCClauseWithIntExprs::getIntExprs();
}

llvm::ArrayRef<Expr *> getIntExprs() const {
return OpenACCClauseWithIntExprs::getIntExprs();
}
};

/// Represents one of a handful of clauses that have a single integer
/// expression.
class OpenACCClauseWithSingleIntExpr : public OpenACCClauseWithParams {
class OpenACCClauseWithSingleIntExpr : public OpenACCClauseWithIntExprs {
Expr *IntExpr;

protected:
OpenACCClauseWithSingleIntExpr(OpenACCClauseKind K, SourceLocation BeginLoc,
SourceLocation LParenLoc, Expr *IntExpr,
SourceLocation EndLoc)
: OpenACCClauseWithParams(K, BeginLoc, LParenLoc, EndLoc),
IntExpr(IntExpr) {}
: OpenACCClauseWithIntExprs(K, BeginLoc, LParenLoc, EndLoc),
IntExpr(IntExpr) {
setIntExprs(MutableArrayRef<Expr *>{&this->IntExpr, 1});
}

public:
bool hasIntExpr() const { return IntExpr; }
const Expr *getIntExpr() const { return IntExpr; }

Expr *getIntExpr() { return IntExpr; };

child_range children() {
return child_range(reinterpret_cast<Stmt **>(&IntExpr),
reinterpret_cast<Stmt **>(&IntExpr + 1));
bool hasIntExpr() const { return !getIntExprs().empty(); }
const Expr *getIntExpr() const {
return hasIntExpr() ? getIntExprs()[0] : nullptr;
}

const_child_range children() const {
return const_child_range(reinterpret_cast<Stmt *const *>(&IntExpr),
reinterpret_cast<Stmt *const *>(&IntExpr + 1));
}
Expr *getIntExpr() { return hasIntExpr() ? getIntExprs()[0] : nullptr; };
};

class OpenACCNumWorkersClause : public OpenACCClauseWithSingleIntExpr {
Expand Down
5 changes: 0 additions & 5 deletions clang/include/clang/AST/Stmt.h
Original file line number Diff line number Diff line change
Expand Up @@ -1067,11 +1067,6 @@ class alignas(void *) Stmt {
/// argument-dependent lookup if this is the operand of a function call.
LLVM_PREFERRED_TYPE(bool)
unsigned RequiresADL : 1;

/// True if these lookup results are overloaded. This is pretty trivially
/// rederivable if we urgently need to kill this field.
LLVM_PREFERRED_TYPE(bool)
unsigned Overloaded : 1;
};
static_assert(sizeof(UnresolvedLookupExprBitfields) <= 4,
"UnresolvedLookupExprBitfields must be <= than 4 bytes to"
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Analysis/FlowSensitive/ASTOps.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@ struct ReferencedDecls {
/// Returns declarations that are declared in or referenced from `FD`.
ReferencedDecls getReferencedDecls(const FunctionDecl &FD);

/// Returns declarations that are declared in or referenced from `S`.
ReferencedDecls getReferencedDecls(const Stmt &S);

} // namespace dataflow
} // namespace clang

Expand Down
15 changes: 15 additions & 0 deletions clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,21 @@ class Environment {
Environment::ValueModel &Model,
ExprJoinBehavior ExprBehavior);

/// Returns a value that approximates both `Val1` and `Val2`, or null if no
/// such value can be produced.
///
/// `Env1` and `Env2` can be used to query child values and path condition
/// implications of `Val1` and `Val2` respectively. The joined value will be
/// produced in `JoinedEnv`.
///
/// Requirements:
///
/// `Val1` and `Val2` must model values of type `Type`.
static Value *joinValues(QualType Ty, Value *Val1, const Environment &Env1,
Value *Val2, const Environment &Env2,
Environment &JoinedEnv,
Environment::ValueModel &Model);

/// Widens the environment point-wise, using `PrevEnv` as needed to inform the
/// approximation.
///
Expand Down
3 changes: 2 additions & 1 deletion clang/include/clang/Analysis/FlowSensitive/Transfer.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ class StmtToEnvMap {
/// Requirements:
///
/// `S` must not be `ParenExpr` or `ExprWithCleanups`.
void transfer(const StmtToEnvMap &StmtToEnv, const Stmt &S, Environment &Env);
void transfer(const StmtToEnvMap &StmtToEnv, const Stmt &S, Environment &Env,
Environment::ValueModel &Model);

} // namespace dataflow
} // namespace clang
Expand Down
10 changes: 5 additions & 5 deletions clang/include/clang/Basic/Attr.td
Original file line number Diff line number Diff line change
Expand Up @@ -368,8 +368,8 @@ class Clang<string name, bit allowInC = 1, int version = 1>
bit AllowInC = allowInC;
}

// HLSL Semantic spellings
class HLSLSemantic<string name> : Spelling<name, "HLSLSemantic">;
// HLSL Annotation spellings
class HLSLAnnotation<string name> : Spelling<name, "HLSLAnnotation">;

class Accessor<string name, list<Spelling> spellings> {
string Name = name;
Expand Down Expand Up @@ -4358,22 +4358,22 @@ def HLSLNumThreads: InheritableAttr {
}

def HLSLSV_GroupIndex: HLSLAnnotationAttr {
let Spellings = [HLSLSemantic<"SV_GroupIndex">];
let Spellings = [HLSLAnnotation<"SV_GroupIndex">];
let Subjects = SubjectList<[ParmVar, GlobalVar]>;
let LangOpts = [HLSL];
let Documentation = [HLSLSV_GroupIndexDocs];
}

def HLSLResourceBinding: InheritableAttr {
let Spellings = [HLSLSemantic<"register">];
let Spellings = [HLSLAnnotation<"register">];
let Subjects = SubjectList<[HLSLBufferObj, ExternalGlobalVar]>;
let LangOpts = [HLSL];
let Args = [StringArgument<"Slot">, StringArgument<"Space", 1>];
let Documentation = [HLSLResourceBindingDocs];
}

def HLSLSV_DispatchThreadID: HLSLAnnotationAttr {
let Spellings = [HLSLSemantic<"SV_DispatchThreadID">];
let Spellings = [HLSLAnnotation<"SV_DispatchThreadID">];
let Subjects = SubjectList<[ParmVar, Field]>;
let LangOpts = [HLSL];
let Documentation = [HLSLSV_DispatchThreadIDDocs];
Expand Down
6 changes: 3 additions & 3 deletions clang/include/clang/Basic/AttributeCommonInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ class AttributeCommonInfo {
/// Context-sensitive version of a keyword attribute.
AS_ContextSensitiveKeyword,

/// <vardecl> : <semantic>
AS_HLSLSemantic,
/// <vardecl> : <annotation>
AS_HLSLAnnotation,

/// The attibute has no source code manifestation and is only created
/// implicitly.
Expand Down Expand Up @@ -120,7 +120,7 @@ class AttributeCommonInfo {
}
static Form Pragma() { return AS_Pragma; }
static Form ContextSensitiveKeyword() { return AS_ContextSensitiveKeyword; }
static Form HLSLSemantic() { return AS_HLSLSemantic; }
static Form HLSLAnnotation() { return AS_HLSLAnnotation; }
static Form Implicit() { return AS_Implicit; }

private:
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Basic/DiagnosticCommonKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,9 @@ def err_cxx23_size_t_suffix: Error<
def err_size_t_literal_too_large: Error<
"%select{signed |}0'size_t' literal is out of range of possible "
"%select{signed |}0'size_t' values">;
def ext_cxx_bitint_suffix : Extension<
"'_BitInt' suffix for literals is a Clang extension">,
InGroup<BitIntExtension>;
def ext_c23_bitint_suffix : ExtWarn<
"'_BitInt' suffix for literals is a C23 extension">,
InGroup<C23>;
Expand Down
6 changes: 6 additions & 0 deletions clang/include/clang/Basic/DiagnosticGroups.td
Original file line number Diff line number Diff line change
Expand Up @@ -1412,6 +1412,9 @@ def MultiGPU: DiagGroup<"multi-gpu">;
// libc and the CRT to be skipped.
def AVRRtlibLinkingQuirks : DiagGroup<"avr-rtlib-linking-quirks">;

// A warning group related to AArch64 SME function attribues.
def AArch64SMEAttributes : DiagGroup<"aarch64-sme-attributes">;

// A warning group for things that will change semantics in the future.
def FutureCompat : DiagGroup<"future-compat">;

Expand Down Expand Up @@ -1517,5 +1520,8 @@ def UnsafeBufferUsage : DiagGroup<"unsafe-buffer-usage", [UnsafeBufferUsageInCon
// Warnings and notes InstallAPI verification.
def InstallAPIViolation : DiagGroup<"installapi-violation">;

// Warnings related to _BitInt extension
def BitIntExtension : DiagGroup<"bit-int-extension">;

// Warnings about misuse of ExtractAPI options.
def ExtractAPIMisuse : DiagGroup<"extractapi-misuse">;
2 changes: 1 addition & 1 deletion clang/include/clang/Basic/DiagnosticParseKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -1654,7 +1654,7 @@ def warn_ext_int_deprecated : Warning<
"'_ExtInt' is deprecated; use '_BitInt' instead">, InGroup<DeprecatedType>;
def ext_bit_int : Extension<
"'_BitInt' in %select{C17 and earlier|C++}0 is a Clang extension">,
InGroup<DiagGroup<"bit-int-extension">>;
InGroup<BitIntExtension>;
} // end of Parse Issue category.

let CategoryName = "Modules Issue" in {
Expand Down
21 changes: 18 additions & 3 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,9 @@ def err_expr_not_cce : Error<
"call to 'size()'|call to 'data()'}0 is not a constant expression">;
def ext_cce_narrowing : ExtWarn<
"%select{case value|enumerator value|non-type template argument|"
"array size|explicit specifier argument|noexcept specifier argument}0 "
"%select{cannot be narrowed from type %2 to %3|"
"evaluates to %2, which cannot be narrowed to type %3}1">,
"array size|explicit specifier argument|noexcept specifier argument|"
"call to 'size()'|call to 'data()'}0 %select{cannot be narrowed from "
"type %2 to %3|evaluates to %2, which cannot be narrowed to type %3}1">,
InGroup<CXX11Narrowing>, DefaultError, SFINAEFailure;
def err_ice_not_integral : Error<
"%select{integer|integral}1 constant expression must have "
Expand Down Expand Up @@ -3754,6 +3754,16 @@ def err_sme_definition_using_za_in_non_sme_target : Error<
"function using ZA state requires 'sme'">;
def err_sme_definition_using_zt0_in_non_sme2_target : Error<
"function using ZT0 state requires 'sme2'">;
def warn_sme_streaming_pass_return_vl_to_non_streaming : Warning<
"passing a VL-dependent argument to/from a function that has a different"
" streaming-mode. The streaming and non-streaming vector lengths may be"
" different">,
InGroup<AArch64SMEAttributes>, DefaultIgnore;
def warn_sme_locally_streaming_has_vl_args_returns : Warning<
"passing/returning a VL-dependent argument to/from a __arm_locally_streaming"
" function. The streaming and non-streaming vector"
" lengths may be different">,
InGroup<AArch64SMEAttributes>, DefaultIgnore;
def err_conflicting_attributes_arm_state : Error<
"conflicting attributes for state '%0'">;
def err_sme_streaming_cannot_be_multiversioned : Error<
Expand Down Expand Up @@ -12283,4 +12293,9 @@ def note_acc_int_expr_conversion
: Note<"conversion to %select{integral|enumeration}0 type %1">;
def err_acc_int_expr_multiple_conversions
: Error<"multiple conversions from expression type %0 to an integral type">;
def err_acc_num_gangs_num_args
: Error<"%select{no|too many}0 integer expression arguments provided to "
"OpenACC 'num_gangs' "
"%select{|clause: '%1' directive expects maximum of %2, %3 were "
"provided}0">;
} // end of sema component.
16 changes: 16 additions & 0 deletions clang/include/clang/Basic/LangOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,11 @@ class LangOptionsBase {
/// - the parameter list of a template template parameter
Ver17,

/// Attempt to be ABI-compatible with code generated by Clang 18.0.x.
/// This causes clang to revert some fixes to the mangling of lambdas
/// in the initializers of members of local classes.
Ver18,

/// Conform to the underlying platform's C and C++ ABIs as closely
/// as we can.
Latest
Expand Down Expand Up @@ -873,6 +878,8 @@ class FPOptions {
/// Return difference with the given option set.
FPOptionsOverride getChangesFrom(const FPOptions &Base) const;

void applyChanges(FPOptionsOverride FPO);

// We can define most of the accessors automatically:
#define OPTION(NAME, TYPE, WIDTH, PREVIOUS) \
TYPE get##NAME() const { \
Expand Down Expand Up @@ -954,6 +961,11 @@ class FPOptionsOverride {
setAllowFPContractAcrossStatement();
}

void setDisallowOptimizations() {
setFPPreciseEnabled(true);
setDisallowFPContract();
}

storage_type getAsOpaqueInt() const {
return (static_cast<storage_type>(Options.getAsOpaqueInt())
<< FPOptions::StorageBitSize) |
Expand Down Expand Up @@ -1010,6 +1022,10 @@ inline FPOptionsOverride FPOptions::getChangesFrom(const FPOptions &Base) const
return getChangesSlow(Base);
}

inline void FPOptions::applyChanges(FPOptionsOverride FPO) {
*this = FPO.applyOverrides(*this);
}

/// Describes the kind of translation unit being processed.
enum TranslationUnitKind {
/// The translation unit is a complete translation unit.
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/OpenACCClauses.def
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
VISIT_CLAUSE(Default)
VISIT_CLAUSE(If)
VISIT_CLAUSE(Self)
VISIT_CLAUSE(NumGangs)
VISIT_CLAUSE(NumWorkers)
VISIT_CLAUSE(VectorLength)

Expand Down
17 changes: 11 additions & 6 deletions clang/include/clang/Driver/OffloadBundler.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ struct OffloadTargetInfo {
// - Version (2 bytes)
// - Compression Method (2 bytes) - Uses the values from
// llvm::compression::Format.
// - Total file size (4 bytes). Available in version 2 and above.
// - Uncompressed Size (4 bytes).
// - Truncated MD5 Hash (8 bytes).
// - Compressed Data (variable length).
Expand All @@ -109,13 +110,17 @@ class CompressedOffloadBundle {
static inline const size_t MagicSize = 4;
static inline const size_t VersionFieldSize = sizeof(uint16_t);
static inline const size_t MethodFieldSize = sizeof(uint16_t);
static inline const size_t SizeFieldSize = sizeof(uint32_t);
static inline const size_t HashFieldSize = 8;
static inline const size_t HeaderSize = MagicSize + VersionFieldSize +
MethodFieldSize + SizeFieldSize +
HashFieldSize;
static inline const size_t FileSizeFieldSize = sizeof(uint32_t);
static inline const size_t UncompressedSizeFieldSize = sizeof(uint32_t);
static inline const size_t HashFieldSize = sizeof(uint64_t);
static inline const size_t V1HeaderSize =
MagicSize + VersionFieldSize + MethodFieldSize +
UncompressedSizeFieldSize + HashFieldSize;
static inline const size_t V2HeaderSize =
MagicSize + VersionFieldSize + FileSizeFieldSize + MethodFieldSize +
UncompressedSizeFieldSize + HashFieldSize;
static inline const llvm::StringRef MagicNumber = "CCOB";
static inline const uint16_t Version = 1;
static inline const uint16_t Version = 2;

public:
static llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
Expand Down
31 changes: 27 additions & 4 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -807,8 +807,12 @@ def gcc_install_dir_EQ : Joined<["--"], "gcc-install-dir=">,
"Note: executables (e.g. ld) used by the compiler are not overridden by the selected GCC installation">;
def gcc_toolchain : Joined<["--"], "gcc-toolchain=">, Flags<[NoXarchOption]>,
Visibility<[ClangOption, FlangOption]>,
HelpText<"Specify a directory where Clang can find 'include' and 'lib{,32,64}/gcc{,-cross}/$triple/$version'. "
"Clang will use the GCC installation with the largest version">;
HelpText<
"Specify a directory where Clang can find 'include' and 'lib{,32,64}/gcc{,-cross}/$triple/$version'. "
"Clang will use the GCC installation with the largest version">,
HelpTextForVariants<[FlangOption],
"Specify a directory where Flang can find 'lib{,32,64}/gcc{,-cross}/$triple/$version'. "
"Flang will use the GCC installation with the largest version">;
def gcc_triple_EQ : Joined<["--"], "gcc-triple=">,
HelpText<"Search for the GCC installation with the specified triple.">;
def CC : Flag<["-"], "CC">, Visibility<[ClangOption, CC1Option]>,
Expand Down Expand Up @@ -3100,6 +3104,11 @@ defm modules_skip_header_search_paths : BoolFOption<"modules-skip-header-search-
HeaderSearchOpts<"ModulesSkipHeaderSearchPaths">, DefaultFalse,
PosFlag<SetTrue, [], [], "Disable writing header search paths">,
NegFlag<SetFalse>, BothFlags<[], [CC1Option]>>;
def fno_modules_prune_non_affecting_module_map_files :
Flag<["-"], "fno-modules-prune-non-affecting-module-map-files">,
Group<f_Group>, Flags<[]>, Visibility<[CC1Option]>,
MarshallingInfoNegativeFlag<HeaderSearchOpts<"ModulesPruneNonAffectingModuleMaps">>,
HelpText<"Do not prune non-affecting module map files when writing module files">;

def fincremental_extensions :
Flag<["-"], "fincremental-extensions">,
Expand Down Expand Up @@ -4747,9 +4756,9 @@ def munaligned_symbols : Flag<["-"], "munaligned-symbols">, Group<m_Group>,
HelpText<"Expect external char-aligned symbols to be without ABI alignment (SystemZ only)">;
def mno_unaligned_symbols : Flag<["-"], "mno-unaligned-symbols">, Group<m_Group>,
HelpText<"Expect external char-aligned symbols to be without ABI alignment (SystemZ only)">;
def mstrict_align : Flag<["-"], "mstrict-align">,
def mstrict_align : Flag<["-"], "mstrict-align">, Group<m_Group>,
HelpText<"Force all memory accesses to be aligned (AArch64/LoongArch/RISC-V only)">;
def mno_strict_align : Flag<["-"], "mno-strict-align">,
def mno_strict_align : Flag<["-"], "mno-strict-align">, Group<m_Group>,
HelpText<"Allow memory accesses to be unaligned (AArch64/LoongArch/RISC-V only)">;
def mno_thumb : Flag<["-"], "mno-thumb">, Group<m_arm_Features_Group>;
def mrestrict_it: Flag<["-"], "mrestrict-it">, Group<m_arm_Features_Group>,
Expand Down Expand Up @@ -5032,6 +5041,12 @@ def maix_small_local_exec_tls : Flag<["-"], "maix-small-local-exec-tls">,
"where the offset from the TLS base is encoded as an "
"immediate operand (AIX 64-bit only). "
"This access sequence is not used for variables larger than 32KB.">;
def maix_small_local_dynamic_tls : Flag<["-"], "maix-small-local-dynamic-tls">,
Group<m_ppc_Features_Group>,
HelpText<"Produce a faster access sequence for local-dynamic TLS variables "
"where the offset from the TLS base is encoded as an "
"immediate operand (AIX 64-bit only). "
"This access sequence is not used for variables larger than 32KB.">;
def maix_struct_return : Flag<["-"], "maix-struct-return">,
Group<m_Group>, Visibility<[ClangOption, CC1Option]>,
HelpText<"Return all structs in memory (PPC32 only)">,
Expand Down Expand Up @@ -5493,6 +5508,14 @@ def fno_rtlib_add_rpath: Flag<["-"], "fno-rtlib-add-rpath">,
Visibility<[ClangOption, FlangOption]>,
HelpText<"Do not add -rpath with architecture-specific resource directory to the linker flags. "
"When --hip-link is specified, do not add -rpath with HIP runtime library directory to the linker flags">;
def frtlib_defaultlib : Flag<["-"], "frtlib-defaultlib">,
Visibility<[ClangOption, CLOption]>,
Group<f_Group>,
HelpText<"On Windows, emit /defaultlib: directives to link compiler-rt libraries (default)">;
def fno_rtlib_defaultlib : Flag<["-"], "fno-rtlib-defaultlib">,
Visibility<[ClangOption, CLOption]>,
Group<f_Group>,
HelpText<"On Windows, do not emit /defaultlib: directives to link compiler-rt libraries">;
def offload_add_rpath: Flag<["--"], "offload-add-rpath">,
Flags<[NoArgumentUnused]>,
Alias<frtlib_add_rpath>;
Expand Down
7 changes: 6 additions & 1 deletion clang/include/clang/Lex/HeaderSearchOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,10 @@ class HeaderSearchOptions {
LLVM_PREFERRED_TYPE(bool)
unsigned ModulesSkipPragmaDiagnosticMappings : 1;

/// Whether to prune non-affecting module map files from PCM files.
LLVM_PREFERRED_TYPE(bool)
unsigned ModulesPruneNonAffectingModuleMaps : 1;

LLVM_PREFERRED_TYPE(bool)
unsigned ModulesHashContent : 1;

Expand Down Expand Up @@ -280,7 +284,8 @@ class HeaderSearchOptions {
ModulesValidateDiagnosticOptions(true),
ModulesSkipDiagnosticOptions(false),
ModulesSkipHeaderSearchPaths(false),
ModulesSkipPragmaDiagnosticMappings(false), ModulesHashContent(false),
ModulesSkipPragmaDiagnosticMappings(false),
ModulesPruneNonAffectingModuleMaps(true), ModulesHashContent(false),
ModulesStrictContextHash(false), ModulesIncludeVFSUsage(false) {}

/// AddPath - Add the \p Path path to the specified \p Group list.
Expand Down
3 changes: 2 additions & 1 deletion clang/include/clang/Lex/LiteralSupport.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ class NumericLiteralParser {
bool isFloat128 : 1; // 1.0q
bool isFract : 1; // 1.0hr/r/lr/uhr/ur/ulr
bool isAccum : 1; // 1.0hk/k/lk/uhk/uk/ulk
bool isBitInt : 1; // 1wb, 1uwb (C23)
bool isBitInt : 1; // 1wb, 1uwb (C23) or 1__wb, 1__uwb (Clang extension in C++
// mode)
uint8_t MicrosoftInteger; // Microsoft suffix extension i8, i16, i32, or i64.


Expand Down
60 changes: 48 additions & 12 deletions clang/include/clang/Parse/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,15 @@ class Parser : public CodeCompletionHandler {
/// top-level declaration is finished.
SmallVector<TemplateIdAnnotation *, 16> TemplateIds;

/// Don't destroy template annotations in MaybeDestroyTemplateIds even if
/// we're at the end of a declaration. Instead, we defer the destruction until
/// after a top-level declaration.
/// Use DelayTemplateIdDestructionRAII rather than setting it directly.
bool DelayTemplateIdDestruction = false;

void MaybeDestroyTemplateIds() {
if (DelayTemplateIdDestruction)
return;
if (!TemplateIds.empty() &&
(Tok.is(tok::eof) || !PP.mightHavePendingAnnotationTokens()))
DestroyTemplateIds();
Expand All @@ -329,6 +337,22 @@ class Parser : public CodeCompletionHandler {
~DestroyTemplateIdAnnotationsRAIIObj() { Self.MaybeDestroyTemplateIds(); }
};

struct DelayTemplateIdDestructionRAII {
Parser &Self;
bool PrevDelayTemplateIdDestruction;

DelayTemplateIdDestructionRAII(Parser &Self,
bool DelayTemplateIdDestruction) noexcept
: Self(Self),
PrevDelayTemplateIdDestruction(Self.DelayTemplateIdDestruction) {
Self.DelayTemplateIdDestruction = DelayTemplateIdDestruction;
}

~DelayTemplateIdDestructionRAII() noexcept {
Self.DelayTemplateIdDestruction = PrevDelayTemplateIdDestruction;
}
};

/// Identifiers which have been declared within a tentative parse.
SmallVector<const IdentifierInfo *, 8> TentativelyDeclaredIdentifiers;

Expand Down Expand Up @@ -2967,25 +2991,25 @@ class Parser : public CodeCompletionHandler {
Sema::AttributeCompletion Completion = Sema::AttributeCompletion::None,
const IdentifierInfo *EnclosingScope = nullptr);

void MaybeParseHLSLSemantics(Declarator &D,
SourceLocation *EndLoc = nullptr) {
assert(getLangOpts().HLSL && "MaybeParseHLSLSemantics is for HLSL only");
void MaybeParseHLSLAnnotations(Declarator &D,
SourceLocation *EndLoc = nullptr) {
assert(getLangOpts().HLSL && "MaybeParseHLSLAnnotations is for HLSL only");
if (Tok.is(tok::colon)) {
ParsedAttributes Attrs(AttrFactory);
ParseHLSLSemantics(Attrs, EndLoc);
ParseHLSLAnnotations(Attrs, EndLoc);
D.takeAttributes(Attrs);
}
}

void MaybeParseHLSLSemantics(ParsedAttributes &Attrs,
SourceLocation *EndLoc = nullptr) {
assert(getLangOpts().HLSL && "MaybeParseHLSLSemantics is for HLSL only");
void MaybeParseHLSLAnnotations(ParsedAttributes &Attrs,
SourceLocation *EndLoc = nullptr) {
assert(getLangOpts().HLSL && "MaybeParseHLSLAnnotations is for HLSL only");
if (getLangOpts().HLSL && Tok.is(tok::colon))
ParseHLSLSemantics(Attrs, EndLoc);
ParseHLSLAnnotations(Attrs, EndLoc);
}

void ParseHLSLSemantics(ParsedAttributes &Attrs,
SourceLocation *EndLoc = nullptr);
void ParseHLSLAnnotations(ParsedAttributes &Attrs,
SourceLocation *EndLoc = nullptr);
Decl *ParseHLSLBuffer(SourceLocation &DeclEnd);

void MaybeParseMicrosoftAttributes(ParsedAttributes &Attrs) {
Expand Down Expand Up @@ -3644,10 +3668,22 @@ class Parser : public CodeCompletionHandler {
/// Parses the clause of the 'bind' argument, which can be a string literal or
/// an ID expression.
ExprResult ParseOpenACCBindClauseArgument();

/// A type to represent the state of parsing after an attempt to parse an
/// OpenACC int-expr. This is useful to determine whether an int-expr list can
/// continue parsing after a failed int-expr.
using OpenACCIntExprParseResult =
std::pair<ExprResult, OpenACCParseCanContinue>;
/// Parses the clause kind of 'int-expr', which can be any integral
/// expression.
ExprResult ParseOpenACCIntExpr(OpenACCDirectiveKind DK, OpenACCClauseKind CK,
SourceLocation Loc);
OpenACCIntExprParseResult ParseOpenACCIntExpr(OpenACCDirectiveKind DK,
OpenACCClauseKind CK,
SourceLocation Loc);
/// Parses the argument list for 'num_gangs', which allows up to 3
/// 'int-expr's.
bool ParseOpenACCIntExprList(OpenACCDirectiveKind DK, OpenACCClauseKind CK,
SourceLocation Loc,
llvm::SmallVectorImpl<Expr *> &IntExprs);
/// Parses the 'device-type-list', which is a list of identifiers.
bool ParseOpenACCDeviceTypeList();
/// Parses the 'async-argument', which is an integral value with two
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/Sema/MultiplexExternalSemaSource.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class MultiplexExternalSemaSource : public ExternalSemaSource {

/// Resolve a declaration ID into a declaration, potentially
/// building a new declaration.
Decl *GetExternalDecl(uint32_t ID) override;
Decl *GetExternalDecl(Decl::DeclID ID) override;

/// Complete the redeclaration chain if it's been extended since the
/// previous generation of the AST source.
Expand Down
14 changes: 11 additions & 3 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -3084,6 +3084,7 @@ class Sema final : public SemaBase {
Decl *ActOnStartOfFunctionDef(Scope *S, Decl *D,
SkipBodyInfo *SkipBody = nullptr,
FnBodyKind BodyKind = FnBodyKind::Other);
void applyFunctionAttributesBeforeParsingBody(Decl *FD);

/// Determine whether we can delay parsing the body of a function or
/// function template until it is used, assuming we don't care about emitting
Expand Down Expand Up @@ -6527,7 +6528,10 @@ class Sema final : public SemaBase {
SourceLocation RParenLoc);

//// ActOnCXXThis - Parse 'this' pointer.
ExprResult ActOnCXXThis(SourceLocation loc);
ExprResult ActOnCXXThis(SourceLocation Loc);

/// Check whether the type of 'this' is valid in the current context.
bool CheckCXXThisType(SourceLocation Loc, QualType Type);

/// Build a CXXThisExpr and mark it referenced in the current context.
Expr *BuildCXXThisExpr(SourceLocation Loc, QualType Type, bool IsImplicit);
Expand Down Expand Up @@ -6949,10 +6953,14 @@ class Sema final : public SemaBase {
///@{

public:
/// Check whether an expression might be an implicit class member access.
bool isPotentialImplicitMemberAccess(const CXXScopeSpec &SS, LookupResult &R,
bool IsAddressOfOperand);

ExprResult BuildPossibleImplicitMemberExpr(
const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, LookupResult &R,
const TemplateArgumentListInfo *TemplateArgs, const Scope *S,
UnresolvedLookupExpr *AsULE = nullptr);
const TemplateArgumentListInfo *TemplateArgs, const Scope *S);

ExprResult
BuildImplicitMemberExpr(const CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
LookupResult &R,
Expand Down
16 changes: 13 additions & 3 deletions clang/include/clang/Sema/SemaOpenACC.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,14 +93,16 @@ class SemaOpenACC : public SemaBase {
}

unsigned getNumIntExprs() const {
assert((ClauseKind == OpenACCClauseKind::NumWorkers ||
assert((ClauseKind == OpenACCClauseKind::NumGangs ||
ClauseKind == OpenACCClauseKind::NumWorkers ||
ClauseKind == OpenACCClauseKind::VectorLength) &&
"Parsed clause kind does not have a int exprs");
return std::get<IntExprDetails>(Details).IntExprs.size();
}

ArrayRef<Expr *> getIntExprs() {
assert((ClauseKind == OpenACCClauseKind::NumWorkers ||
assert((ClauseKind == OpenACCClauseKind::NumGangs ||
ClauseKind == OpenACCClauseKind::NumWorkers ||
ClauseKind == OpenACCClauseKind::VectorLength) &&
"Parsed clause kind does not have a int exprs");
return std::get<IntExprDetails>(Details).IntExprs;
Expand Down Expand Up @@ -134,11 +136,19 @@ class SemaOpenACC : public SemaBase {
}

void setIntExprDetails(ArrayRef<Expr *> IntExprs) {
assert((ClauseKind == OpenACCClauseKind::NumWorkers ||
assert((ClauseKind == OpenACCClauseKind::NumGangs ||
ClauseKind == OpenACCClauseKind::NumWorkers ||
ClauseKind == OpenACCClauseKind::VectorLength) &&
"Parsed clause kind does not have a int exprs");
Details = IntExprDetails{{IntExprs.begin(), IntExprs.end()}};
}
void setIntExprDetails(llvm::SmallVector<Expr *> &&IntExprs) {
assert((ClauseKind == OpenACCClauseKind::NumGangs ||
ClauseKind == OpenACCClauseKind::NumWorkers ||
ClauseKind == OpenACCClauseKind::VectorLength) &&
"Parsed clause kind does not have a int exprs");
Details = IntExprDetails{IntExprs};
}
};

SemaOpenACC(Sema &S);
Expand Down
131 changes: 98 additions & 33 deletions clang/include/clang/Serialization/ASTBitCodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,85 @@ using IdentifierID = uint32_t;
/// discovery), with values below NUM_PREDEF_DECL_IDS being reserved.
/// At the start of a chain of precompiled headers, declaration ID 1 is
/// used for the translation unit declaration.
///
/// FIXME: Merge with Decl::DeclID
using DeclID = uint32_t;

// FIXME: Turn these into classes so we can have some type safety when
// we go from local ID to global and vice-versa.
using LocalDeclID = DeclID;
using GlobalDeclID = DeclID;
class LocalDeclID {
public:
explicit LocalDeclID(DeclID ID) : ID(ID) {}

DeclID get() const { return ID; }

private:
DeclID ID;
};

/// Wrapper class for DeclID. This is helpful to not mix the use of LocalDeclID
/// and GlobalDeclID to improve the type safety.
class GlobalDeclID {
public:
GlobalDeclID() : ID(0) {}
explicit GlobalDeclID(DeclID ID) : ID(ID) {}

DeclID get() const { return ID; }

explicit operator DeclID() const { return ID; }

friend bool operator==(const GlobalDeclID &LHS, const GlobalDeclID &RHS) {
return LHS.ID == RHS.ID;
}
friend bool operator!=(const GlobalDeclID &LHS, const GlobalDeclID &RHS) {
return LHS.ID != RHS.ID;
}
// We may sort the global decl ID.
friend bool operator<(const GlobalDeclID &LHS, const GlobalDeclID &RHS) {
return LHS.ID < RHS.ID;
}
friend bool operator>(const GlobalDeclID &LHS, const GlobalDeclID &RHS) {
return LHS.ID > RHS.ID;
}
friend bool operator<=(const GlobalDeclID &LHS, const GlobalDeclID &RHS) {
return LHS.ID <= RHS.ID;
}
friend bool operator>=(const GlobalDeclID &LHS, const GlobalDeclID &RHS) {
return LHS.ID >= RHS.ID;
}

private:
DeclID ID;
};

/// A helper iterator adaptor to convert the iterators to `SmallVector<DeclID>`
/// to the iterators to `SmallVector<GlobalDeclID>`.
class GlobalDeclIDIterator
: public llvm::iterator_adaptor_base<GlobalDeclIDIterator, const DeclID *,
std::forward_iterator_tag,
GlobalDeclID> {
public:
GlobalDeclIDIterator() : iterator_adaptor_base(nullptr) {}

GlobalDeclIDIterator(const DeclID *ID) : iterator_adaptor_base(ID) {}

value_type operator*() const { return GlobalDeclID(*I); }

bool operator==(const GlobalDeclIDIterator &RHS) const { return I == RHS.I; }
};

/// A helper iterator adaptor to convert the iterators to
/// `SmallVector<GlobalDeclID>` to the iterators to `SmallVector<DeclID>`.
class DeclIDIterator
: public llvm::iterator_adaptor_base<DeclIDIterator, const GlobalDeclID *,
std::forward_iterator_tag, DeclID> {
public:
DeclIDIterator() : iterator_adaptor_base(nullptr) {}

DeclIDIterator(const GlobalDeclID *ID) : iterator_adaptor_base(ID) {}

value_type operator*() const { return DeclID(*I); }

bool operator==(const DeclIDIterator &RHS) const { return I == RHS.I; }
};

/// An ID number that refers to a type in an AST file.
///
Expand Down Expand Up @@ -2056,35 +2129,6 @@ enum CtorInitializerType {
/// Kinds of cleanup objects owned by ExprWithCleanups.
enum CleanupObjectKind { COK_Block, COK_CompoundLiteral };

/// Describes the redeclarations of a declaration.
struct LocalRedeclarationsInfo {
// The ID of the first declaration
DeclID FirstID;

// Offset into the array of redeclaration chains.
unsigned Offset;

friend bool operator<(const LocalRedeclarationsInfo &X,
const LocalRedeclarationsInfo &Y) {
return X.FirstID < Y.FirstID;
}

friend bool operator>(const LocalRedeclarationsInfo &X,
const LocalRedeclarationsInfo &Y) {
return X.FirstID > Y.FirstID;
}

friend bool operator<=(const LocalRedeclarationsInfo &X,
const LocalRedeclarationsInfo &Y) {
return X.FirstID <= Y.FirstID;
}

friend bool operator>=(const LocalRedeclarationsInfo &X,
const LocalRedeclarationsInfo &Y) {
return X.FirstID >= Y.FirstID;
}
};

/// Describes the categories of an Objective-C class.
struct ObjCCategoriesInfo {
// The ID of the definition
Expand Down Expand Up @@ -2187,6 +2231,27 @@ template <> struct DenseMapInfo<clang::serialization::DeclarationNameKey> {
}
};

template <> struct DenseMapInfo<clang::serialization::GlobalDeclID> {
using DeclID = clang::serialization::DeclID;
using GlobalDeclID = clang::serialization::GlobalDeclID;

static GlobalDeclID getEmptyKey() {
return GlobalDeclID(DenseMapInfo<DeclID>::getEmptyKey());
}

static GlobalDeclID getTombstoneKey() {
return GlobalDeclID(DenseMapInfo<DeclID>::getTombstoneKey());
}

static unsigned getHashValue(const GlobalDeclID &Key) {
return DenseMapInfo<DeclID>::getHashValue(Key.get());
}

static bool isEqual(const GlobalDeclID &L, const GlobalDeclID &R) {
return L == R;
}
};

} // namespace llvm

#endif // LLVM_CLANG_SERIALIZATION_ASTBITCODES_H
98 changes: 59 additions & 39 deletions clang/include/clang/Serialization/ASTReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -504,7 +504,7 @@ class ASTReader
static_assert(std::is_same_v<serialization::DeclID, Decl::DeclID>);

using GlobalDeclMapType =
ContinuousRangeMap<serialization::DeclID, ModuleFile *, 4>;
ContinuousRangeMap<serialization::GlobalDeclID, ModuleFile *, 4>;

/// Mapping from global declaration IDs to the module in which the
/// declaration resides.
Expand All @@ -513,14 +513,14 @@ class ASTReader
using FileOffset = std::pair<ModuleFile *, uint64_t>;
using FileOffsetsTy = SmallVector<FileOffset, 2>;
using DeclUpdateOffsetsMap =
llvm::DenseMap<serialization::DeclID, FileOffsetsTy>;
llvm::DenseMap<serialization::GlobalDeclID, FileOffsetsTy>;

/// Declarations that have modifications residing in a later file
/// in the chain.
DeclUpdateOffsetsMap DeclUpdateOffsets;

using DelayedNamespaceOffsetMapTy = llvm::DenseMap<
serialization::DeclID,
serialization::GlobalDeclID,
std::pair</*LexicalOffset*/ uint64_t, /*VisibleOffset*/ uint64_t>>;

/// Mapping from global declaration IDs to the lexical and visible block
Expand Down Expand Up @@ -606,7 +606,11 @@ class ASTReader

/// An array of lexical contents of a declaration context, as a sequence of
/// Decl::Kind, DeclID pairs.
using LexicalContents = ArrayRef<llvm::support::unaligned_uint32_t>;
using unalighed_decl_id_t =
llvm::support::detail::packed_endian_specific_integral<
serialization::DeclID, llvm::endianness::native,
llvm::support::unaligned>;
using LexicalContents = ArrayRef<unalighed_decl_id_t>;

/// Map from a DeclContext to its lexical contents.
llvm::DenseMap<const DeclContext*, std::pair<ModuleFile*, LexicalContents>>
Expand All @@ -631,7 +635,7 @@ class ASTReader

/// Updates to the visible declarations of declaration contexts that
/// haven't been loaded yet.
llvm::DenseMap<serialization::DeclID, DeclContextVisibleUpdates>
llvm::DenseMap<serialization::GlobalDeclID, DeclContextVisibleUpdates>
PendingVisibleUpdates;

/// The set of C++ or Objective-C classes that have forward
Expand All @@ -658,7 +662,8 @@ class ASTReader
/// Read the record that describes the visible contents of a DC.
bool ReadVisibleDeclContextStorage(ModuleFile &M,
llvm::BitstreamCursor &Cursor,
uint64_t Offset, serialization::DeclID ID);
uint64_t Offset,
serialization::GlobalDeclID ID);

/// A vector containing identifiers that have already been
/// loaded.
Expand Down Expand Up @@ -811,29 +816,38 @@ class ASTReader
/// This contains the data loaded from all EAGERLY_DESERIALIZED_DECLS blocks
/// in the chain. The referenced declarations are deserialized and passed to
/// the consumer eagerly.
SmallVector<serialization::DeclID, 16> EagerlyDeserializedDecls;
SmallVector<serialization::GlobalDeclID, 16> EagerlyDeserializedDecls;

/// The IDs of all tentative definitions stored in the chain.
///
/// Sema keeps track of all tentative definitions in a TU because it has to
/// complete them and pass them on to CodeGen. Thus, tentative definitions in
/// the PCH chain must be eagerly deserialized.
SmallVector<serialization::DeclID, 16> TentativeDefinitions;
SmallVector<serialization::GlobalDeclID, 16> TentativeDefinitions;

/// The IDs of all CXXRecordDecls stored in the chain whose VTables are
/// used.
///
/// CodeGen has to emit VTables for these records, so they have to be eagerly
/// deserialized.
SmallVector<serialization::DeclID, 64> VTableUses;
struct VTableUse {
serialization::GlobalDeclID ID;
SourceLocation::UIntTy RawLoc;
bool Used;
};
SmallVector<VTableUse> VTableUses;

/// A snapshot of the pending instantiations in the chain.
///
/// This record tracks the instantiations that Sema has to perform at the
/// end of the TU. It consists of a pair of values for every pending
/// instantiation where the first value is the ID of the decl and the second
/// is the instantiation location.
SmallVector<serialization::DeclID, 64> PendingInstantiations;
struct PendingInstantiation {
serialization::GlobalDeclID ID;
SourceLocation::UIntTy RawLoc;
};
SmallVector<PendingInstantiation, 64> PendingInstantiations;

//@}

Expand All @@ -843,11 +857,11 @@ class ASTReader

/// A snapshot of Sema's unused file-scoped variable tracking, for
/// generating warnings.
SmallVector<serialization::DeclID, 16> UnusedFileScopedDecls;
SmallVector<serialization::GlobalDeclID, 16> UnusedFileScopedDecls;

/// A list of all the delegating constructors we've seen, to diagnose
/// cycles.
SmallVector<serialization::DeclID, 4> DelegatingCtorDecls;
SmallVector<serialization::GlobalDeclID, 4> DelegatingCtorDecls;

/// Method selectors used in a @selector expression. Used for
/// implementation of -Wselector.
Expand All @@ -860,7 +874,7 @@ class ASTReader
/// The IDs of type aliases for ext_vectors that exist in the chain.
///
/// Used by Sema for finding sugared names for ext_vectors in diagnostics.
SmallVector<serialization::DeclID, 4> ExtVectorDecls;
SmallVector<serialization::GlobalDeclID, 4> ExtVectorDecls;

//@}

Expand All @@ -871,7 +885,7 @@ class ASTReader
/// The IDs of all potentially unused typedef names in the chain.
///
/// Sema tracks these to emit warnings.
SmallVector<serialization::DeclID, 16> UnusedLocalTypedefNameCandidates;
SmallVector<serialization::GlobalDeclID, 16> UnusedLocalTypedefNameCandidates;

/// Our current depth in #pragma cuda force_host_device begin/end
/// macros.
Expand All @@ -880,7 +894,7 @@ class ASTReader
/// The IDs of the declarations Sema stores directly.
///
/// Sema tracks a few important decls, such as namespace std, directly.
SmallVector<serialization::DeclID, 4> SemaDeclRefs;
SmallVector<serialization::GlobalDeclID, 4> SemaDeclRefs;

/// The IDs of the types ASTContext stores directly.
///
Expand All @@ -891,7 +905,7 @@ class ASTReader
///
/// The AST context tracks a few important decls, currently cudaConfigureCall,
/// directly.
SmallVector<serialization::DeclID, 2> CUDASpecialDeclRefs;
SmallVector<serialization::GlobalDeclID, 2> CUDASpecialDeclRefs;

/// The floating point pragma option settings.
SmallVector<uint64_t, 1> FPPragmaOptions;
Expand Down Expand Up @@ -940,11 +954,15 @@ class ASTReader
llvm::DenseMap<const Decl *, std::set<std::string>> OpenCLDeclExtMap;

/// A list of the namespaces we've seen.
SmallVector<serialization::DeclID, 4> KnownNamespaces;
SmallVector<serialization::GlobalDeclID, 4> KnownNamespaces;

/// A list of undefined decls with internal linkage followed by the
/// SourceLocation of a matching ODR-use.
SmallVector<serialization::DeclID, 8> UndefinedButUsed;
struct UndefinedButUsedDecl {
serialization::GlobalDeclID ID;
SourceLocation::UIntTy RawLoc;
};
SmallVector<UndefinedButUsedDecl, 8> UndefinedButUsed;

/// Delete expressions to analyze at the end of translation unit.
SmallVector<uint64_t, 8> DelayedDeleteExprs;
Expand All @@ -956,7 +974,8 @@ class ASTReader
/// The IDs of all decls to be checked for deferred diags.
///
/// Sema tracks these to emit deferred diags.
llvm::SmallSetVector<serialization::DeclID, 4> DeclsToCheckForDeferredDiags;
llvm::SmallSetVector<serialization::GlobalDeclID, 4>
DeclsToCheckForDeferredDiags;

private:
struct ImportedSubmodule {
Expand Down Expand Up @@ -1093,8 +1112,8 @@ class ASTReader
///
/// The declarations on the identifier chain for these identifiers will be
/// loaded once the recursive loading has completed.
llvm::MapVector<IdentifierInfo *, SmallVector<uint32_t, 4>>
PendingIdentifierInfos;
llvm::MapVector<IdentifierInfo *, SmallVector<serialization::GlobalDeclID, 4>>
PendingIdentifierInfos;

/// The set of lookup results that we have faked in order to support
/// merging of partially deserialized decls but that we have not yet removed.
Expand Down Expand Up @@ -1221,7 +1240,7 @@ class ASTReader
SmallVector<ObjCInterfaceDecl *, 16> ObjCClassesLoaded;

using KeyDeclsMap =
llvm::DenseMap<Decl *, SmallVector<serialization::DeclID, 2>>;
llvm::DenseMap<Decl *, SmallVector<serialization::GlobalDeclID, 2>>;

/// A mapping from canonical declarations to the set of global
/// declaration IDs for key declaration that have been merged with that
Expand Down Expand Up @@ -1430,15 +1449,15 @@ class ASTReader
QualType readTypeRecord(unsigned Index);
RecordLocation TypeCursorForIndex(unsigned Index);
void LoadedDecl(unsigned Index, Decl *D);
Decl *ReadDeclRecord(serialization::DeclID ID);
Decl *ReadDeclRecord(serialization::GlobalDeclID ID);
void markIncompleteDeclChain(Decl *D);

/// Returns the most recent declaration of a declaration (which must be
/// of a redeclarable kind) that is either local or has already been loaded
/// merged into its redecl chain.
Decl *getMostRecentExistingDecl(Decl *D);

RecordLocation DeclCursorForID(serialization::DeclID ID,
RecordLocation DeclCursorForID(serialization::GlobalDeclID ID,
SourceLocation &Location);
void loadDeclUpdateRecords(PendingUpdateRecord &Record);
void loadPendingDeclChain(Decl *D, uint64_t LocalOffset);
Expand Down Expand Up @@ -1897,8 +1916,8 @@ class ASTReader

/// Map from a local declaration ID within a given module to a
/// global declaration ID.
serialization::DeclID getGlobalDeclID(ModuleFile &F,
serialization::LocalDeclID LocalID) const;
serialization::GlobalDeclID
getGlobalDeclID(ModuleFile &F, serialization::LocalDeclID LocalID) const;

/// Returns true if global DeclID \p ID originated from module \p M.
bool isDeclIDFromModule(serialization::GlobalDeclID ID, ModuleFile &M) const;
Expand All @@ -1912,23 +1931,23 @@ class ASTReader

/// Resolve a declaration ID into a declaration, potentially
/// building a new declaration.
Decl *GetDecl(serialization::DeclID ID);
Decl *GetExternalDecl(uint32_t ID) override;
Decl *GetDecl(serialization::GlobalDeclID ID);
Decl *GetExternalDecl(Decl::DeclID ID) override;

/// Resolve a declaration ID into a declaration. Return 0 if it's not
/// been loaded yet.
Decl *GetExistingDecl(serialization::DeclID ID);
Decl *GetExistingDecl(serialization::GlobalDeclID ID);

/// Reads a declaration with the given local ID in the given module.
Decl *GetLocalDecl(ModuleFile &F, uint32_t LocalID) {
Decl *GetLocalDecl(ModuleFile &F, serialization::LocalDeclID LocalID) {
return GetDecl(getGlobalDeclID(F, LocalID));
}

/// Reads a declaration with the given local ID in the given module.
///
/// \returns The requested declaration, casted to the given return type.
template<typename T>
T *GetLocalDeclAs(ModuleFile &F, uint32_t LocalID) {
template <typename T>
T *GetLocalDeclAs(ModuleFile &F, serialization::LocalDeclID LocalID) {
return cast_or_null<T>(GetLocalDecl(F, LocalID));
}

Expand All @@ -1939,14 +1958,14 @@ class ASTReader
/// module file.
serialization::DeclID
mapGlobalIDToModuleFileGlobalID(ModuleFile &M,
serialization::DeclID GlobalID);
serialization::GlobalDeclID GlobalID);

/// Reads a declaration ID from the given position in a record in the
/// given module.
///
/// \returns The declaration ID read from the record, adjusted to a global ID.
serialization::DeclID ReadDeclID(ModuleFile &F, const RecordData &Record,
unsigned &Idx);
serialization::GlobalDeclID
ReadDeclID(ModuleFile &F, const RecordData &Record, unsigned &Idx);

/// Reads a declaration from the given position in a record in the
/// given module.
Expand Down Expand Up @@ -2120,9 +2139,10 @@ class ASTReader
void LoadSelector(Selector Sel);

void SetIdentifierInfo(unsigned ID, IdentifierInfo *II);
void SetGloballyVisibleDecls(IdentifierInfo *II,
const SmallVectorImpl<uint32_t> &DeclIDs,
SmallVectorImpl<Decl *> *Decls = nullptr);
void SetGloballyVisibleDecls(
IdentifierInfo *II,
const SmallVectorImpl<serialization::GlobalDeclID> &DeclIDs,
SmallVectorImpl<Decl *> *Decls = nullptr);

/// Report a diagnostic.
DiagnosticBuilder Diag(unsigned DiagID) const;
Expand Down Expand Up @@ -2363,7 +2383,7 @@ class ASTReader

// Contains the IDs for declarations that were requested before we have
// access to a Sema object.
SmallVector<uint64_t, 16> PreloadedDeclIDs;
SmallVector<serialization::GlobalDeclID, 16> PreloadedDeclIDs;

/// Retrieve the semantic analysis object used to analyze the
/// translation unit in which the precompiled header is being
Expand Down
12 changes: 2 additions & 10 deletions clang/include/clang/Serialization/ASTRecordReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,13 +103,6 @@ class ASTRecordReader
DC);
}

/// Read the record that describes the visible contents of a DC.
bool readVisibleDeclContextStorage(uint64_t Offset,
serialization::DeclID ID) {
return Reader->ReadVisibleDeclContextStorage(*F, F->DeclsCursor, Offset,
ID);
}

ExplicitSpecifier readExplicitSpec() {
uint64_t Kind = readInt();
bool HasExpr = Kind & 0x1;
Expand Down Expand Up @@ -143,8 +136,7 @@ class ASTRecordReader
/// Reads a declaration with the given local ID in the given module.
///
/// \returns The requested declaration, casted to the given return type.
template<typename T>
T *GetLocalDeclAs(uint32_t LocalID) {
template <typename T> T *GetLocalDeclAs(serialization::LocalDeclID LocalID) {
return cast_or_null<T>(Reader->GetLocalDecl(*F, LocalID));
}

Expand Down Expand Up @@ -190,7 +182,7 @@ class ASTRecordReader
/// Reads a declaration ID from the given position in this record.
///
/// \returns The declaration ID read from the record, adjusted to a global ID.
serialization::DeclID readDeclID() {
serialization::GlobalDeclID readDeclID() {
return Reader->ReadDeclID(*F, Record, Idx);
}

Expand Down
4 changes: 2 additions & 2 deletions clang/include/clang/Serialization/ModuleFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -462,7 +462,7 @@ class ModuleFile {
serialization::DeclID BaseDeclID = 0;

/// Remapping table for declaration IDs in this module.
ContinuousRangeMap<uint32_t, int, 2> DeclRemap;
ContinuousRangeMap<serialization::DeclID, int, 2> DeclRemap;

/// Mapping from the module files that this module file depends on
/// to the base declaration ID for that module as it is understood within this
Expand All @@ -474,7 +474,7 @@ class ModuleFile {
llvm::DenseMap<ModuleFile *, serialization::DeclID> GlobalToLocalDeclIDs;

/// Array of file-level DeclIDs sorted by file.
const serialization::DeclID *FileSortedDecls = nullptr;
const serialization::LocalDeclID *FileSortedDecls = nullptr;
unsigned NumFileSortedDecls = 0;

/// Array of category list location information within this
Expand Down
11 changes: 10 additions & 1 deletion clang/lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1083,7 +1083,8 @@ void ASTContext::addModuleInitializer(Module *M, Decl *D) {
Inits->Initializers.push_back(D);
}

void ASTContext::addLazyModuleInitializers(Module *M, ArrayRef<uint32_t> IDs) {
void ASTContext::addLazyModuleInitializers(Module *M,
ArrayRef<Decl::DeclID> IDs) {
auto *&Inits = ModuleInitializers[M];
if (!Inits)
Inits = new (*this) PerModuleInitializers;
Expand Down Expand Up @@ -7241,6 +7242,14 @@ QualType ASTContext::isPromotableBitField(Expr *E) const {
// We perform that promotion here to match GCC and C++.
// FIXME: C does not permit promotion of an enum bit-field whose rank is
// greater than that of 'int'. We perform that promotion to match GCC.
//
// C23 6.3.1.1p2:
// The value from a bit-field of a bit-precise integer type is converted to
// the corresponding bit-precise integer type. (The rest is the same as in
// C11.)
if (QualType QT = Field->getType(); QT->isBitIntType())
return QT;

if (BitWidth < IntSize)
return IntTy;

Expand Down
27 changes: 20 additions & 7 deletions clang/lib/AST/ASTImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -695,7 +695,7 @@ namespace clang {
// Returns true if the given function has a placeholder return type and
// that type is declared inside the body of the function.
// E.g. auto f() { struct X{}; return X(); }
bool hasAutoReturnTypeDeclaredInside(FunctionDecl *D);
bool hasReturnTypeDeclaredInside(FunctionDecl *D);
};

template <typename InContainerTy>
Expand Down Expand Up @@ -3647,15 +3647,28 @@ class IsTypeDeclaredInsideVisitor
};
} // namespace

/// This function checks if the function has 'auto' return type that contains
/// This function checks if the given function has a return type that contains
/// a reference (in any way) to a declaration inside the same function.
bool ASTNodeImporter::hasAutoReturnTypeDeclaredInside(FunctionDecl *D) {
bool ASTNodeImporter::hasReturnTypeDeclaredInside(FunctionDecl *D) {
QualType FromTy = D->getType();
const auto *FromFPT = FromTy->getAs<FunctionProtoType>();
assert(FromFPT && "Must be called on FunctionProtoType");

auto IsCXX11LambdaWithouTrailingReturn = [&]() {
if (Importer.FromContext.getLangOpts().CPlusPlus14) // C++14 or later
return false;

if (FromFPT->hasTrailingReturn())
return false;

if (const auto *MD = dyn_cast<CXXMethodDecl>(D))
return cast<CXXRecordDecl>(MD->getDeclContext())->isLambda();

return false;
};

QualType RetT = FromFPT->getReturnType();
if (isa<AutoType>(RetT.getTypePtr())) {
if (isa<AutoType>(RetT.getTypePtr()) || IsCXX11LambdaWithouTrailingReturn()) {
FunctionDecl *Def = D->getDefinition();
IsTypeDeclaredInsideVisitor Visitor(Def ? Def : D);
return Visitor.CheckType(RetT);
Expand Down Expand Up @@ -3811,7 +3824,7 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
// E.g.: auto foo() { struct X{}; return X(); }
// To avoid an infinite recursion when importing, create the FunctionDecl
// with a simplified return type.
if (hasAutoReturnTypeDeclaredInside(D)) {
if (hasReturnTypeDeclaredInside(D)) {
FromReturnTy = Importer.getFromContext().VoidTy;
UsedDifferentProtoType = true;
}
Expand Down Expand Up @@ -8561,8 +8574,8 @@ ASTNodeImporter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) {

return UnresolvedLookupExpr::Create(
Importer.getToContext(), *ToNamingClassOrErr, *ToQualifierLocOrErr,
ToNameInfo, E->requiresADL(), E->isOverloaded(), ToDecls.begin(),
ToDecls.end());
ToNameInfo, E->requiresADL(), ToDecls.begin(), ToDecls.end(),
/*KnownDependent=*/E->isTypeDependent());
}

ExpectedStmt
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/DeclTemplate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ void RedeclarableTemplateDecl::loadLazySpecializationsImpl() const {
CommonBase *CommonBasePtr = getMostRecentDecl()->getCommonPtr();
if (CommonBasePtr->LazySpecializations) {
ASTContext &Context = getASTContext();
uint32_t *Specs = CommonBasePtr->LazySpecializations;
Decl::DeclID *Specs = CommonBasePtr->LazySpecializations;
CommonBasePtr->LazySpecializations = nullptr;
for (uint32_t I = 0, N = *Specs++; I != N; ++I)
(void)Context.getExternalSource()->GetExternalDecl(Specs[I]);
Expand Down
28 changes: 14 additions & 14 deletions clang/lib/AST/ExprCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -353,15 +353,14 @@ SourceLocation CXXPseudoDestructorExpr::getEndLoc() const {
UnresolvedLookupExpr::UnresolvedLookupExpr(
const ASTContext &Context, CXXRecordDecl *NamingClass,
NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc,
const DeclarationNameInfo &NameInfo, bool RequiresADL, bool Overloaded,
const DeclarationNameInfo &NameInfo, bool RequiresADL,
const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin,
UnresolvedSetIterator End, bool KnownDependent)
: OverloadExpr(UnresolvedLookupExprClass, Context, QualifierLoc,
TemplateKWLoc, NameInfo, TemplateArgs, Begin, End,
KnownDependent, false, false),
NamingClass(NamingClass) {
UnresolvedLookupExprBits.RequiresADL = RequiresADL;
UnresolvedLookupExprBits.Overloaded = Overloaded;
}

UnresolvedLookupExpr::UnresolvedLookupExpr(EmptyShell Empty,
Expand All @@ -373,15 +372,16 @@ UnresolvedLookupExpr::UnresolvedLookupExpr(EmptyShell Empty,
UnresolvedLookupExpr *UnresolvedLookupExpr::Create(
const ASTContext &Context, CXXRecordDecl *NamingClass,
NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo,
bool RequiresADL, bool Overloaded, UnresolvedSetIterator Begin,
UnresolvedSetIterator End) {
bool RequiresADL, UnresolvedSetIterator Begin, UnresolvedSetIterator End,
bool KnownDependent) {
unsigned NumResults = End - Begin;
unsigned Size = totalSizeToAlloc<DeclAccessPair, ASTTemplateKWAndArgsInfo,
TemplateArgumentLoc>(NumResults, 0, 0);
void *Mem = Context.Allocate(Size, alignof(UnresolvedLookupExpr));
return new (Mem) UnresolvedLookupExpr(Context, NamingClass, QualifierLoc,
SourceLocation(), NameInfo, RequiresADL,
Overloaded, nullptr, Begin, End, false);
return new (Mem) UnresolvedLookupExpr(
Context, NamingClass, QualifierLoc,
/*TemplateKWLoc=*/SourceLocation(), NameInfo, RequiresADL,
/*TemplateArgs=*/nullptr, Begin, End, KnownDependent);
}

UnresolvedLookupExpr *UnresolvedLookupExpr::Create(
Expand All @@ -390,16 +390,16 @@ UnresolvedLookupExpr *UnresolvedLookupExpr::Create(
const DeclarationNameInfo &NameInfo, bool RequiresADL,
const TemplateArgumentListInfo *Args, UnresolvedSetIterator Begin,
UnresolvedSetIterator End, bool KnownDependent) {
assert(Args || TemplateKWLoc.isValid());
unsigned NumResults = End - Begin;
bool HasTemplateKWAndArgsInfo = Args || TemplateKWLoc.isValid();
unsigned NumTemplateArgs = Args ? Args->size() : 0;
unsigned Size =
totalSizeToAlloc<DeclAccessPair, ASTTemplateKWAndArgsInfo,
TemplateArgumentLoc>(NumResults, 1, NumTemplateArgs);
unsigned Size = totalSizeToAlloc<DeclAccessPair, ASTTemplateKWAndArgsInfo,
TemplateArgumentLoc>(
NumResults, HasTemplateKWAndArgsInfo, NumTemplateArgs);
void *Mem = Context.Allocate(Size, alignof(UnresolvedLookupExpr));
return new (Mem) UnresolvedLookupExpr(
Context, NamingClass, QualifierLoc, TemplateKWLoc, NameInfo, RequiresADL,
/*Overloaded=*/true, Args, Begin, End, KnownDependent);
return new (Mem) UnresolvedLookupExpr(Context, NamingClass, QualifierLoc,
TemplateKWLoc, NameInfo, RequiresADL,
Args, Begin, End, KnownDependent);
}

UnresolvedLookupExpr *UnresolvedLookupExpr::CreateEmpty(
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/AST/ExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16853,13 +16853,13 @@ bool Expr::EvaluateCharRangeAsString(std::string &Result,
if (!::EvaluateInteger(SizeExpression, SizeValue, Info))
return false;

int64_t Size = SizeValue.getExtValue();
uint64_t Size = SizeValue.getZExtValue();

if (!::EvaluatePointer(PtrExpression, String, Info))
return false;

QualType CharTy = PtrExpression->getType()->getPointeeType();
for (int64_t I = 0; I < Size; ++I) {
for (uint64_t I = 0; I < Size; ++I) {
APValue Char;
if (!handleLValueToRValueConversion(Info, PtrExpression, CharTy, String,
Char))
Expand Down
4 changes: 1 addition & 3 deletions clang/lib/AST/ExternalASTSource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,7 @@ bool ExternalASTSource::layoutRecordType(
return false;
}

Decl *ExternalASTSource::GetExternalDecl(uint32_t ID) {
return nullptr;
}
Decl *ExternalASTSource::GetExternalDecl(Decl::DeclID ID) { return nullptr; }

Selector ExternalASTSource::GetExternalSelector(uint32_t ID) {
return Selector();
Expand Down
30 changes: 26 additions & 4 deletions clang/lib/AST/Interp/ByteCodeExprGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,12 @@ bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) {
return false;

PrimType T = classifyPrim(CE->getType());
if (T == PT_IntAP)
return this->emitCastPointerIntegralAP(Ctx.getBitWidth(CE->getType()),
CE);
if (T == PT_IntAPS)
return this->emitCastPointerIntegralAPS(Ctx.getBitWidth(CE->getType()),
CE);
return this->emitCastPointerIntegral(T, CE);
}

Expand Down Expand Up @@ -922,9 +928,9 @@ bool ByteCodeExprGen<Emitter>::VisitImplicitValueInitExpr(const ImplicitValueIni
return true;
}

if (QT->isAnyComplexType()) {
if (const auto *ComplexTy = E->getType()->getAs<ComplexType>()) {
assert(Initializing);
QualType ElemQT = QT->getAs<ComplexType>()->getElementType();
QualType ElemQT = ComplexTy->getElementType();
PrimType ElemT = classifyPrim(ElemQT);
for (unsigned I = 0; I < 2; ++I) {
if (!this->visitZeroInitializer(ElemT, ElemQT, E))
Expand All @@ -935,6 +941,20 @@ bool ByteCodeExprGen<Emitter>::VisitImplicitValueInitExpr(const ImplicitValueIni
return true;
}

if (const auto *VecT = E->getType()->getAs<VectorType>()) {
unsigned NumVecElements = VecT->getNumElements();
QualType ElemQT = VecT->getElementType();
PrimType ElemT = classifyPrim(ElemQT);

for (unsigned I = 0; I < NumVecElements; ++I) {
if (!this->visitZeroInitializer(ElemT, ElemQT, E))
return false;
if (!this->emitInitElem(ElemT, I, E))
return false;
}
return true;
}

return false;
}

Expand Down Expand Up @@ -1098,13 +1118,13 @@ bool ByteCodeExprGen<Emitter>::VisitInitListExpr(const InitListExpr *E) {
return true;
}

if (T->isAnyComplexType()) {
if (const auto *ComplexTy = E->getType()->getAs<ComplexType>()) {
unsigned NumInits = E->getNumInits();

if (NumInits == 1)
return this->delegate(E->inits()[0]);

QualType ElemQT = E->getType()->getAs<ComplexType>()->getElementType();
QualType ElemQT = ComplexTy->getElementType();
PrimType ElemT = classifyPrim(ElemQT);
if (NumInits == 0) {
// Zero-initialize both elements.
Expand Down Expand Up @@ -1337,6 +1357,8 @@ bool ByteCodeExprGen<Emitter>::VisitMemberExpr(const MemberExpr *E) {
if (const auto *FD = dyn_cast<FieldDecl>(Member)) {
const RecordDecl *RD = FD->getParent();
const Record *R = getRecord(RD);
if (!R)
return false;
const Record::Field *F = R->getField(FD);
// Leave a pointer to the field on the stack.
if (F->Decl->getType()->isReferenceType())
Expand Down
25 changes: 24 additions & 1 deletion clang/lib/AST/Interp/ByteCodeStmtGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -675,7 +675,30 @@ bool ByteCodeStmtGen<Emitter>::visitDefaultStmt(const DefaultStmt *S) {

template <class Emitter>
bool ByteCodeStmtGen<Emitter>::visitAttributedStmt(const AttributedStmt *S) {
// Ignore all attributes.

for (const Attr *A : S->getAttrs()) {
auto *AA = dyn_cast<CXXAssumeAttr>(A);
if (!AA)
continue;

assert(isa<NullStmt>(S->getSubStmt()));

const Expr *Assumption = AA->getAssumption();
if (Assumption->isValueDependent())
return false;

if (Assumption->HasSideEffects(this->Ctx.getASTContext()))
continue;

// Evaluate assumption.
if (!this->visitBool(Assumption))
return false;

if (!this->emitAssume(Assumption))
return false;
}

// Ignore other attributes.
return this->visitStmt(S->getSubStmt());
}

Expand Down
5 changes: 4 additions & 1 deletion clang/lib/AST/Interp/IntegralAP.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,10 @@ template <bool Signed> class IntegralAP final {
}

IntegralAP truncate(unsigned BitWidth) const {
return IntegralAP(V.trunc(BitWidth));
if constexpr (Signed)
return IntegralAP(V.trunc(BitWidth).sextOrTrunc(this->bitWidth()));
else
return IntegralAP(V.trunc(BitWidth).zextOrTrunc(this->bitWidth()));
}

IntegralAP<false> toUnsigned() const {
Expand Down
63 changes: 51 additions & 12 deletions clang/lib/AST/Interp/Interp.h
Original file line number Diff line number Diff line change
Expand Up @@ -1548,17 +1548,16 @@ bool OffsetHelper(InterpState &S, CodePtr OpPC, const T &Offset,
if (!CheckArray(S, OpPC, Ptr))
return false;

// Get a version of the index comparable to the type.
T Index = T::from(Ptr.getIndex(), Offset.bitWidth());
// Compute the largest index into the array.
T MaxIndex = T::from(Ptr.getNumElems(), Offset.bitWidth());
uint64_t Index = Ptr.getIndex();
uint64_t MaxIndex = static_cast<uint64_t>(Ptr.getNumElems());

bool Invalid = false;
// Helper to report an invalid offset, computed as APSInt.
auto DiagInvalidOffset = [&]() -> void {
const unsigned Bits = Offset.bitWidth();
APSInt APOffset(Offset.toAPSInt().extend(Bits + 2), false);
APSInt APIndex(Index.toAPSInt().extend(Bits + 2), false);
APSInt APOffset(Offset.toAPSInt().extend(Bits + 2), /*IsUnsigend=*/false);
APSInt APIndex(APInt(Bits + 2, Index, /*IsSigned=*/true),
/*IsUnsigned=*/false);
APSInt NewIndex =
(Op == ArithOp::Add) ? (APIndex + APOffset) : (APIndex - APOffset);
S.CCEDiag(S.Current->getSource(OpPC), diag::note_constexpr_array_index)
Expand All @@ -1569,22 +1568,24 @@ bool OffsetHelper(InterpState &S, CodePtr OpPC, const T &Offset,
};

if (Ptr.isBlockPointer()) {
T MaxOffset = T::from(MaxIndex - Index, Offset.bitWidth());
uint64_t IOffset = static_cast<uint64_t>(Offset);
uint64_t MaxOffset = MaxIndex - Index;

if constexpr (Op == ArithOp::Add) {
// If the new offset would be negative, bail out.
if (Offset.isNegative() && (Offset.isMin() || -Offset > Index))
if (Offset.isNegative() && (Offset.isMin() || -IOffset > Index))
DiagInvalidOffset();

// If the new offset would be out of bounds, bail out.
if (Offset.isPositive() && Offset > MaxOffset)
if (Offset.isPositive() && IOffset > MaxOffset)
DiagInvalidOffset();
} else {
// If the new offset would be negative, bail out.
if (Offset.isPositive() && Index < Offset)
if (Offset.isPositive() && Index < IOffset)
DiagInvalidOffset();

// If the new offset would be out of bounds, bail out.
if (Offset.isNegative() && (Offset.isMin() || -Offset > MaxOffset))
if (Offset.isNegative() && (Offset.isMin() || -IOffset > MaxOffset))
DiagInvalidOffset();
}
}
Expand All @@ -1601,7 +1602,7 @@ bool OffsetHelper(InterpState &S, CodePtr OpPC, const T &Offset,
else
Result = WideIndex - WideOffset;

S.Stk.push<Pointer>(Ptr.atIndex(static_cast<unsigned>(Result)));
S.Stk.push<Pointer>(Ptr.atIndex(static_cast<uint64_t>(Result)));
return true;
}

Expand Down Expand Up @@ -1832,6 +1833,32 @@ bool CastPointerIntegral(InterpState &S, CodePtr OpPC) {
return true;
}

static inline bool CastPointerIntegralAP(InterpState &S, CodePtr OpPC,
uint32_t BitWidth) {
const Pointer &Ptr = S.Stk.pop<Pointer>();

const SourceInfo &E = S.Current->getSource(OpPC);
S.CCEDiag(E, diag::note_constexpr_invalid_cast)
<< 2 << S.getLangOpts().CPlusPlus << S.Current->getRange(OpPC);

S.Stk.push<IntegralAP<false>>(
IntegralAP<false>::from(Ptr.getIntegerRepresentation(), BitWidth));
return true;
}

static inline bool CastPointerIntegralAPS(InterpState &S, CodePtr OpPC,
uint32_t BitWidth) {
const Pointer &Ptr = S.Stk.pop<Pointer>();

const SourceInfo &E = S.Current->getSource(OpPC);
S.CCEDiag(E, diag::note_constexpr_invalid_cast)
<< 2 << S.getLangOpts().CPlusPlus << S.Current->getRange(OpPC);

S.Stk.push<IntegralAP<true>>(
IntegralAP<true>::from(Ptr.getIntegerRepresentation(), BitWidth));
return true;
}

//===----------------------------------------------------------------------===//
// Zero, Nullptr
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -2300,6 +2327,18 @@ inline bool InvalidDeclRef(InterpState &S, CodePtr OpPC,
return CheckDeclRef(S, OpPC, DR);
}

inline bool Assume(InterpState &S, CodePtr OpPC) {
const auto Val = S.Stk.pop<Boolean>();

if (Val)
return true;

// Else, diagnose.
const SourceLocation &Loc = S.Current->getLocation(OpPC);
S.CCEDiag(Loc, diag::note_constexpr_assumption_failed);
return false;
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
inline bool OffsetOf(InterpState &S, CodePtr OpPC, const OffsetOfExpr *E) {
llvm::SmallVector<int64_t> ArrayIndices;
Expand Down
17 changes: 17 additions & 0 deletions clang/lib/AST/Interp/InterpBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "Boolean.h"
#include "Interp.h"
#include "PrimType.h"
#include "clang/AST/OSLog.h"
#include "clang/AST/RecordLayout.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/TargetInfo.h"
Expand Down Expand Up @@ -1088,6 +1089,17 @@ static bool interp__builtin_is_aligned_up_down(InterpState &S, CodePtr OpPC,
return false;
}

static bool interp__builtin_os_log_format_buffer_size(InterpState &S,
CodePtr OpPC,
const InterpFrame *Frame,
const Function *Func,
const CallExpr *Call) {
analyze_os_log::OSLogBufferLayout Layout;
analyze_os_log::computeOSLogBufferLayout(S.getCtx(), Call, Layout);
pushInteger(S, Layout.size().getQuantity(), Call->getType());
return true;
}

bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
const CallExpr *Call) {
const InterpFrame *Frame = S.Current;
Expand Down Expand Up @@ -1409,6 +1421,11 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
return false;
break;

case Builtin::BI__builtin_os_log_format_buffer_size:
if (!interp__builtin_os_log_format_buffer_size(S, OpPC, Frame, F, Call))
return false;
break;

default:
S.FFDiag(S.Current->getLocation(OpPC),
diag::note_invalid_subexpr_in_const_expr)
Expand Down
15 changes: 13 additions & 2 deletions clang/lib/AST/Interp/Opcodes.td
Original file line number Diff line number Diff line change
Expand Up @@ -664,10 +664,19 @@ def CastFloatingIntegralAPS : Opcode {
}

def CastPointerIntegral : Opcode {
let Types = [AluTypeClass];
let Args = [];
let Types = [FixedSizeIntegralTypeClass];
let HasGroup = 1;
}
def CastPointerIntegralAP : Opcode {
let Types = [];
let HasGroup = 0;
let Args = [ArgUint32];
}
def CastPointerIntegralAPS : Opcode {
let Types = [];
let HasGroup = 0;
let Args = [ArgUint32];
}

def DecayPtr : Opcode {
let Types = [PtrTypeClass, PtrTypeClass];
Expand Down Expand Up @@ -727,6 +736,8 @@ def InvalidDeclRef : Opcode {
let Args = [ArgDeclRef];
}

def Assume : Opcode;

def ArrayDecay : Opcode;

def CheckNonNullArg : Opcode {
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/AST/Interp/Pointer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Pointer::Pointer(Block *Pointee)
: Pointer(Pointee, Pointee->getDescriptor()->getMetadataSize(),
Pointee->getDescriptor()->getMetadataSize()) {}

Pointer::Pointer(Block *Pointee, unsigned BaseAndOffset)
Pointer::Pointer(Block *Pointee, uint64_t BaseAndOffset)
: Pointer(Pointee, BaseAndOffset, BaseAndOffset) {}

Pointer::Pointer(const Pointer &P)
Expand All @@ -34,7 +34,7 @@ Pointer::Pointer(const Pointer &P)
PointeeStorage.BS.Pointee->addPointer(this);
}

Pointer::Pointer(Block *Pointee, unsigned Base, unsigned Offset)
Pointer::Pointer(Block *Pointee, unsigned Base, uint64_t Offset)
: Offset(Offset), StorageKind(Storage::Block) {
assert((Base == RootPtrMark || Base % alignof(void *) == 0) && "wrong base");

Expand Down
12 changes: 6 additions & 6 deletions clang/lib/AST/Interp/Pointer.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,10 @@ class Pointer {
PointeeStorage.Int.Desc = nullptr;
}
Pointer(Block *B);
Pointer(Block *B, unsigned BaseAndOffset);
Pointer(Block *B, uint64_t BaseAndOffset);
Pointer(const Pointer &P);
Pointer(Pointer &&P);
Pointer(uint64_t Address, const Descriptor *Desc, unsigned Offset = 0)
Pointer(uint64_t Address, const Descriptor *Desc, uint64_t Offset = 0)
: Offset(Offset), StorageKind(Storage::Int) {
PointeeStorage.Int.Value = Address;
PointeeStorage.Int.Desc = Desc;
Expand Down Expand Up @@ -134,14 +134,14 @@ class Pointer {
std::optional<APValue> toRValue(const Context &Ctx) const;

/// Offsets a pointer inside an array.
[[nodiscard]] Pointer atIndex(unsigned Idx) const {
[[nodiscard]] Pointer atIndex(uint64_t Idx) const {
if (isIntegralPointer())
return Pointer(asIntPointer().Value, asIntPointer().Desc, Idx);

if (asBlockPointer().Base == RootPtrMark)
return Pointer(asBlockPointer().Pointee, RootPtrMark,
getDeclDesc()->getSize());
unsigned Off = Idx * elemSize();
uint64_t Off = Idx * elemSize();
if (getFieldDesc()->ElemDesc)
Off += sizeof(InlineDescriptor);
else
Expand Down Expand Up @@ -630,7 +630,7 @@ class Pointer {
friend class DeadBlock;
friend struct InitMap;

Pointer(Block *Pointee, unsigned Base, unsigned Offset);
Pointer(Block *Pointee, unsigned Base, uint64_t Offset);

/// Returns the embedded descriptor preceding a field.
InlineDescriptor *getInlineDesc() const {
Expand All @@ -656,7 +656,7 @@ class Pointer {
}

/// Offset into the storage.
unsigned Offset = 0;
uint64_t Offset = 0;

/// Previous link in the pointer chain.
Pointer *Prev = nullptr;
Expand Down
15 changes: 5 additions & 10 deletions clang/lib/AST/Interp/Program.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,27 +108,23 @@ Pointer Program::getPtrGlobal(unsigned Idx) const {
}

std::optional<unsigned> Program::getGlobal(const ValueDecl *VD) {
auto It = GlobalIndices.find(VD);
if (It != GlobalIndices.end())
if (auto It = GlobalIndices.find(VD); It != GlobalIndices.end())
return It->second;

// Find any previous declarations which were already evaluated.
std::optional<unsigned> Index;
for (const Decl *P = VD; P; P = P->getPreviousDecl()) {
auto It = GlobalIndices.find(P);
if (It != GlobalIndices.end()) {
for (const Decl *P = VD->getPreviousDecl(); P; P = P->getPreviousDecl()) {
if (auto It = GlobalIndices.find(P); It != GlobalIndices.end()) {
Index = It->second;
break;
}
}

// Map the decl to the existing index.
if (Index) {
if (Index)
GlobalIndices[VD] = *Index;
return std::nullopt;
}

return Index;
return std::nullopt;
}

std::optional<unsigned> Program::getOrCreateGlobal(const ValueDecl *VD,
Expand Down Expand Up @@ -173,7 +169,6 @@ std::optional<unsigned> Program::getOrCreateDummy(const ValueDecl *VD) {

std::optional<unsigned> Program::createGlobal(const ValueDecl *VD,
const Expr *Init) {
assert(!getGlobal(VD));
bool IsStatic, IsExtern;
if (const auto *Var = dyn_cast<VarDecl>(VD)) {
IsStatic = Context::shouldBeGloballyIndexed(VD);
Expand Down
18 changes: 9 additions & 9 deletions clang/lib/AST/ItaniumMangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1062,33 +1062,35 @@ void CXXNameMangler::mangleNameWithAbiTags(GlobalDecl GD,
// ::= <local-name>
//
const DeclContext *DC = Context.getEffectiveDeclContext(ND);
bool IsLambda = isLambda(ND);

// If this is an extern variable declared locally, the relevant DeclContext
// is that of the containing namespace, or the translation unit.
// FIXME: This is a hack; extern variables declared locally should have
// a proper semantic declaration context!
if (isLocalContainerContext(DC) && ND->hasLinkage() && !isLambda(ND))
if (isLocalContainerContext(DC) && ND->hasLinkage() && !IsLambda)
while (!DC->isNamespace() && !DC->isTranslationUnit())
DC = Context.getEffectiveParentContext(DC);
else if (GetLocalClassDecl(ND)) {
else if (GetLocalClassDecl(ND) &&
(!IsLambda || isCompatibleWith(LangOptions::ClangABI::Ver18))) {
mangleLocalName(GD, AdditionalAbiTags);
return;
}

assert(!isa<LinkageSpecDecl>(DC) && "context cannot be LinkageSpecDecl");

if (isLocalContainerContext(DC)) {
mangleLocalName(GD, AdditionalAbiTags);
return;
}

// Closures can require a nested-name mangling even if they're semantically
// in the global namespace.
if (const NamedDecl *PrefixND = getClosurePrefix(ND)) {
mangleNestedNameWithClosurePrefix(GD, PrefixND, AdditionalAbiTags);
return;
}

if (isLocalContainerContext(DC)) {
mangleLocalName(GD, AdditionalAbiTags);
return;
}

if (DC->isTranslationUnit() || isStdNamespace(DC)) {
// Check if we have a template.
const TemplateArgumentList *TemplateArgs = nullptr;
Expand Down Expand Up @@ -2201,8 +2203,6 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) {
if (NoFunction && isLocalContainerContext(DC))
return;

assert(!isLocalContainerContext(DC));

const NamedDecl *ND = cast<NamedDecl>(DC);
if (mangleSubstitution(ND))
return;
Expand Down
16 changes: 16 additions & 0 deletions clang/lib/AST/OpenACCClause.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,16 @@ OpenACCVectorLengthClause::Create(const ASTContext &C, SourceLocation BeginLoc,
OpenACCVectorLengthClause(BeginLoc, LParenLoc, IntExpr, EndLoc);
}

OpenACCNumGangsClause *OpenACCNumGangsClause::Create(const ASTContext &C,
SourceLocation BeginLoc,
SourceLocation LParenLoc,
ArrayRef<Expr *> IntExprs,
SourceLocation EndLoc) {
void *Mem = C.Allocate(
OpenACCNumGangsClause::totalSizeToAlloc<Expr *>(IntExprs.size()));
return new (Mem) OpenACCNumGangsClause(BeginLoc, LParenLoc, IntExprs, EndLoc);
}

//===----------------------------------------------------------------------===//
// OpenACC clauses printing methods
//===----------------------------------------------------------------------===//
Expand All @@ -141,6 +151,12 @@ void OpenACCClausePrinter::VisitSelfClause(const OpenACCSelfClause &C) {
OS << "(" << CondExpr << ")";
}

void OpenACCClausePrinter::VisitNumGangsClause(const OpenACCNumGangsClause &C) {
OS << "num_gangs(";
llvm::interleaveComma(C.getIntExprs(), OS);
OS << ")";
}

void OpenACCClausePrinter::VisitNumWorkersClause(
const OpenACCNumWorkersClause &C) {
OS << "num_workers(" << C.getIntExpr() << ")";
Expand Down
6 changes: 6 additions & 0 deletions clang/lib/AST/StmtProfile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2497,6 +2497,12 @@ void OpenACCClauseProfiler::VisitSelfClause(const OpenACCSelfClause &Clause) {
Profiler.VisitStmt(Clause.getConditionExpr());
}

void OpenACCClauseProfiler::VisitNumGangsClause(
const OpenACCNumGangsClause &Clause) {
for (auto *E : Clause.getIntExprs())
Profiler.VisitStmt(E);
}

void OpenACCClauseProfiler::VisitNumWorkersClause(
const OpenACCNumWorkersClause &Clause) {
assert(Clause.hasIntExpr() && "num_workers clause requires a valid int expr");
Expand Down
1 change: 1 addition & 0 deletions clang/lib/AST/TextNodeDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,7 @@ void TextNodeDumper::Visit(const OpenACCClause *C) {
break;
case OpenACCClauseKind::If:
case OpenACCClauseKind::Self:
case OpenACCClauseKind::NumGangs:
case OpenACCClauseKind::NumWorkers:
case OpenACCClauseKind::VectorLength:
// The condition expression will be printed as a part of the 'children',
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/ASTMatchers/Dynamic/Marshallers.h
Original file line number Diff line number Diff line change
Expand Up @@ -937,7 +937,7 @@ class MapAnyOfMatcherDescriptor : public MatcherDescriptor {
public:
MapAnyOfMatcherDescriptor(ASTNodeKind CladeNodeKind,
std::vector<ASTNodeKind> NodeKinds)
: CladeNodeKind(CladeNodeKind), NodeKinds(NodeKinds) {}
: CladeNodeKind(CladeNodeKind), NodeKinds(std::move(NodeKinds)) {}

VariantMatcher create(SourceRange NameRange, ArrayRef<ParserValue> Args,
Diagnostics *Error) const override {
Expand Down Expand Up @@ -1026,7 +1026,7 @@ class MapAnyOfBuilderDescriptor : public MatcherDescriptor {
}

return std::make_unique<MapAnyOfMatcherDescriptor>(CladeNodeKind,
NodeKinds);
std::move(NodeKinds));
}

bool isVariadic() const override { return true; }
Expand Down
6 changes: 6 additions & 0 deletions clang/lib/Analysis/FlowSensitive/ASTOps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -261,4 +261,10 @@ ReferencedDecls getReferencedDecls(const FunctionDecl &FD) {
return Result;
}

ReferencedDecls getReferencedDecls(const Stmt &S) {
ReferencedDecls Result;
getReferencedDecls(S, Result);
return Result;
}

} // namespace clang::dataflow
46 changes: 24 additions & 22 deletions clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -237,13 +237,8 @@ joinLocToVal(const llvm::MapVector<const StorageLocation *, Value *> &LocToVal,
continue;
assert(It->second != nullptr);

if (areEquivalentValues(*Val, *It->second)) {
Result.insert({Loc, Val});
continue;
}

if (Value *JoinedVal = joinDistinctValues(
Loc->getType(), *Val, Env1, *It->second, Env2, JoinedEnv, Model)) {
if (Value *JoinedVal = Environment::joinValues(
Loc->getType(), Val, Env1, It->second, Env2, JoinedEnv, Model)) {
Result.insert({Loc, JoinedVal});
}
}
Expand Down Expand Up @@ -775,27 +770,16 @@ Environment Environment::join(const Environment &EnvA, const Environment &EnvB,
JoinedEnv.LocForRecordReturnVal = EnvA.LocForRecordReturnVal;
JoinedEnv.ThisPointeeLoc = EnvA.ThisPointeeLoc;

if (EnvA.ReturnVal == nullptr || EnvB.ReturnVal == nullptr) {
// `ReturnVal` might not always get set -- for example if we have a return
// statement of the form `return some_other_func()` and we decide not to
// analyze `some_other_func()`.
// In this case, we can't say anything about the joined return value -- we
// don't simply want to propagate the return value that we do have, because
// it might not be the correct one.
// This occurs for example in the test `ContextSensitiveMutualRecursion`.
if (EnvA.CallStack.empty()) {
JoinedEnv.ReturnVal = nullptr;
} else if (areEquivalentValues(*EnvA.ReturnVal, *EnvB.ReturnVal)) {
JoinedEnv.ReturnVal = EnvA.ReturnVal;
} else {
assert(!EnvA.CallStack.empty());
// FIXME: Make `CallStack` a vector of `FunctionDecl` so we don't need this
// cast.
auto *Func = dyn_cast<FunctionDecl>(EnvA.CallStack.back());
assert(Func != nullptr);
if (Value *JoinedVal =
joinDistinctValues(Func->getReturnType(), *EnvA.ReturnVal, EnvA,
*EnvB.ReturnVal, EnvB, JoinedEnv, Model))
JoinedEnv.ReturnVal = JoinedVal;
JoinedEnv.ReturnVal =
joinValues(Func->getReturnType(), EnvA.ReturnVal, EnvA, EnvB.ReturnVal,
EnvB, JoinedEnv, Model);
}

if (EnvA.ReturnLoc == EnvB.ReturnLoc)
Expand All @@ -821,6 +805,24 @@ Environment Environment::join(const Environment &EnvA, const Environment &EnvB,
return JoinedEnv;
}

Value *Environment::joinValues(QualType Ty, Value *Val1,
const Environment &Env1, Value *Val2,
const Environment &Env2, Environment &JoinedEnv,
Environment::ValueModel &Model) {
if (Val1 == nullptr || Val2 == nullptr)
// We can't say anything about the joined value -- even if one of the values
// is non-null, we don't want to simply propagate it, because it would be
// too specific: Because the other value is null, that means we have no
// information at all about the value (i.e. the value is unconstrained).
return nullptr;

if (areEquivalentValues(*Val1, *Val2))
// Arbitrarily return one of the two values.
return Val1;

return joinDistinctValues(Ty, *Val1, Env1, *Val2, Env2, JoinedEnv, Model);
}

StorageLocation &Environment::createStorageLocation(QualType Type) {
return DACtx->createStorageLocation(Type);
}
Expand Down
Loading