1,728 changes: 777 additions & 951 deletions clang/bindings/python/clang/cindex.py

Large diffs are not rendered by default.

33 changes: 0 additions & 33 deletions clang/bindings/python/clang/enumerations.py

This file was deleted.

22 changes: 12 additions & 10 deletions clang/bindings/python/tests/cindex/test_enums.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import unittest

from clang.cindex import (
TokenKind,
CursorKind,
TemplateArgumentKind,
ExceptionSpecificationKind,
Expand All @@ -14,8 +15,9 @@
)


class TestCursorKind(unittest.TestCase):
class TestEnums(unittest.TestCase):
enums = [
TokenKind,
CursorKind,
TemplateArgumentKind,
ExceptionSpecificationKind,
Expand All @@ -31,17 +33,17 @@ class TestCursorKind(unittest.TestCase):
def test_from_id(self):
"""Check that kinds can be constructed from valid IDs"""
for enum in self.enums:
self.assertEqual(enum.from_id(2), enum._kinds[2])
self.assertEqual(enum.from_id(2), enum(2))
max_value = max([variant.value for variant in enum])
with self.assertRaises(ValueError):
enum.from_id(len(enum._kinds))
enum.from_id(max_value + 1)
with self.assertRaises(ValueError):
enum.from_id(-1)

def test_unique_kinds(self):
"""Check that no kind name has been used multiple times"""
def test_duplicate_ids(self):
"""Check that no two kinds have the same id"""
# for enum in self.enums:
for enum in self.enums:
for id in range(len(enum._kinds)):
try:
enum.from_id(id).name
except ValueError:
pass
num_declared_variants = len(enum._member_map_.keys())
num_unique_variants = len(list(enum))
self.assertEqual(num_declared_variants, num_unique_variants)
20 changes: 0 additions & 20 deletions clang/bindings/python/tests/cindex/test_token_kind.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,6 @@


class TestTokenKind(unittest.TestCase):
def test_constructor(self):
"""Ensure TokenKind constructor works as expected."""

t = TokenKind(5, "foo")

self.assertEqual(t.value, 5)
self.assertEqual(t.name, "foo")

def test_bad_register(self):
"""Ensure a duplicate value is rejected for registration."""

with self.assertRaises(ValueError):
TokenKind.register(2, "foo")

def test_unknown_value(self):
"""Ensure trying to fetch an unknown value raises."""

with self.assertRaises(ValueError):
TokenKind.from_value(-1)

def test_registration(self):
"""Ensure that items registered appear as class attributes."""
self.assertTrue(hasattr(TokenKind, "LITERAL"))
Expand Down
5 changes: 4 additions & 1 deletion clang/docs/LanguageExtensions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3977,7 +3977,10 @@ standard library ``<stdarg.h>`` header:
* ``__builtin_va_list``
A predefined typedef for the target-specific ``va_list`` type.
A predefined typedef for the target-specific ``va_list`` type. It is undefined
behavior to use a byte-wise copy of this type produced by calling ``memcpy``,
``memmove``, or similar. Valid explicit copies are only produced by calling
``va_copy`` or ``__builtin_va_copy``.
* ``void __builtin_va_start(__builtin_va_list list, <parameter-name>)``
Expand Down
17 changes: 15 additions & 2 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ code bases.
- Setting the deprecated CMake variable ``GCC_INSTALL_PREFIX`` (which sets the
default ``--gcc-toolchain=``) now leads to a fatal error.

- The ``le32`` and ``le64`` targets have been removed.

C/C++ Language Potentially Breaking Changes
-------------------------------------------

Expand Down Expand Up @@ -103,7 +105,7 @@ ABI Changes in This Version
ifuncs. Its purpose was to preserve backwards compatibility when the ".ifunc"
suffix got removed from the name mangling. The alias interacts badly with
GlobalOpt (see the issue #96197).

- Fixed Microsoft name mangling for auto non-type template arguments of pointer
type for MSVC 1920+. This change resolves incompatibilities with code compiled
by MSVC 1920+ but will introduce incompatibilities with code compiled by
Expand Down Expand Up @@ -165,6 +167,7 @@ Clang Python Bindings Potentially Breaking Changes
of variant 271.
- Renamed ``TypeKind`` variant 162 from ``OBJCCLASS`` to ``OBJCTYPEPARAM``.
The previous name was incorrect, it was a duplicate of variant 28.
- Refactored enum implementation, switching to the standard library `Enum` type.

What's New in Clang |release|?
==============================
Expand Down Expand Up @@ -310,6 +313,10 @@ Resolutions to C++ Defect Reports
- Clang now considers ``noexcept(typeid(expr))`` more carefully, instead of always assuming that ``std::bad_typeid`` can be thrown.
(`CWG2191: Incorrect result for noexcept(typeid(v)) <https://cplusplus.github.io/CWG/issues/2191.html>`_).

- Clang now correctly implements lookup for the terminal name of a member-qualified nested-name-specifier.
(`CWG1835: Dependent member lookup before < <https://cplusplus.github.io/CWG/issues/1835.html>`_).
The warning can be disabled via `-Wno-missing-dependent-template-keyword`.

C Language Changes
------------------

Expand Down Expand Up @@ -592,6 +599,9 @@ Attribute Changes in Clang

Improvements to Clang's diagnostics
-----------------------------------
- Clang now emits an error instead of a warning for ``-Wundefined-internal``
when compiling with `-pedantic-errors` to conform to the C standard

- Clang now applies syntax highlighting to the code snippets it
prints.

Expand Down Expand Up @@ -1005,7 +1015,7 @@ Bug Fixes to C++ Support
- Fixed a type constraint substitution issue involving a generic lambda expression. (#GH93821)
- Fix a crash caused by improper use of ``__array_extent``. (#GH80474)
- Fixed several bugs in capturing variables within unevaluated contexts. (#GH63845), (#GH67260), (#GH69307),
(#GH88081), (#GH89496), (#GH90669) and (#GH91633).
(#GH88081), (#GH89496), (#GH90669), (#GH91633) and (#GH97453).
- Fixed a crash in constraint instantiation under nested lambdas with dependent parameters.
- Fixed handling of brace ellison when building deduction guides. (#GH64625), (#GH83368).
- Clang now instantiates local constexpr functions eagerly for constant evaluators. (#GH35052), (#GH94849)
Expand All @@ -1024,6 +1034,9 @@ Bug Fixes to C++ Support
- Fixed a bug where references to lambda capture inside a ``noexcept`` specifier were not correctly
instantiated. (#GH95735).
- Fixed a CTAD substitution bug involving type aliases that reference outer template parameters. (#GH94614).
- Clang now correctly handles unexpanded packs in the template parameter list of a generic lambda expression
(#GH48937)
- Fix a crash when parsing an invalid type-requirement in a requires expression. (#GH51868)

Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
1 change: 0 additions & 1 deletion clang/docs/tools/clang-formatted-files.txt
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,6 @@ clang/lib/Basic/Targets/BPF.cpp
clang/lib/Basic/Targets/BPF.h
clang/lib/Basic/Targets/Hexagon.h
clang/lib/Basic/Targets/Lanai.h
clang/lib/Basic/Targets/Le64.h
clang/lib/Basic/Targets/M68k.h
clang/lib/Basic/Targets/MSP430.h
clang/lib/Basic/Targets/NVPTX.cpp
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/AST/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -1283,6 +1283,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
uint16_t
getPointerAuthVTablePointerDiscriminator(const CXXRecordDecl *RD);

/// Return the "other" type-specific discriminator for the given type.
uint16_t getPointerAuthTypeDiscriminator(QualType T) const;

/// Apply Objective-C protocol qualifiers to the given type.
/// \param allowOnPointerType specifies if we can apply protocol
/// qualifiers on ObjCObjectPointerType. It can be set to true when
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/AST/DeclBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -673,6 +673,9 @@ class alignas(8) Decl {
/// Whether this declaration comes from explicit global module.
bool isFromExplicitGlobalModule() const;

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

/// Return true if this declaration has an attribute which acts as
/// definition of the entity, such as 'alias' or 'ifunc'.
bool hasDefiningAttr() const;
Expand Down
92 changes: 49 additions & 43 deletions clang/include/clang/AST/ExprCXX.h
Original file line number Diff line number Diff line change
Expand Up @@ -3676,9 +3676,9 @@ class CXXUnresolvedConstructExpr final
/// an implicit access if a qualifier is provided.
class CXXDependentScopeMemberExpr final
: public Expr,
private llvm::TrailingObjects<CXXDependentScopeMemberExpr,
ASTTemplateKWAndArgsInfo,
TemplateArgumentLoc, NamedDecl *> {
private llvm::TrailingObjects<
CXXDependentScopeMemberExpr, NestedNameSpecifierLoc, DeclAccessPair,
ASTTemplateKWAndArgsInfo, TemplateArgumentLoc> {
friend class ASTStmtReader;
friend class ASTStmtWriter;
friend TrailingObjects;
Expand All @@ -3691,17 +3691,15 @@ class CXXDependentScopeMemberExpr final
/// implicit accesses.
QualType BaseType;

/// The nested-name-specifier that precedes the member name, if any.
/// FIXME: This could be in principle store as a trailing object.
/// However the performance impact of doing so should be investigated first.
NestedNameSpecifierLoc QualifierLoc;

/// The member to which this member expression refers, which
/// can be name, overloaded operator, or destructor.
///
/// FIXME: could also be a template-id
DeclarationNameInfo MemberNameInfo;

/// The location of the '->' or '.' operator.
SourceLocation OperatorLoc;

// CXXDependentScopeMemberExpr is followed by several trailing objects,
// some of which optional. They are in order:
//
Expand All @@ -3721,8 +3719,16 @@ class CXXDependentScopeMemberExpr final
return CXXDependentScopeMemberExprBits.HasTemplateKWAndArgsInfo;
}

bool hasFirstQualifierFoundInScope() const {
return CXXDependentScopeMemberExprBits.HasFirstQualifierFoundInScope;
unsigned getNumUnqualifiedLookups() const {
return CXXDependentScopeMemberExprBits.NumUnqualifiedLookups;
}

unsigned numTrailingObjects(OverloadToken<NestedNameSpecifierLoc>) const {
return hasQualifier();
}

unsigned numTrailingObjects(OverloadToken<DeclAccessPair>) const {
return getNumUnqualifiedLookups();
}

unsigned numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const {
Expand All @@ -3733,33 +3739,32 @@ class CXXDependentScopeMemberExpr final
return getNumTemplateArgs();
}

unsigned numTrailingObjects(OverloadToken<NamedDecl *>) const {
return hasFirstQualifierFoundInScope();
}

CXXDependentScopeMemberExpr(const ASTContext &Ctx, Expr *Base,
QualType BaseType, bool IsArrow,
SourceLocation OperatorLoc,
NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateKWLoc,
NamedDecl *FirstQualifierFoundInScope,
ArrayRef<DeclAccessPair> UnqualifiedLookups,
DeclarationNameInfo MemberNameInfo,
const TemplateArgumentListInfo *TemplateArgs);

CXXDependentScopeMemberExpr(EmptyShell Empty, bool HasTemplateKWAndArgsInfo,
bool HasFirstQualifierFoundInScope);
CXXDependentScopeMemberExpr(EmptyShell Empty, bool HasQualifier,
unsigned NumUnqualifiedLookups,
bool HasTemplateKWAndArgsInfo);

public:
static CXXDependentScopeMemberExpr *
Create(const ASTContext &Ctx, Expr *Base, QualType BaseType, bool IsArrow,
SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateKWLoc, NamedDecl *FirstQualifierFoundInScope,
SourceLocation TemplateKWLoc,
ArrayRef<DeclAccessPair> UnqualifiedLookups,
DeclarationNameInfo MemberNameInfo,
const TemplateArgumentListInfo *TemplateArgs);

static CXXDependentScopeMemberExpr *
CreateEmpty(const ASTContext &Ctx, bool HasTemplateKWAndArgsInfo,
unsigned NumTemplateArgs, bool HasFirstQualifierFoundInScope);
CreateEmpty(const ASTContext &Ctx, bool HasQualifier,
unsigned NumUnqualifiedLookups, bool HasTemplateKWAndArgsInfo,
unsigned NumTemplateArgs);

/// True if this is an implicit access, i.e. one in which the
/// member being accessed was not written in the source. The source
Expand All @@ -3784,34 +3789,35 @@ class CXXDependentScopeMemberExpr final
bool isArrow() const { return CXXDependentScopeMemberExprBits.IsArrow; }

/// Retrieve the location of the '->' or '.' operator.
SourceLocation getOperatorLoc() const {
return CXXDependentScopeMemberExprBits.OperatorLoc;
SourceLocation getOperatorLoc() const { return OperatorLoc; }

/// Determines whether this member expression had a nested-name-specifier
/// prior to the name of the member, e.g., x->Base::foo.
bool hasQualifier() const {
return CXXDependentScopeMemberExprBits.HasQualifier;
}

/// Retrieve the nested-name-specifier that qualifies the member name.
NestedNameSpecifier *getQualifier() const {
return QualifierLoc.getNestedNameSpecifier();
/// If the member name was qualified, retrieves the nested-name-specifier
/// that precedes the member name, with source-location information.
NestedNameSpecifierLoc getQualifierLoc() const {
if (!hasQualifier())
return NestedNameSpecifierLoc();
return *getTrailingObjects<NestedNameSpecifierLoc>();
}

/// Retrieve the nested-name-specifier that qualifies the member
/// name, with source location information.
NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
/// If the member name was qualified, retrieves the
/// nested-name-specifier that precedes the member name. Otherwise, returns
/// NULL.
NestedNameSpecifier *getQualifier() const {
return getQualifierLoc().getNestedNameSpecifier();
}

/// Retrieve the first part of the nested-name-specifier that was
/// found in the scope of the member access expression when the member access
/// was initially parsed.
///
/// This function only returns a useful result when member access expression
/// uses a qualified member name, e.g., "x.Base::f". Here, the declaration
/// returned by this function describes what was found by unqualified name
/// lookup for the identifier "Base" within the scope of the member access
/// expression itself. At template instantiation time, this information is
/// combined with the results of name lookup into the type of the object
/// expression itself (the class type of x).
NamedDecl *getFirstQualifierFoundInScope() const {
if (!hasFirstQualifierFoundInScope())
return nullptr;
return *getTrailingObjects<NamedDecl *>();
/// Retrieve the declarations found by unqualified lookup for the first
/// component name of the nested-name-specifier, if any.
ArrayRef<DeclAccessPair> unqualified_lookups() const {
if (!getNumUnqualifiedLookups())
return std::nullopt;
return {getTrailingObjects<DeclAccessPair>(), getNumUnqualifiedLookups()};
}

/// Retrieve the name of the member that this expression refers to.
Expand Down
15 changes: 8 additions & 7 deletions clang/include/clang/AST/Stmt.h
Original file line number Diff line number Diff line change
Expand Up @@ -1020,18 +1020,19 @@ class alignas(void *) Stmt {
LLVM_PREFERRED_TYPE(bool)
unsigned IsArrow : 1;

/// True if this member expression used a nested-name-specifier to
/// refer to the member, e.g., "x->Base::f".
LLVM_PREFERRED_TYPE(bool)
unsigned HasQualifier : 1;

/// Whether this member expression has info for explicit template
/// keyword and arguments.
LLVM_PREFERRED_TYPE(bool)
unsigned HasTemplateKWAndArgsInfo : 1;

/// See getFirstQualifierFoundInScope() and the comment listing
/// the trailing objects.
LLVM_PREFERRED_TYPE(bool)
unsigned HasFirstQualifierFoundInScope : 1;

/// The location of the '->' or '.' operator.
SourceLocation OperatorLoc;
/// Number of declarations found by unqualified lookup for the
/// first component name of the nested-name-specifier.
unsigned NumUnqualifiedLookups;
};

class OverloadExprBitfields {
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/AST/Type.h
Original file line number Diff line number Diff line change
Expand Up @@ -2509,6 +2509,7 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase {
bool isFunctionNoProtoType() const { return getAs<FunctionNoProtoType>(); }
bool isFunctionProtoType() const { return getAs<FunctionProtoType>(); }
bool isPointerType() const;
bool isSignableType() const;
bool isAnyPointerType() const; // Any C pointer or ObjC object pointer
bool isCountAttributedType() const;
bool isBlockPointerType() const;
Expand Down Expand Up @@ -8004,6 +8005,8 @@ inline bool Type::isAnyPointerType() const {
return isPointerType() || isObjCObjectPointerType();
}

inline bool Type::isSignableType() const { return isPointerType(); }

inline bool Type::isBlockPointerType() const {
return isa<BlockPointerType>(CanonicalType);
}
Expand Down
4 changes: 4 additions & 0 deletions clang/include/clang/AST/UnresolvedSet.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,10 @@ class UnresolvedSetImpl {
decls().push_back(DeclAccessPair::make(D, AS));
}

void addAllDecls(ArrayRef<DeclAccessPair> Other) {
append(iterator(Other.begin()), iterator(Other.end()));
}

/// Replaces the given declaration with the new one, once.
///
/// \return true if the set changed
Expand Down
12 changes: 12 additions & 0 deletions clang/include/clang/Basic/Attr.td
Original file line number Diff line number Diff line change
Expand Up @@ -4172,6 +4172,18 @@ def LoopHint : Attr {
let HasCustomParsing = 1;
}

/// The HLSL loop attributes
def HLSLLoopHint: StmtAttr {
/// [unroll(directive)]
/// [loop]
let Spellings = [Microsoft<"unroll">, Microsoft<"loop">];
let Args = [UnsignedArgument<"directive", /*opt*/1>];
let Subjects = SubjectList<[ForStmt, WhileStmt, DoStmt],
ErrorDiag, "'for', 'while', and 'do' statements">;
let LangOpts = [HLSL];
let Documentation = [HLSLLoopHintDocs, HLSLUnrollHintDocs];
}

def CapturedRecord : InheritableAttr {
// This attribute has no spellings as it is only ever created implicitly.
let Spellings = [];
Expand Down
99 changes: 97 additions & 2 deletions clang/include/clang/Basic/AttrDocs.td
Original file line number Diff line number Diff line change
Expand Up @@ -7343,6 +7343,100 @@ where shaders must be compiled into a library and linked at runtime.
}];
}

def HLSLLoopHintDocs : Documentation {
let Category = DocCatStmt;
let Heading = "[loop]";
let Content = [{
The ``[loop]`` directive allows loop optimization hints to be
specified for the subsequent loop. The directive allows unrolling to
be disabled and is not compatible with [unroll(x)].

Specifying the parameter, ``[loop]``, directs the
unroller to not unroll the loop.

.. code-block:: hlsl

[loop]
for (...) {
...
}

.. code-block:: hlsl

[loop]
while (...) {
...
}

.. code-block:: hlsl

[loop]
do {
...
} while (...)

See `hlsl loop extensions <https://learn.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-for>`_
for details.
}];
}

def HLSLUnrollHintDocs : Documentation {
let Category = DocCatStmt;
let Heading = "[unroll(x)], [unroll]";
let Content = [{
Loop unrolling optimization hints can be specified with ``[unroll(x)]``
. The attribute is placed immediately before a for, while,
or do-while.
Specifying the parameter, ``[unroll(_value_)]``, directs the
unroller to unroll the loop ``_value_`` times. Note: [unroll(x)] is not compatible with [loop].

.. code-block:: hlsl

[unroll(4)]
for (...) {
...
}

.. code-block:: hlsl

[unroll]
for (...) {
...
}

.. code-block:: hlsl

[unroll(4)]
while (...) {
...
}

.. code-block:: hlsl

[unroll]
while (...) {
...
}

.. code-block:: hlsl

[unroll(4)]
do {
...
} while (...)

.. code-block:: hlsl

[unroll]
do {
...
} while (...)

See `hlsl loop extensions <https://learn.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-for>`_
for details.
}];
}

def ClangRandomizeLayoutDocs : Documentation {
let Category = DocCatDecl;
let Heading = "randomize_layout, no_randomize_layout";
Expand Down Expand Up @@ -7402,7 +7496,8 @@ b for constant buffer views (CBV).

Register space is specified in the format ``space[number]`` and defaults to ``space0`` if omitted.
Here're resource binding examples with and without space:
.. code-block:: c++

.. code-block:: hlsl

RWBuffer<float> Uav : register(u3, space1);
Buffer<float> Buf : register(t1);
Expand All @@ -7420,7 +7515,7 @@ A subcomponent is a register number, which is an integer. A component is in the

Examples:

.. code-block:: c++
.. code-block:: hlsl

cbuffer A {
float3 a : packoffset(c0.y);
Expand Down
7 changes: 3 additions & 4 deletions clang/include/clang/Basic/DiagnosticParseKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -895,10 +895,9 @@ def missing_template_arg_list_after_template_kw : Extension<
"keyword">, InGroup<DiagGroup<"missing-template-arg-list-after-template-kw">>,
DefaultError;

def err_missing_dependent_template_keyword : Error<
"use 'template' keyword to treat '%0' as a dependent template name">;
def warn_missing_dependent_template_keyword : ExtWarn<
"use 'template' keyword to treat '%0' as a dependent template name">;
def ext_missing_dependent_template_keyword : ExtWarn<
"use 'template' keyword to treat '%0' as a dependent template name">,
InGroup<DiagGroup<"missing-dependent-template-keyword">>;

def ext_extern_template : Extension<
"extern templates are a C++11 extension">, InGroup<CXX11>;
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -6016,7 +6016,7 @@ def note_deleted_assign_field : Note<
"because field %2 is of %select{reference|const-qualified}4 type %3">;

// These should be errors.
def warn_undefined_internal : Warning<
def warn_undefined_internal : ExtWarn<
"%select{function|variable}0 %q1 has internal linkage but is not defined">,
InGroup<DiagGroup<"undefined-internal">>;
def err_undefined_internal_type : Error<
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/Features.def
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ FEATURE(ptrauth_vtable_pointer_address_discrimination, LangOpts.PointerAuthVTPtr
FEATURE(ptrauth_vtable_pointer_type_discrimination, LangOpts.PointerAuthVTPtrTypeDiscrimination)
FEATURE(ptrauth_member_function_pointer_type_discrimination, LangOpts.PointerAuthCalls)
FEATURE(ptrauth_init_fini, LangOpts.PointerAuthInitFini)
FEATURE(ptrauth_function_pointer_type_discrimination, LangOpts.PointerAuthFunctionTypeDiscrimination)
EXTENSION(swiftcc,
PP.getTargetInfo().checkCallingConvention(CC_Swift) ==
clang::TargetInfo::CCCR_OK)
Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/Basic/LangOptions.def
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,8 @@ LANGOPT(PointerAuthAuthTraps, 1, 0, "pointer authentication failure traps")
LANGOPT(PointerAuthVTPtrAddressDiscrimination, 1, 0, "incorporate address discrimination in authenticated vtable pointers")
LANGOPT(PointerAuthVTPtrTypeDiscrimination, 1, 0, "incorporate type discrimination in authenticated vtable pointers")
LANGOPT(PointerAuthInitFini, 1, 0, "sign function pointers in init/fini arrays")
BENIGN_LANGOPT(PointerAuthFunctionTypeDiscrimination, 1, 0,
"Use type discrimination when signing function pointers")

LANGOPT(DoubleSquareBracketAttributes, 1, 0, "'[[]]' attributes extension for all language standard modes")
LANGOPT(ExperimentalLateParseAttributes, 1, 0, "experimental late parsing of attributes")
Expand Down
23 changes: 0 additions & 23 deletions clang/include/clang/Basic/TargetInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Frontend/OpenMP/OMPGridValues.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/VersionTuple.h"
Expand Down Expand Up @@ -1410,7 +1408,6 @@ class TargetInfo : public TransferrableTargetInfo,
bool BranchProtectionPAuthLR;
bool GuardedControlStack;

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

public:
BranchProtectionInfo()
: SignReturnAddr(LangOptions::SignReturnAddressScopeKind::None),
SignKey(LangOptions::SignReturnAddressKeyKind::AKey),
Expand All @@ -1454,25 +1450,6 @@ class TargetInfo : public TransferrableTargetInfo,
BranchProtectionPAuthLR = LangOpts.BranchProtectionPAuthLR;
GuardedControlStack = LangOpts.GuardedControlStack;
}

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

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

/// Determine if the Architecture in this TargetInfo supports branch
Expand Down
4 changes: 4 additions & 0 deletions clang/include/clang/CodeGen/CodeGenABITypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,10 @@ unsigned getLLVMFieldNumber(CodeGenModule &CGM,
/// Return a declaration discriminator for the given global decl.
uint16_t getPointerAuthDeclDiscriminator(CodeGenModule &CGM, GlobalDecl GD);

/// Return a type discriminator for the given function type.
uint16_t getPointerAuthTypeDiscriminator(CodeGenModule &CGM,
QualType FunctionType);

/// Given the language and code-generation options that Clang was configured
/// with, set the default LLVM IR attributes for a function definition.
/// The attributes set here are mostly global target-configuration and
Expand Down
5 changes: 5 additions & 0 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -4234,6 +4234,8 @@ defm ptrauth_vtable_pointer_address_discrimination :
defm ptrauth_vtable_pointer_type_discrimination :
OptInCC1FFlag<"ptrauth-vtable-pointer-type-discrimination", "Enable type discrimination of vtable pointers">;
defm ptrauth_init_fini : OptInCC1FFlag<"ptrauth-init-fini", "Enable signing of function pointers in init/fini arrays">;
defm ptrauth_function_pointer_type_discrimination : OptInCC1FFlag<"ptrauth-function-pointer-type-discrimination",
"Enable type discrimination on C function pointers">;
}

def fenable_matrix : Flag<["-"], "fenable-matrix">, Group<f_Group>,
Expand Down Expand Up @@ -6685,6 +6687,9 @@ defm stack_arrays : BoolOptionWithoutMarshalling<"f", "stack-arrays",
defm loop_versioning : BoolOptionWithoutMarshalling<"f", "version-loops-for-stride",
PosFlag<SetTrue, [], [ClangOption], "Create unit-strided versions of loops">,
NegFlag<SetFalse, [], [ClangOption], "Do not create unit-strided loops (default)">>;

def fhermetic_module_files : Flag<["-"], "fhermetic-module-files">, Group<f_Group>,
HelpText<"Emit hermetic module files (no nested USE association)">;
} // let Visibility = [FC1Option, FlangOption]

def J : JoinedOrSeparate<["-"], "J">,
Expand Down
14 changes: 5 additions & 9 deletions clang/include/clang/Parse/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -3368,15 +3368,11 @@ class Parser : public CodeCompletionHandler {
BaseResult ParseBaseSpecifier(Decl *ClassDecl);
AccessSpecifier getAccessSpecifierIfPresent() const;

bool ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
ParsedType ObjectType,
bool ObjectHadErrors,
SourceLocation TemplateKWLoc,
IdentifierInfo *Name,
SourceLocation NameLoc,
bool EnteringContext,
UnqualifiedId &Id,
bool AssumeTemplateId);
bool ParseUnqualifiedIdTemplateId(
CXXScopeSpec &SS, ParsedType ObjectType, bool ObjectHadErrors,
SourceLocation TemplateKWLoc, SourceLocation TildeLoc,
IdentifierInfo *Name, SourceLocation NameLoc, bool EnteringContext,
UnqualifiedId &Id, bool AssumeTemplateId);
bool ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext,
ParsedType ObjectType,
UnqualifiedId &Result);
Expand Down
8 changes: 8 additions & 0 deletions clang/include/clang/Sema/DeclSpec.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ class CXXScopeSpec {
SourceRange Range;
NestedNameSpecifierLocBuilder Builder;
ArrayRef<TemplateParameterList *> TemplateParamLists;
ArrayRef<DeclAccessPair> UnqualifiedLookups;

public:
SourceRange getRange() const { return Range; }
Expand All @@ -91,6 +92,13 @@ class CXXScopeSpec {
return TemplateParamLists;
}

void setUnqualifiedLookups(ArrayRef<DeclAccessPair> Found) {
UnqualifiedLookups = Found;
}
ArrayRef<DeclAccessPair> getUnqualifiedLookups() const {
return UnqualifiedLookups;
}

/// Retrieve the representation of the nested-name-specifier.
NestedNameSpecifier *getScopeRep() const {
return Builder.getRepresentation();
Expand Down
8 changes: 6 additions & 2 deletions clang/include/clang/Sema/Lookup.h
Original file line number Diff line number Diff line change
Expand Up @@ -483,11 +483,15 @@ class LookupResult {
ResultKind = Found;
}

void addAllDecls(ArrayRef<DeclAccessPair> Other) {
Decls.addAllDecls(Other);
ResultKind = Found;
}

/// Add all the declarations from another set of lookup
/// results.
void addAllDecls(const LookupResult &Other) {
Decls.append(Other.Decls.begin(), Other.Decls.end());
ResultKind = Found;
addAllDecls(Other.Decls.pairs());
}

/// Determine whether no result was found because we could not
Expand Down
54 changes: 22 additions & 32 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -2802,7 +2802,8 @@ class Sema final : public SemaBase {
/// (e.g., Base::), perform name lookup for that identifier as a
/// nested-name-specifier within the given scope, and return the result of
/// that name lookup.
NamedDecl *FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS);
bool LookupFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS,
UnresolvedSetImpl &R);

/// Keeps information about an identifier in a nested-name-spec.
///
Expand Down Expand Up @@ -2842,9 +2843,6 @@ class Sema final : public SemaBase {
/// \param EnteringContext If true, enter the context specified by the
/// nested-name-specifier.
/// \param SS Optional nested name specifier preceding the identifier.
/// \param ScopeLookupResult Provides the result of name lookup within the
/// scope of the nested-name-specifier that was computed at template
/// definition time.
/// \param ErrorRecoveryLookup Specifies if the method is called to improve
/// error recovery and what kind of recovery is performed.
/// \param IsCorrectedToColon If not null, suggestion of replace '::' -> ':'
Expand All @@ -2853,11 +2851,6 @@ class Sema final : public SemaBase {
/// not '::'.
/// \param OnlyNamespace If true, only considers namespaces in lookup.
///
/// This routine differs only slightly from ActOnCXXNestedNameSpecifier, in
/// that it contains an extra parameter \p ScopeLookupResult, which provides
/// the result of name lookup within the scope of the nested-name-specifier
/// that was computed at template definition time.
///
/// If ErrorRecoveryLookup is true, then this call is used to improve error
/// recovery. This means that it should not emit diagnostics, it should
/// just return true on failure. It also means it should only return a valid
Expand All @@ -2866,7 +2859,6 @@ class Sema final : public SemaBase {
/// specifier.
bool BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo,
bool EnteringContext, CXXScopeSpec &SS,
NamedDecl *ScopeLookupResult,
bool ErrorRecoveryLookup,
bool *IsCorrectedToColon = nullptr,
bool OnlyNamespace = false);
Expand Down Expand Up @@ -8566,11 +8558,12 @@ class Sema final : public SemaBase {
const TemplateArgumentListInfo *TemplateArgs,
bool IsDefiniteInstance, const Scope *S);

ExprResult ActOnDependentMemberExpr(
Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OpLoc,
const CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
NamedDecl *FirstQualifierInScope, const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *TemplateArgs);
ExprResult
ActOnDependentMemberExpr(Expr *Base, QualType BaseType, bool IsArrow,
SourceLocation OpLoc, const CXXScopeSpec &SS,
SourceLocation TemplateKWLoc,
const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *TemplateArgs);

/// The main callback when the parser finds something like
/// expression . [nested-name-specifier] identifier
Expand Down Expand Up @@ -8626,15 +8619,14 @@ class Sema final : public SemaBase {
ExprResult BuildMemberReferenceExpr(
Expr *Base, QualType BaseType, SourceLocation OpLoc, bool IsArrow,
CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
NamedDecl *FirstQualifierInScope, const DeclarationNameInfo &NameInfo,
const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *TemplateArgs, const Scope *S,
ActOnMemberAccessExtraArgs *ExtraArgs = nullptr);

ExprResult
BuildMemberReferenceExpr(Expr *Base, QualType BaseType, SourceLocation OpLoc,
bool IsArrow, const CXXScopeSpec &SS,
SourceLocation TemplateKWLoc,
NamedDecl *FirstQualifierInScope, LookupResult &R,
SourceLocation TemplateKWLoc, LookupResult &R,
const TemplateArgumentListInfo *TemplateArgs,
const Scope *S, bool SuppressQualifierCheck = false,
ActOnMemberAccessExtraArgs *ExtraArgs = nullptr);
Expand Down Expand Up @@ -11122,15 +11114,14 @@ class Sema final : public SemaBase {
QualType ObjectType, bool EnteringContext,
RequiredTemplateKind RequiredTemplate = SourceLocation(),
AssumedTemplateKind *ATK = nullptr,
bool AllowTypoCorrection = true);
bool AllowTypoCorrection = true, bool MayBeNNS = false);

TemplateNameKind isTemplateName(Scope *S, CXXScopeSpec &SS,
bool hasTemplateKeyword,
const UnqualifiedId &Name,
ParsedType ObjectType, bool EnteringContext,
TemplateTy &Template,
bool &MemberOfUnknownSpecialization,
bool Disambiguation = false);
TemplateNameKind
isTemplateName(Scope *S, CXXScopeSpec &SS, bool hasTemplateKeyword,
const UnqualifiedId &Name, ParsedType ObjectType,
bool EnteringContext, TemplateTy &Template,
bool &MemberOfUnknownSpecialization,
bool Disambiguation = false, bool MayBeNNS = false);

/// Try to resolve an undeclared template name as a type template.
///
Expand Down Expand Up @@ -11459,12 +11450,11 @@ class Sema final : public SemaBase {
/// For example, given "x.MetaFun::template apply", the scope specifier
/// \p SS will be "MetaFun::", \p TemplateKWLoc contains the location
/// of the "template" keyword, and "apply" is the \p Name.
TemplateNameKind ActOnTemplateName(Scope *S, CXXScopeSpec &SS,
SourceLocation TemplateKWLoc,
const UnqualifiedId &Name,
ParsedType ObjectType,
bool EnteringContext, TemplateTy &Template,
bool AllowInjectedClassName = false);
TemplateNameKind
ActOnTemplateName(Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
const UnqualifiedId &Name, ParsedType ObjectType,
bool EnteringContext, TemplateTy &Template,
bool AllowInjectedClassName = false, bool MayBeNNS = false);

DeclResult ActOnClassTemplateSpecialization(
Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc,
Expand Down
279 changes: 279 additions & 0 deletions clang/lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3140,6 +3140,285 @@ ASTContext::getPointerAuthVTablePointerDiscriminator(const CXXRecordDecl *RD) {
return llvm::getPointerAuthStableSipHash(Str);
}

/// Encode a function type for use in the discriminator of a function pointer
/// type. We can't use the itanium scheme for this since C has quite permissive
/// rules for type compatibility that we need to be compatible with.
///
/// Formally, this function associates every function pointer type T with an
/// encoded string E(T). Let the equivalence relation T1 ~ T2 be defined as
/// E(T1) == E(T2). E(T) is part of the ABI of values of type T. C type
/// compatibility requires equivalent treatment under the ABI, so
/// CCompatible(T1, T2) must imply E(T1) == E(T2), that is, CCompatible must be
/// a subset of ~. Crucially, however, it must be a proper subset because
/// CCompatible is not an equivalence relation: for example, int[] is compatible
/// with both int[1] and int[2], but the latter are not compatible with each
/// other. Therefore this encoding function must be careful to only distinguish
/// types if there is no third type with which they are both required to be
/// compatible.
static void encodeTypeForFunctionPointerAuth(const ASTContext &Ctx,
raw_ostream &OS, QualType QT) {
// FIXME: Consider address space qualifiers.
const Type *T = QT.getCanonicalType().getTypePtr();

// FIXME: Consider using the C++ type mangling when we encounter a construct
// that is incompatible with C.

switch (T->getTypeClass()) {
case Type::Atomic:
return encodeTypeForFunctionPointerAuth(
Ctx, OS, cast<AtomicType>(T)->getValueType());

case Type::LValueReference:
OS << "R";
encodeTypeForFunctionPointerAuth(Ctx, OS,
cast<ReferenceType>(T)->getPointeeType());
return;
case Type::RValueReference:
OS << "O";
encodeTypeForFunctionPointerAuth(Ctx, OS,
cast<ReferenceType>(T)->getPointeeType());
return;

case Type::Pointer:
// C11 6.7.6.1p2:
// For two pointer types to be compatible, both shall be identically
// qualified and both shall be pointers to compatible types.
// FIXME: we should also consider pointee types.
OS << "P";
return;

case Type::ObjCObjectPointer:
case Type::BlockPointer:
OS << "P";
return;

case Type::Complex:
OS << "C";
return encodeTypeForFunctionPointerAuth(
Ctx, OS, cast<ComplexType>(T)->getElementType());

case Type::VariableArray:
case Type::ConstantArray:
case Type::IncompleteArray:
case Type::ArrayParameter:
// C11 6.7.6.2p6:
// For two array types to be compatible, both shall have compatible
// element types, and if both size specifiers are present, and are integer
// constant expressions, then both size specifiers shall have the same
// constant value [...]
//
// So since ElemType[N] has to be compatible ElemType[], we can't encode the
// width of the array.
OS << "A";
return encodeTypeForFunctionPointerAuth(
Ctx, OS, cast<ArrayType>(T)->getElementType());

case Type::ObjCInterface:
case Type::ObjCObject:
OS << "<objc_object>";
return;

case Type::Enum:
// C11 6.7.2.2p4:
// Each enumerated type shall be compatible with char, a signed integer
// type, or an unsigned integer type.
//
// So we have to treat enum types as integers.
return encodeTypeForFunctionPointerAuth(
Ctx, OS, cast<EnumType>(T)->getDecl()->getIntegerType());

case Type::FunctionNoProto:
case Type::FunctionProto: {
// C11 6.7.6.3p15:
// For two function types to be compatible, both shall specify compatible
// return types. Moreover, the parameter type lists, if both are present,
// shall agree in the number of parameters and in the use of the ellipsis
// terminator; corresponding parameters shall have compatible types.
//
// That paragraph goes on to describe how unprototyped functions are to be
// handled, which we ignore here. Unprototyped function pointers are hashed
// as though they were prototyped nullary functions since thats probably
// what the user meant. This behavior is non-conforming.
// FIXME: If we add a "custom discriminator" function type attribute we
// should encode functions as their discriminators.
OS << "F";
const auto *FuncType = cast<FunctionType>(T);
encodeTypeForFunctionPointerAuth(Ctx, OS, FuncType->getReturnType());
if (const auto *FPT = dyn_cast<FunctionProtoType>(FuncType)) {
for (QualType Param : FPT->param_types()) {
Param = Ctx.getSignatureParameterType(Param);
encodeTypeForFunctionPointerAuth(Ctx, OS, Param);
}
if (FPT->isVariadic())
OS << "z";
}
OS << "E";
return;
}

case Type::MemberPointer: {
OS << "M";
const auto *MPT = T->getAs<MemberPointerType>();
encodeTypeForFunctionPointerAuth(Ctx, OS, QualType(MPT->getClass(), 0));
encodeTypeForFunctionPointerAuth(Ctx, OS, MPT->getPointeeType());
return;
}
case Type::ExtVector:
case Type::Vector:
OS << "Dv" << Ctx.getTypeSizeInChars(T).getQuantity();
break;

// Don't bother discriminating based on these types.
case Type::Pipe:
case Type::BitInt:
case Type::ConstantMatrix:
OS << "?";
return;

case Type::Builtin: {
const auto *BTy = T->getAs<BuiltinType>();
switch (BTy->getKind()) {
#define SIGNED_TYPE(Id, SingletonId) \
case BuiltinType::Id: \
OS << "i"; \
return;
#define UNSIGNED_TYPE(Id, SingletonId) \
case BuiltinType::Id: \
OS << "i"; \
return;
#define PLACEHOLDER_TYPE(Id, SingletonId) case BuiltinType::Id:
#define BUILTIN_TYPE(Id, SingletonId)
#include "clang/AST/BuiltinTypes.def"
llvm_unreachable("placeholder types should not appear here.");

case BuiltinType::Half:
OS << "Dh";
return;
case BuiltinType::Float:
OS << "f";
return;
case BuiltinType::Double:
OS << "d";
return;
case BuiltinType::LongDouble:
OS << "e";
return;
case BuiltinType::Float16:
OS << "DF16_";
return;
case BuiltinType::Float128:
OS << "g";
return;

case BuiltinType::Void:
OS << "v";
return;

case BuiltinType::ObjCId:
case BuiltinType::ObjCClass:
case BuiltinType::ObjCSel:
case BuiltinType::NullPtr:
OS << "P";
return;

// Don't bother discriminating based on OpenCL types.
case BuiltinType::OCLSampler:
case BuiltinType::OCLEvent:
case BuiltinType::OCLClkEvent:
case BuiltinType::OCLQueue:
case BuiltinType::OCLReserveID:
case BuiltinType::BFloat16:
case BuiltinType::VectorQuad:
case BuiltinType::VectorPair:
OS << "?";
return;

// Don't bother discriminating based on these seldom-used types.
case BuiltinType::Ibm128:
return;
#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
case BuiltinType::Id: \
return;
#include "clang/Basic/OpenCLImageTypes.def"
#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
case BuiltinType::Id: \
return;
#include "clang/Basic/OpenCLExtensionTypes.def"
#define SVE_TYPE(Name, Id, SingletonId) \
case BuiltinType::Id: \
return;
#include "clang/Basic/AArch64SVEACLETypes.def"
case BuiltinType::Dependent:
llvm_unreachable("should never get here");
case BuiltinType::AMDGPUBufferRsrc:
case BuiltinType::WasmExternRef:
#define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
#include "clang/Basic/RISCVVTypes.def"
llvm_unreachable("not yet implemented");
}
}
case Type::Record: {
const RecordDecl *RD = T->getAs<RecordType>()->getDecl();
const IdentifierInfo *II = RD->getIdentifier();

// In C++, an immediate typedef of an anonymous struct or union
// is considered to name it for ODR purposes, but C's specification
// of type compatibility does not have a similar rule. Using the typedef
// name in function type discriminators anyway, as we do here,
// therefore technically violates the C standard: two function pointer
// types defined in terms of two typedef'd anonymous structs with
// different names are formally still compatible, but we are assigning
// them different discriminators and therefore incompatible ABIs.
//
// This is a relatively minor violation that significantly improves
// discrimination in some cases and has not caused problems in
// practice. Regardless, it is now part of the ABI in places where
// function type discrimination is used, and it can no longer be
// changed except on new platforms.

if (!II)
if (const TypedefNameDecl *Typedef = RD->getTypedefNameForAnonDecl())
II = Typedef->getDeclName().getAsIdentifierInfo();

if (!II) {
OS << "<anonymous_record>";
return;
}
OS << II->getLength() << II->getName();
return;
}
case Type::DeducedTemplateSpecialization:
case Type::Auto:
#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
#define DEPENDENT_TYPE(Class, Base) case Type::Class:
#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
#define ABSTRACT_TYPE(Class, Base)
#define TYPE(Class, Base)
#include "clang/AST/TypeNodes.inc"
llvm_unreachable("unexpected non-canonical or dependent type!");
return;
}
}

uint16_t ASTContext::getPointerAuthTypeDiscriminator(QualType T) const {
assert(!T->isDependentType() &&
"cannot compute type discriminator of a dependent type");

SmallString<256> Str;
llvm::raw_svector_ostream Out(Str);

if (T->isFunctionPointerType() || T->isFunctionReferenceType())
T = T->getPointeeType();

if (T->isFunctionType())
encodeTypeForFunctionPointerAuth(*this, Out, T);
else
llvm_unreachable(
"type discrimination of non-function type not implemented yet");

return llvm::getPointerAuthStableSipHash(Str);
}

QualType ASTContext::getObjCGCQualType(QualType T,
Qualifiers::GC GCAttr) const {
QualType CanT = getCanonicalType(T);
Expand Down
12 changes: 9 additions & 3 deletions clang/lib/AST/ASTImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8439,8 +8439,14 @@ ExpectedStmt ASTNodeImporter::VisitCXXDependentScopeMemberExpr(
auto ToOperatorLoc = importChecked(Err, E->getOperatorLoc());
auto ToQualifierLoc = importChecked(Err, E->getQualifierLoc());
auto ToTemplateKeywordLoc = importChecked(Err, E->getTemplateKeywordLoc());
auto ToFirstQualifierFoundInScope =
importChecked(Err, E->getFirstQualifierFoundInScope());

UnresolvedSet<8> ToUnqualifiedLookups;
for (auto D : E->unqualified_lookups())
if (auto ToDOrErr = import(D.getDecl()))
ToUnqualifiedLookups.addDecl(*ToDOrErr);
else
return ToDOrErr.takeError();

if (Err)
return std::move(Err);

Expand Down Expand Up @@ -8474,7 +8480,7 @@ ExpectedStmt ASTNodeImporter::VisitCXXDependentScopeMemberExpr(

return CXXDependentScopeMemberExpr::Create(
Importer.getToContext(), ToBase, ToType, E->isArrow(), ToOperatorLoc,
ToQualifierLoc, ToTemplateKeywordLoc, ToFirstQualifierFoundInScope,
ToQualifierLoc, ToTemplateKeywordLoc, ToUnqualifiedLookups.pairs(),
ToMemberNameInfo, ResInfo);
}

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

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

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

bool Decl::isInNamedModule() const {
return getOwningModule() && getOwningModule()->isNamedModule();
}

static Decl::Kind getKind(const Decl *D) { return D->getKind(); }
static Decl::Kind getKind(const DeclContext *DC) { return DC->getDeclKind(); }

Expand Down
67 changes: 40 additions & 27 deletions clang/lib/AST/ExprCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1489,19 +1489,27 @@ SourceLocation CXXUnresolvedConstructExpr::getBeginLoc() const {
CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(
const ASTContext &Ctx, Expr *Base, QualType BaseType, bool IsArrow,
SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateKWLoc, NamedDecl *FirstQualifierFoundInScope,
SourceLocation TemplateKWLoc, ArrayRef<DeclAccessPair> UnqualifiedLookups,
DeclarationNameInfo MemberNameInfo,
const TemplateArgumentListInfo *TemplateArgs)
: Expr(CXXDependentScopeMemberExprClass, Ctx.DependentTy, VK_LValue,
OK_Ordinary),
Base(Base), BaseType(BaseType), QualifierLoc(QualifierLoc),
MemberNameInfo(MemberNameInfo) {
Base(Base), BaseType(BaseType), MemberNameInfo(MemberNameInfo),
OperatorLoc(OperatorLoc) {
CXXDependentScopeMemberExprBits.IsArrow = IsArrow;
CXXDependentScopeMemberExprBits.HasQualifier = QualifierLoc.hasQualifier();
CXXDependentScopeMemberExprBits.NumUnqualifiedLookups =
UnqualifiedLookups.size();
CXXDependentScopeMemberExprBits.HasTemplateKWAndArgsInfo =
(TemplateArgs != nullptr) || TemplateKWLoc.isValid();
CXXDependentScopeMemberExprBits.HasFirstQualifierFoundInScope =
FirstQualifierFoundInScope != nullptr;
CXXDependentScopeMemberExprBits.OperatorLoc = OperatorLoc;

if (hasQualifier())
new (getTrailingObjects<NestedNameSpecifierLoc>())
NestedNameSpecifierLoc(QualifierLoc);

std::uninitialized_copy_n(UnqualifiedLookups.data(),
UnqualifiedLookups.size(),
getTrailingObjects<DeclAccessPair>());

if (TemplateArgs) {
auto Deps = TemplateArgumentDependence::None;
Expand All @@ -1513,54 +1521,59 @@ CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(
TemplateKWLoc);
}

if (hasFirstQualifierFoundInScope())
*getTrailingObjects<NamedDecl *>() = FirstQualifierFoundInScope;
setDependence(computeDependence(this));
}

CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(
EmptyShell Empty, bool HasTemplateKWAndArgsInfo,
bool HasFirstQualifierFoundInScope)
EmptyShell Empty, bool HasQualifier, unsigned NumUnqualifiedLookups,
bool HasTemplateKWAndArgsInfo)
: Expr(CXXDependentScopeMemberExprClass, Empty) {
CXXDependentScopeMemberExprBits.HasQualifier = HasQualifier;
CXXDependentScopeMemberExprBits.NumUnqualifiedLookups = NumUnqualifiedLookups;
CXXDependentScopeMemberExprBits.HasTemplateKWAndArgsInfo =
HasTemplateKWAndArgsInfo;
CXXDependentScopeMemberExprBits.HasFirstQualifierFoundInScope =
HasFirstQualifierFoundInScope;
}

CXXDependentScopeMemberExpr *CXXDependentScopeMemberExpr::Create(
const ASTContext &Ctx, Expr *Base, QualType BaseType, bool IsArrow,
SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateKWLoc, NamedDecl *FirstQualifierFoundInScope,
SourceLocation TemplateKWLoc, ArrayRef<DeclAccessPair> UnqualifiedLookups,
DeclarationNameInfo MemberNameInfo,
const TemplateArgumentListInfo *TemplateArgs) {
bool HasQualifier = QualifierLoc.hasQualifier();
unsigned NumUnqualifiedLookups = UnqualifiedLookups.size();
assert(!NumUnqualifiedLookups || HasQualifier);
bool HasTemplateKWAndArgsInfo =
(TemplateArgs != nullptr) || TemplateKWLoc.isValid();
unsigned NumTemplateArgs = TemplateArgs ? TemplateArgs->size() : 0;
bool HasFirstQualifierFoundInScope = FirstQualifierFoundInScope != nullptr;

unsigned Size = totalSizeToAlloc<ASTTemplateKWAndArgsInfo,
TemplateArgumentLoc, NamedDecl *>(
HasTemplateKWAndArgsInfo, NumTemplateArgs, HasFirstQualifierFoundInScope);
unsigned Size =
totalSizeToAlloc<NestedNameSpecifierLoc, DeclAccessPair,
ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(
HasQualifier, NumUnqualifiedLookups, HasTemplateKWAndArgsInfo,
NumTemplateArgs);

void *Mem = Ctx.Allocate(Size, alignof(CXXDependentScopeMemberExpr));
return new (Mem) CXXDependentScopeMemberExpr(
Ctx, Base, BaseType, IsArrow, OperatorLoc, QualifierLoc, TemplateKWLoc,
FirstQualifierFoundInScope, MemberNameInfo, TemplateArgs);
UnqualifiedLookups, MemberNameInfo, TemplateArgs);
}

CXXDependentScopeMemberExpr *CXXDependentScopeMemberExpr::CreateEmpty(
const ASTContext &Ctx, bool HasTemplateKWAndArgsInfo,
unsigned NumTemplateArgs, bool HasFirstQualifierFoundInScope) {
assert(NumTemplateArgs == 0 || HasTemplateKWAndArgsInfo);
const ASTContext &Ctx, bool HasQualifier, unsigned NumUnqualifiedLookups,
bool HasTemplateKWAndArgsInfo, unsigned NumTemplateArgs) {
assert(!NumTemplateArgs || HasTemplateKWAndArgsInfo);
assert(!NumUnqualifiedLookups || HasQualifier);

unsigned Size = totalSizeToAlloc<ASTTemplateKWAndArgsInfo,
TemplateArgumentLoc, NamedDecl *>(
HasTemplateKWAndArgsInfo, NumTemplateArgs, HasFirstQualifierFoundInScope);
unsigned Size =
totalSizeToAlloc<NestedNameSpecifierLoc, DeclAccessPair,
ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(
HasQualifier, NumUnqualifiedLookups, HasTemplateKWAndArgsInfo,
NumTemplateArgs);

void *Mem = Ctx.Allocate(Size, alignof(CXXDependentScopeMemberExpr));
return new (Mem) CXXDependentScopeMemberExpr(
EmptyShell(), HasTemplateKWAndArgsInfo, HasFirstQualifierFoundInScope);
return new (Mem) CXXDependentScopeMemberExpr(EmptyShell(), HasQualifier,
NumUnqualifiedLookups,
HasTemplateKWAndArgsInfo);
}

CXXThisExpr *CXXThisExpr::Create(const ASTContext &Ctx, SourceLocation L,
Expand Down
39 changes: 15 additions & 24 deletions clang/lib/AST/ItaniumMangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -594,11 +594,10 @@ class CXXNameMangler {
void mangleMemberExprBase(const Expr *base, bool isArrow);
void mangleMemberExpr(const Expr *base, bool isArrow,
NestedNameSpecifier *qualifier,
NamedDecl *firstQualifierLookup,
ArrayRef<DeclAccessPair> UnqualifiedLookups,
DeclarationName name,
const TemplateArgumentLoc *TemplateArgs,
unsigned NumTemplateArgs,
unsigned knownArity);
unsigned NumTemplateArgs, unsigned knownArity);
void mangleCastExpression(const Expr *E, StringRef CastEncoding);
void mangleInitListElements(const InitListExpr *InitList);
void mangleRequirement(SourceLocation RequiresExprLoc,
Expand Down Expand Up @@ -4496,14 +4495,11 @@ void CXXNameMangler::mangleMemberExprBase(const Expr *Base, bool IsArrow) {
}

/// Mangles a member expression.
void CXXNameMangler::mangleMemberExpr(const Expr *base,
bool isArrow,
NestedNameSpecifier *qualifier,
NamedDecl *firstQualifierLookup,
DeclarationName member,
const TemplateArgumentLoc *TemplateArgs,
unsigned NumTemplateArgs,
unsigned arity) {
void CXXNameMangler::mangleMemberExpr(
const Expr *base, bool isArrow, NestedNameSpecifier *qualifier,
ArrayRef<DeclAccessPair> UnqualifiedLookups, DeclarationName member,
const TemplateArgumentLoc *TemplateArgs, unsigned NumTemplateArgs,
unsigned arity) {
// <expression> ::= dt <expression> <unresolved-name>
// ::= pt <expression> <unresolved-name>
if (base)
Expand Down Expand Up @@ -4985,22 +4981,19 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity,
case Expr::MemberExprClass: {
NotPrimaryExpr();
const MemberExpr *ME = cast<MemberExpr>(E);
mangleMemberExpr(ME->getBase(), ME->isArrow(),
ME->getQualifier(), nullptr,
ME->getMemberDecl()->getDeclName(),
ME->getTemplateArgs(), ME->getNumTemplateArgs(),
Arity);
mangleMemberExpr(ME->getBase(), ME->isArrow(), ME->getQualifier(),
std::nullopt, ME->getMemberDecl()->getDeclName(),
ME->getTemplateArgs(), ME->getNumTemplateArgs(), Arity);
break;
}

case Expr::UnresolvedMemberExprClass: {
NotPrimaryExpr();
const UnresolvedMemberExpr *ME = cast<UnresolvedMemberExpr>(E);
mangleMemberExpr(ME->isImplicitAccess() ? nullptr : ME->getBase(),
ME->isArrow(), ME->getQualifier(), nullptr,
ME->getMemberName(),
ME->getTemplateArgs(), ME->getNumTemplateArgs(),
Arity);
ME->isArrow(), ME->getQualifier(), std::nullopt,
ME->getMemberName(), ME->getTemplateArgs(),
ME->getNumTemplateArgs(), Arity);
break;
}

Expand All @@ -5010,10 +5003,8 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity,
= cast<CXXDependentScopeMemberExpr>(E);
mangleMemberExpr(ME->isImplicitAccess() ? nullptr : ME->getBase(),
ME->isArrow(), ME->getQualifier(),
ME->getFirstQualifierFoundInScope(),
ME->getMember(),
ME->getTemplateArgs(), ME->getNumTemplateArgs(),
Arity);
ME->unqualified_lookups(), ME->getMember(),
ME->getTemplateArgs(), ME->getNumTemplateArgs(), Arity);
break;
}

Expand Down
1 change: 0 additions & 1 deletion clang/lib/Basic/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,6 @@ add_clang_library(clangBasic
Targets/DirectX.cpp
Targets/Hexagon.cpp
Targets/Lanai.cpp
Targets/Le64.cpp
Targets/LoongArch.cpp
Targets/M68k.cpp
Targets/MSP430.cpp
Expand Down
12 changes: 0 additions & 12 deletions clang/lib/Basic/Targets.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
#include "Targets/DirectX.h"
#include "Targets/Hexagon.h"
#include "Targets/Lanai.h"
#include "Targets/Le64.h"
#include "Targets/LoongArch.h"
#include "Targets/M68k.h"
#include "Targets/MSP430.h"
Expand Down Expand Up @@ -344,17 +343,6 @@ std::unique_ptr<TargetInfo> AllocateTarget(const llvm::Triple &Triple,
return std::make_unique<M68kTargetInfo>(Triple, Opts);
}

case llvm::Triple::le32:
switch (os) {
case llvm::Triple::NaCl:
return std::make_unique<NaClTargetInfo<PNaClTargetInfo>>(Triple, Opts);
default:
return nullptr;
}

case llvm::Triple::le64:
return std::make_unique<Le64TargetInfo>(Triple, Opts);

case llvm::Triple::ppc:
switch (os) {
case llvm::Triple::Linux:
Expand Down
30 changes: 0 additions & 30 deletions clang/lib/Basic/Targets/Le64.cpp

This file was deleted.

64 changes: 0 additions & 64 deletions clang/lib/Basic/Targets/Le64.h

This file was deleted.

3 changes: 0 additions & 3 deletions clang/lib/Basic/Targets/OSTargets.h
Original file line number Diff line number Diff line change
Expand Up @@ -841,9 +841,6 @@ class LLVM_LIBRARY_VISIBILITY NaClTargetInfo : public OSTargetInfo<Target> {
"i64:64-i128:128-n8:16:32:64-S128");
} else if (Triple.getArch() == llvm::Triple::mipsel) {
// Handled on mips' setDataLayout.
} else {
assert(Triple.getArch() == llvm::Triple::le32);
this->resetDataLayout("e-p:32:32-i64:64");
}
}
};
Expand Down
32 changes: 23 additions & 9 deletions clang/lib/CodeGen/CGExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1542,9 +1542,11 @@ ConstantEmitter::emitAbstract(const Expr *E, QualType destType) {

llvm::Constant *
ConstantEmitter::emitAbstract(SourceLocation loc, const APValue &value,
QualType destType) {
QualType destType,
bool EnablePtrAuthFunctionTypeDiscrimination) {
auto state = pushAbstract();
auto C = tryEmitPrivate(value, destType);
auto C =
tryEmitPrivate(value, destType, EnablePtrAuthFunctionTypeDiscrimination);
C = validateAndPopAbstract(C, state);
if (!C) {
CGM.Error(loc,
Expand Down Expand Up @@ -1938,14 +1940,18 @@ class ConstantLValueEmitter : public ConstStmtVisitor<ConstantLValueEmitter,
ConstantEmitter &Emitter;
const APValue &Value;
QualType DestType;
bool EnablePtrAuthFunctionTypeDiscrimination;

// Befriend StmtVisitorBase so that we don't have to expose Visit*.
friend StmtVisitorBase;

public:
ConstantLValueEmitter(ConstantEmitter &emitter, const APValue &value,
QualType destType)
: CGM(emitter.CGM), Emitter(emitter), Value(value), DestType(destType) {}
QualType destType,
bool EnablePtrAuthFunctionTypeDiscrimination = true)
: CGM(emitter.CGM), Emitter(emitter), Value(value), DestType(destType),
EnablePtrAuthFunctionTypeDiscrimination(
EnablePtrAuthFunctionTypeDiscrimination) {}

llvm::Constant *tryEmit();

Expand Down Expand Up @@ -2069,7 +2075,10 @@ ConstantLValueEmitter::tryEmitBase(const APValue::LValueBase &base) {
return CGM.GetWeakRefReference(D).getPointer();

auto PtrAuthSign = [&](llvm::Constant *C) {
CGPointerAuthInfo AuthInfo = CGM.getFunctionPointerAuthInfo(DestType);
CGPointerAuthInfo AuthInfo;

if (EnablePtrAuthFunctionTypeDiscrimination)
AuthInfo = CGM.getFunctionPointerAuthInfo(DestType);

if (AuthInfo) {
if (hasNonZeroOffset())
Expand Down Expand Up @@ -2220,8 +2229,10 @@ llvm::Constant *ConstantLValueEmitter::emitPointerAuthPointer(const Expr *E) {

// The assertions here are all checked by Sema.
assert(Result.Val.isLValue());
if (isa<FunctionDecl>(Result.Val.getLValueBase().get<const ValueDecl *>()))
assert(Result.Val.getLValueOffset().isZero());
return ConstantEmitter(CGM, Emitter.CGF)
.emitAbstract(E->getExprLoc(), Result.Val, E->getType());
.emitAbstract(E->getExprLoc(), Result.Val, E->getType(), false);
}

unsigned ConstantLValueEmitter::emitPointerAuthKey(const Expr *E) {
Expand Down Expand Up @@ -2278,15 +2289,18 @@ ConstantLValueEmitter::VisitMaterializeTemporaryExpr(
return CGM.GetAddrOfGlobalTemporary(E, Inner);
}

llvm::Constant *ConstantEmitter::tryEmitPrivate(const APValue &Value,
QualType DestType) {
llvm::Constant *
ConstantEmitter::tryEmitPrivate(const APValue &Value, QualType DestType,
bool EnablePtrAuthFunctionTypeDiscrimination) {
switch (Value.getKind()) {
case APValue::None:
case APValue::Indeterminate:
// Out-of-lifetime and indeterminate values can be modeled as 'undef'.
return llvm::UndefValue::get(CGM.getTypes().ConvertType(DestType));
case APValue::LValue:
return ConstantLValueEmitter(*this, Value, DestType).tryEmit();
return ConstantLValueEmitter(*this, Value, DestType,
EnablePtrAuthFunctionTypeDiscrimination)
.tryEmit();
case APValue::Int:
return llvm::ConstantInt::get(CGM.getLLVMContext(), Value.getInt());
case APValue::FixedPoint:
Expand Down
15 changes: 13 additions & 2 deletions clang/lib/CodeGen/CGLoopInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -612,9 +612,9 @@ void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx,
const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(Attr);
const OpenCLUnrollHintAttr *OpenCLHint =
dyn_cast<OpenCLUnrollHintAttr>(Attr);

const HLSLLoopHintAttr *HLSLLoopHint = dyn_cast<HLSLLoopHintAttr>(Attr);
// Skip non loop hint attributes
if (!LH && !OpenCLHint) {
if (!LH && !OpenCLHint && !HLSLLoopHint) {
continue;
}

Expand All @@ -635,6 +635,17 @@ void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx,
Option = LoopHintAttr::UnrollCount;
State = LoopHintAttr::Numeric;
}
} else if (HLSLLoopHint) {
ValueInt = HLSLLoopHint->getDirective();
if (HLSLLoopHint->getSemanticSpelling() ==
HLSLLoopHintAttr::Spelling::Microsoft_unroll) {
if (ValueInt == 0)
State = LoopHintAttr::Enable;
if (ValueInt > 0) {
Option = LoopHintAttr::UnrollCount;
State = LoopHintAttr::Numeric;
}
}
} else if (LH) {
auto *ValueExpr = LH->getValue();
if (ValueExpr) {
Expand Down
67 changes: 63 additions & 4 deletions clang/lib/CodeGen/CGPointerAuth.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ llvm::ConstantInt *CodeGenModule::getPointerAuthOtherDiscriminator(
return nullptr;

case PointerAuthSchema::Discrimination::Type:
llvm_unreachable("type discrimination not implemented yet");
assert(!Type.isNull() && "type not provided for type-discriminated schema");
return llvm::ConstantInt::get(
IntPtrTy, getContext().getPointerAuthTypeDiscriminator(Type));

case PointerAuthSchema::Discrimination::Decl:
assert(Decl.getDecl() &&
Expand All @@ -43,6 +45,11 @@ llvm::ConstantInt *CodeGenModule::getPointerAuthOtherDiscriminator(
llvm_unreachable("bad discrimination kind");
}

uint16_t CodeGen::getPointerAuthTypeDiscriminator(CodeGenModule &CGM,
QualType FunctionType) {
return CGM.getContext().getPointerAuthTypeDiscriminator(FunctionType);
}

uint16_t CodeGen::getPointerAuthDeclDiscriminator(CodeGenModule &CGM,
GlobalDecl Declaration) {
return CGM.getPointerAuthDeclDiscriminator(Declaration);
Expand Down Expand Up @@ -71,12 +78,15 @@ CGPointerAuthInfo CodeGenModule::getFunctionPointerAuthInfo(QualType T) {
assert(!Schema.isAddressDiscriminated() &&
"function pointers cannot use address-specific discrimination");

assert(!Schema.hasOtherDiscrimination() &&
"function pointers don't support any discrimination yet");
llvm::Constant *Discriminator = nullptr;
if (T->isFunctionPointerType() || T->isFunctionReferenceType())
T = T->getPointeeType();
if (T->isFunctionType())
Discriminator = getPointerAuthOtherDiscriminator(Schema, GlobalDecl(), T);

return CGPointerAuthInfo(Schema.getKey(), Schema.getAuthenticationMode(),
/*IsaPointer=*/false, /*AuthenticatesNull=*/false,
/*Discriminator=*/nullptr);
Discriminator);
}

llvm::Value *
Expand Down Expand Up @@ -114,6 +124,47 @@ CGPointerAuthInfo CodeGenFunction::EmitPointerAuthInfo(
Schema.authenticatesNullValues(), Discriminator);
}

/// Return the natural pointer authentication for values of the given
/// pointee type.
static CGPointerAuthInfo
getPointerAuthInfoForPointeeType(CodeGenModule &CGM, QualType PointeeType) {
if (PointeeType.isNull())
return CGPointerAuthInfo();

// Function pointers use the function-pointer schema by default.
if (PointeeType->isFunctionType())
return CGM.getFunctionPointerAuthInfo(PointeeType);

// Normal data pointers never use direct pointer authentication by default.
return CGPointerAuthInfo();
}

CGPointerAuthInfo CodeGenModule::getPointerAuthInfoForPointeeType(QualType T) {
return ::getPointerAuthInfoForPointeeType(*this, T);
}

/// Return the natural pointer authentication for values of the given
/// pointer type.
static CGPointerAuthInfo getPointerAuthInfoForType(CodeGenModule &CGM,
QualType PointerType) {
assert(PointerType->isSignableType());

// Block pointers are currently not signed.
if (PointerType->isBlockPointerType())
return CGPointerAuthInfo();

auto PointeeType = PointerType->getPointeeType();

if (PointeeType.isNull())
return CGPointerAuthInfo();

return ::getPointerAuthInfoForPointeeType(CGM, PointeeType);
}

CGPointerAuthInfo CodeGenModule::getPointerAuthInfoForType(QualType T) {
return ::getPointerAuthInfoForType(*this, T);
}

llvm::Constant *
CodeGenModule::getConstantSignedPointer(llvm::Constant *Pointer, unsigned Key,
llvm::Constant *StorageAddress,
Expand Down Expand Up @@ -180,6 +231,14 @@ llvm::Constant *CodeGenModule::getFunctionPointer(GlobalDecl GD,
llvm::Type *Ty) {
const auto *FD = cast<FunctionDecl>(GD.getDecl());
QualType FuncType = FD->getType();

// Annoyingly, K&R functions have prototypes in the clang AST, but
// expressions referring to them are unprototyped.
if (!FD->hasPrototype())
if (const auto *Proto = FuncType->getAs<FunctionProtoType>())
FuncType = Context.getFunctionNoProtoType(Proto->getReturnType(),
Proto->getExtInfo());

return getFunctionPointer(getRawFunctionPointer(GD, Ty), FuncType);
}

Expand Down
46 changes: 24 additions & 22 deletions clang/lib/CodeGen/CodeGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,6 @@ createTargetCodeGenInfo(CodeGenModule &CGM) {
default:
return createDefaultTargetCodeGenInfo(CGM);

case llvm::Triple::le32:
return createPNaClTargetCodeGenInfo(CGM);
case llvm::Triple::m68k:
return createM68kTargetCodeGenInfo(CGM);
case llvm::Triple::mips:
Expand Down Expand Up @@ -3702,6 +3700,19 @@ template <typename AttrT> static bool hasImplicitAttr(const ValueDecl *D) {
return D->isImplicit();
}

bool CodeGenModule::shouldEmitCUDAGlobalVar(const VarDecl *Global) const {
assert(LangOpts.CUDA && "Should not be called by non-CUDA languages");
// We need to emit host-side 'shadows' for all global
// device-side variables because the CUDA runtime needs their
// size and host-side address in order to provide access to
// their device-side incarnations.
return !LangOpts.CUDAIsDevice || Global->hasAttr<CUDADeviceAttr>() ||
Global->hasAttr<CUDAConstantAttr>() ||
Global->hasAttr<CUDASharedAttr>() ||
Global->getType()->isCUDADeviceBuiltinSurfaceType() ||
Global->getType()->isCUDADeviceBuiltinTextureType();
}

void CodeGenModule::EmitGlobal(GlobalDecl GD) {
const auto *Global = cast<ValueDecl>(GD.getDecl());

Expand All @@ -3726,36 +3737,27 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) {
// Non-constexpr non-lambda implicit host device functions are not emitted
// unless they are used on device side.
if (LangOpts.CUDA) {
if (LangOpts.CUDAIsDevice) {
assert((isa<FunctionDecl>(Global) || isa<VarDecl>(Global)) &&
"Expected Variable or Function");
if (const auto *VD = dyn_cast<VarDecl>(Global)) {
if (!shouldEmitCUDAGlobalVar(VD))
return;
} else if (LangOpts.CUDAIsDevice) {
const auto *FD = dyn_cast<FunctionDecl>(Global);
if ((!Global->hasAttr<CUDADeviceAttr>() ||
(LangOpts.OffloadImplicitHostDeviceTemplates && FD &&
(LangOpts.OffloadImplicitHostDeviceTemplates &&
hasImplicitAttr<CUDAHostAttr>(FD) &&
hasImplicitAttr<CUDADeviceAttr>(FD) && !FD->isConstexpr() &&
!isLambdaCallOperator(FD) &&
!getContext().CUDAImplicitHostDeviceFunUsedByDevice.count(FD))) &&
!Global->hasAttr<CUDAGlobalAttr>() &&
!Global->hasAttr<CUDAConstantAttr>() &&
!Global->hasAttr<CUDASharedAttr>() &&
!Global->getType()->isCUDADeviceBuiltinSurfaceType() &&
!Global->getType()->isCUDADeviceBuiltinTextureType() &&
!(LangOpts.HIPStdPar && isa<FunctionDecl>(Global) &&
!Global->hasAttr<CUDAHostAttr>()))
return;
} else {
// We need to emit host-side 'shadows' for all global
// device-side variables because the CUDA runtime needs their
// size and host-side address in order to provide access to
// their device-side incarnations.

// So device-only functions are the only things we skip.
if (isa<FunctionDecl>(Global) && !Global->hasAttr<CUDAHostAttr>() &&
Global->hasAttr<CUDADeviceAttr>())
return;

assert((isa<FunctionDecl>(Global) || isa<VarDecl>(Global)) &&
"Expected Variable or Function");
}
// Device-only functions are the only things we skip.
} else if (!Global->hasAttr<CUDAHostAttr>() &&
Global->hasAttr<CUDADeviceAttr>())
return;
}

if (LangOpts.OpenMP) {
Expand Down
7 changes: 7 additions & 0 deletions clang/lib/CodeGen/CodeGenModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -563,6 +563,9 @@ class CodeGenModule : public CodeGenTypeCache {

bool isTriviallyRecursive(const FunctionDecl *F);
bool shouldEmitFunction(GlobalDecl GD);
// Whether a global variable should be emitted by CUDA/HIP host/device
// related attributes.
bool shouldEmitCUDAGlobalVar(const VarDecl *VD) const;
bool shouldOpportunisticallyEmitVTables();
/// Map used to be sure we don't emit the same CompoundLiteral twice.
llvm::DenseMap<const CompoundLiteralExpr *, llvm::GlobalVariable *>
Expand Down Expand Up @@ -972,6 +975,10 @@ class CodeGenModule : public CodeGenTypeCache {

CGPointerAuthInfo getFunctionPointerAuthInfo(QualType T);

CGPointerAuthInfo getPointerAuthInfoForPointeeType(QualType type);

CGPointerAuthInfo getPointerAuthInfoForType(QualType type);

bool shouldSignPointer(const PointerAuthSchema &Schema);
llvm::Constant *getConstantSignedPointer(llvm::Constant *Pointer,
const PointerAuthSchema &Schema,
Expand Down
9 changes: 6 additions & 3 deletions clang/lib/CodeGen/ConstantEmitter.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,9 @@ class ConstantEmitter {
/// expression is known to be a constant expression with either a fairly
/// simple type or a known simple form.
llvm::Constant *emitAbstract(const Expr *E, QualType T);
llvm::Constant *emitAbstract(SourceLocation loc, const APValue &value,
QualType T);
llvm::Constant *
emitAbstract(SourceLocation loc, const APValue &value, QualType T,
bool EnablePtrAuthFunctionTypeDiscrimination = true);

/// Try to emit the result of the given expression as an abstract constant.
llvm::Constant *tryEmitAbstract(const Expr *E, QualType T);
Expand Down Expand Up @@ -138,7 +139,9 @@ class ConstantEmitter {
llvm::Constant *tryEmitPrivate(const Expr *E, QualType T);
llvm::Constant *tryEmitPrivateForMemory(const Expr *E, QualType T);

llvm::Constant *tryEmitPrivate(const APValue &value, QualType T);
llvm::Constant *
tryEmitPrivate(const APValue &value, QualType T,
bool EnablePtrAuthFunctionTypeDiscrimination = true);
llvm::Constant *tryEmitPrivateForMemory(const APValue &value, QualType T);

/// Get the address of the current location. This is a constant
Expand Down
7 changes: 0 additions & 7 deletions clang/lib/CodeGen/ItaniumCXXABI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -576,13 +576,6 @@ CodeGen::CGCXXABI *CodeGen::CreateItaniumCXXABI(CodeGenModule &CGM) {
return new XLCXXABI(CGM);

case TargetCXXABI::GenericItanium:
if (CGM.getContext().getTargetInfo().getTriple().getArch()
== llvm::Triple::le32) {
// For PNaCl, use ARM-style method pointers so that PNaCl code
// does not assume anything about the alignment of function
// pointers.
return new ItaniumCXXABI(CGM, /*UseARMMethodPtrABI=*/true);
}
return new ItaniumCXXABI(CGM);

case TargetCXXABI::Microsoft:
Expand Down
22 changes: 22 additions & 0 deletions clang/lib/CodeGen/TargetInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "clang/CodeGen/CGFunctionInfo.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Twine.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Type.h"
#include "llvm/Support/raw_ostream.h"

Expand Down Expand Up @@ -206,6 +207,27 @@ llvm::Value *TargetCodeGenInfo::createEnqueuedBlockKernel(
return F;
}

void TargetCodeGenInfo::setBranchProtectionFnAttributes(
const TargetInfo::BranchProtectionInfo &BPI, llvm::Function &F) {
llvm::AttrBuilder FuncAttrs(F.getContext());
setBranchProtectionFnAttributes(BPI, FuncAttrs);
F.addFnAttrs(FuncAttrs);
}

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

namespace {
class DefaultTargetCodeGenInfo : public TargetCodeGenInfo {
public:
Expand Down
11 changes: 10 additions & 1 deletion clang/lib/CodeGen/TargetInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@
#define LLVM_CLANG_LIB_CODEGEN_TARGETINFO_H

#include "CGBuilder.h"
#include "CodeGenModule.h"
#include "CGValue.h"
#include "CodeGenModule.h"
#include "clang/AST/Type.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/SyncScope.h"
#include "clang/Basic/TargetInfo.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"

Expand Down Expand Up @@ -413,6 +414,14 @@ class TargetCodeGenInfo {
return nullptr;
}

static void
setBranchProtectionFnAttributes(const TargetInfo::BranchProtectionInfo &BPI,
llvm::Function &F);

static void
setBranchProtectionFnAttributes(const TargetInfo::BranchProtectionInfo &BPI,
llvm::AttrBuilder &FuncAttrs);

protected:
static std::string qualifyWindowsLibrary(StringRef Lib);

Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CodeGen/Targets/AArch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ class AArch64TargetCodeGenInfo : public TargetCodeGenInfo {
}
}
auto *Fn = cast<llvm::Function>(GV);
BPI.setFnAttributes(*Fn);
setBranchProtectionFnAttributes(BPI, *Fn);
}

bool isScalarizableAsmOperand(CodeGen::CodeGenFunction &CGF,
Expand Down
7 changes: 3 additions & 4 deletions clang/lib/CodeGen/Targets/ARM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,9 +151,8 @@ class ARMTargetCodeGenInfo : public TargetCodeGenInfo {
D->getLocation(),
diag::warn_target_unsupported_branch_protection_attribute)
<< Arch;
} else {
BPI.setFnAttributes(*Fn);
}
} else
setBranchProtectionFnAttributes(BPI, (*Fn));
} else if (CGM.getLangOpts().BranchTargetEnforcement ||
CGM.getLangOpts().hasSignReturnAddress()) {
// If the Branch Protection attribute is missing, validate the target
Expand All @@ -168,7 +167,7 @@ class ARMTargetCodeGenInfo : public TargetCodeGenInfo {
} else if (CGM.getTarget().isBranchProtectionSupportedArch(
CGM.getTarget().getTargetOpts().CPU)) {
TargetInfo::BranchProtectionInfo BPI(CGM.getLangOpts());
BPI.setFnAttributes(*Fn);
setBranchProtectionFnAttributes(BPI, (*Fn));
}

const ARMInterruptAttr *Attr = FD->getAttr<ARMInterruptAttr>();
Expand Down
9 changes: 3 additions & 6 deletions clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1789,6 +1789,9 @@ void Clang::AddAArch64TargetArgs(const ArgList &Args,
options::OPT_fno_ptrauth_vtable_pointer_type_discrimination);
Args.addOptInFlag(CmdArgs, options::OPT_fptrauth_init_fini,
options::OPT_fno_ptrauth_init_fini);
Args.addOptInFlag(
CmdArgs, options::OPT_fptrauth_function_pointer_type_discrimination,
options::OPT_fno_ptrauth_function_pointer_type_discrimination);
}

void Clang::AddLoongArchTargetArgs(const ArgList &Args,
Expand Down Expand Up @@ -3812,12 +3815,6 @@ static void RenderBuiltinOptions(const ToolChain &TC, const llvm::Triple &T,
if (UseBuiltins)
A->render(Args, CmdArgs);
}

// le32-specific flags:
// -fno-math-builtin: clang should not convert math builtins to intrinsics
// by default.
if (TC.getArch() == llvm::Triple::le32)
CmdArgs.push_back("-fno-math-builtin");
}

bool Driver::getDefaultModuleCachePath(SmallVectorImpl<char> &Result) {
Expand Down
32 changes: 20 additions & 12 deletions clang/lib/Driver/ToolChains/Flang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,26 @@ static void addDashXForInput(const ArgList &Args, const InputInfo &Input,

void Flang::addFortranDialectOptions(const ArgList &Args,
ArgStringList &CmdArgs) const {
Args.addAllArgs(
CmdArgs, {options::OPT_ffixed_form, options::OPT_ffree_form,
options::OPT_ffixed_line_length_EQ, options::OPT_fopenacc,
options::OPT_finput_charset_EQ, options::OPT_fimplicit_none,
options::OPT_fno_implicit_none, options::OPT_fbackslash,
options::OPT_fno_backslash, options::OPT_flogical_abbreviations,
options::OPT_fno_logical_abbreviations,
options::OPT_fxor_operator, options::OPT_fno_xor_operator,
options::OPT_falternative_parameter_statement,
options::OPT_fdefault_real_8, options::OPT_fdefault_integer_8,
options::OPT_fdefault_double_8, options::OPT_flarge_sizes,
options::OPT_fno_automatic});
Args.addAllArgs(CmdArgs, {options::OPT_ffixed_form,
options::OPT_ffree_form,
options::OPT_ffixed_line_length_EQ,
options::OPT_fopenacc,
options::OPT_finput_charset_EQ,
options::OPT_fimplicit_none,
options::OPT_fno_implicit_none,
options::OPT_fbackslash,
options::OPT_fno_backslash,
options::OPT_flogical_abbreviations,
options::OPT_fno_logical_abbreviations,
options::OPT_fxor_operator,
options::OPT_fno_xor_operator,
options::OPT_falternative_parameter_statement,
options::OPT_fdefault_real_8,
options::OPT_fdefault_integer_8,
options::OPT_fdefault_double_8,
options::OPT_flarge_sizes,
options::OPT_fno_automatic,
options::OPT_fhermetic_module_files});
}

void Flang::addPreprocessingOptions(const ArgList &Args,
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Format/WhitespaceManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1116,7 +1116,7 @@ void WhitespaceManager::alignTrailingComments() {
// leave the comments.
if (RestoredLineLength >= Style.ColumnLimit && Style.ColumnLimit > 0)
break;
C.Spaces = OriginalSpaces;
C.Spaces = C.NewlinesBefore > 0 ? C.Tok->OriginalColumn : OriginalSpaces;
continue;
}

Expand Down
10 changes: 8 additions & 2 deletions clang/lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1479,8 +1479,10 @@ void CompilerInvocation::setDefaultPointerAuthOptions(
using Key = PointerAuthSchema::ARM8_3Key;
using Discrimination = PointerAuthSchema::Discrimination;
// If you change anything here, be sure to update <ptrauth.h>.
Opts.FunctionPointers =
PointerAuthSchema(Key::ASIA, false, Discrimination::None);
Opts.FunctionPointers = PointerAuthSchema(
Key::ASIA, false,
LangOpts.PointerAuthFunctionTypeDiscrimination ? Discrimination::Type
: Discrimination::None);

Opts.CXXVTablePointers = PointerAuthSchema(
Key::ASDA, LangOpts.PointerAuthVTPtrAddressDiscrimination,
Expand Down Expand Up @@ -3411,6 +3413,8 @@ static void GeneratePointerAuthArgs(const LangOptions &Opts,
GenerateArg(Consumer, OPT_fptrauth_vtable_pointer_type_discrimination);
if (Opts.PointerAuthInitFini)
GenerateArg(Consumer, OPT_fptrauth_init_fini);
if (Opts.PointerAuthFunctionTypeDiscrimination)
GenerateArg(Consumer, OPT_fptrauth_function_pointer_type_discrimination);
}

static void ParsePointerAuthArgs(LangOptions &Opts, ArgList &Args,
Expand All @@ -3424,6 +3428,8 @@ static void ParsePointerAuthArgs(LangOptions &Opts, ArgList &Args,
Opts.PointerAuthVTPtrTypeDiscrimination =
Args.hasArg(OPT_fptrauth_vtable_pointer_type_discrimination);
Opts.PointerAuthInitFini = Args.hasArg(OPT_fptrauth_init_fini);
Opts.PointerAuthFunctionTypeDiscrimination =
Args.hasArg(OPT_fptrauth_function_pointer_type_discrimination);
}

/// Check if input file kind and language standard are compatible.
Expand Down
76 changes: 38 additions & 38 deletions clang/lib/Headers/avx512fp16intrin.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,8 @@ _mm512_set_ph(_Float16 __h1, _Float16 __h2, _Float16 __h3, _Float16 __h4,
(h5), (h4), (h3), (h2), (h1))

static __inline __m512h __DEFAULT_FN_ATTRS512
_mm512_set1_pch(_Float16 _Complex h) {
return (__m512h)_mm512_set1_ps(__builtin_bit_cast(float, h));
_mm512_set1_pch(_Float16 _Complex __h) {
return (__m512h)_mm512_set1_ps(__builtin_bit_cast(float, __h));
}

static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_castph_ps(__m128h __a) {
Expand Down Expand Up @@ -282,75 +282,75 @@ _mm512_zextph256_ph512(__m256h __a) {
#define _mm_comi_sh(A, B, pred) \
_mm_comi_round_sh((A), (B), (pred), _MM_FROUND_CUR_DIRECTION)

static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comieq_sh(__m128h A,
__m128h B) {
return __builtin_ia32_vcomish((__v8hf)A, (__v8hf)B, _CMP_EQ_OS,
static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comieq_sh(__m128h __A,
__m128h __B) {
return __builtin_ia32_vcomish((__v8hf)__A, (__v8hf)__B, _CMP_EQ_OS,
_MM_FROUND_CUR_DIRECTION);
}

static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comilt_sh(__m128h A,
__m128h B) {
return __builtin_ia32_vcomish((__v8hf)A, (__v8hf)B, _CMP_LT_OS,
static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comilt_sh(__m128h __A,
__m128h __B) {
return __builtin_ia32_vcomish((__v8hf)__A, (__v8hf)__B, _CMP_LT_OS,
_MM_FROUND_CUR_DIRECTION);
}

static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comile_sh(__m128h A,
__m128h B) {
return __builtin_ia32_vcomish((__v8hf)A, (__v8hf)B, _CMP_LE_OS,
static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comile_sh(__m128h __A,
__m128h __B) {
return __builtin_ia32_vcomish((__v8hf)__A, (__v8hf)__B, _CMP_LE_OS,
_MM_FROUND_CUR_DIRECTION);
}

static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comigt_sh(__m128h A,
__m128h B) {
return __builtin_ia32_vcomish((__v8hf)A, (__v8hf)B, _CMP_GT_OS,
static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comigt_sh(__m128h __A,
__m128h __B) {
return __builtin_ia32_vcomish((__v8hf)__A, (__v8hf)__B, _CMP_GT_OS,
_MM_FROUND_CUR_DIRECTION);
}

static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comige_sh(__m128h A,
__m128h B) {
return __builtin_ia32_vcomish((__v8hf)A, (__v8hf)B, _CMP_GE_OS,
static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comige_sh(__m128h __A,
__m128h __B) {
return __builtin_ia32_vcomish((__v8hf)__A, (__v8hf)__B, _CMP_GE_OS,
_MM_FROUND_CUR_DIRECTION);
}

static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comineq_sh(__m128h A,
__m128h B) {
return __builtin_ia32_vcomish((__v8hf)A, (__v8hf)B, _CMP_NEQ_US,
static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comineq_sh(__m128h __A,
__m128h __B) {
return __builtin_ia32_vcomish((__v8hf)__A, (__v8hf)__B, _CMP_NEQ_US,
_MM_FROUND_CUR_DIRECTION);
}

static __inline__ int __DEFAULT_FN_ATTRS128 _mm_ucomieq_sh(__m128h A,
__m128h B) {
return __builtin_ia32_vcomish((__v8hf)A, (__v8hf)B, _CMP_EQ_OQ,
static __inline__ int __DEFAULT_FN_ATTRS128 _mm_ucomieq_sh(__m128h __A,
__m128h __B) {
return __builtin_ia32_vcomish((__v8hf)__A, (__v8hf)__B, _CMP_EQ_OQ,
_MM_FROUND_CUR_DIRECTION);
}

static __inline__ int __DEFAULT_FN_ATTRS128 _mm_ucomilt_sh(__m128h A,
__m128h B) {
return __builtin_ia32_vcomish((__v8hf)A, (__v8hf)B, _CMP_LT_OQ,
static __inline__ int __DEFAULT_FN_ATTRS128 _mm_ucomilt_sh(__m128h __A,
__m128h __B) {
return __builtin_ia32_vcomish((__v8hf)__A, (__v8hf)__B, _CMP_LT_OQ,
_MM_FROUND_CUR_DIRECTION);
}

static __inline__ int __DEFAULT_FN_ATTRS128 _mm_ucomile_sh(__m128h A,
__m128h B) {
return __builtin_ia32_vcomish((__v8hf)A, (__v8hf)B, _CMP_LE_OQ,
static __inline__ int __DEFAULT_FN_ATTRS128 _mm_ucomile_sh(__m128h __A,
__m128h __B) {
return __builtin_ia32_vcomish((__v8hf)__A, (__v8hf)__B, _CMP_LE_OQ,
_MM_FROUND_CUR_DIRECTION);
}

static __inline__ int __DEFAULT_FN_ATTRS128 _mm_ucomigt_sh(__m128h A,
__m128h B) {
return __builtin_ia32_vcomish((__v8hf)A, (__v8hf)B, _CMP_GT_OQ,
static __inline__ int __DEFAULT_FN_ATTRS128 _mm_ucomigt_sh(__m128h __A,
__m128h __B) {
return __builtin_ia32_vcomish((__v8hf)__A, (__v8hf)__B, _CMP_GT_OQ,
_MM_FROUND_CUR_DIRECTION);
}

static __inline__ int __DEFAULT_FN_ATTRS128 _mm_ucomige_sh(__m128h A,
__m128h B) {
return __builtin_ia32_vcomish((__v8hf)A, (__v8hf)B, _CMP_GE_OQ,
static __inline__ int __DEFAULT_FN_ATTRS128 _mm_ucomige_sh(__m128h __A,
__m128h __B) {
return __builtin_ia32_vcomish((__v8hf)__A, (__v8hf)__B, _CMP_GE_OQ,
_MM_FROUND_CUR_DIRECTION);
}

static __inline__ int __DEFAULT_FN_ATTRS128 _mm_ucomineq_sh(__m128h A,
__m128h B) {
return __builtin_ia32_vcomish((__v8hf)A, (__v8hf)B, _CMP_NEQ_UQ,
static __inline__ int __DEFAULT_FN_ATTRS128 _mm_ucomineq_sh(__m128h __A,
__m128h __B) {
return __builtin_ia32_vcomish((__v8hf)__A, (__v8hf)__B, _CMP_NEQ_UQ,
_MM_FROUND_CUR_DIRECTION);
}

Expand Down
9 changes: 9 additions & 0 deletions clang/lib/Headers/cpuid.h
Original file line number Diff line number Diff line change
Expand Up @@ -339,4 +339,13 @@ static __inline int __get_cpuid_count (unsigned int __leaf,
return 1;
}

// In some configurations, __cpuidex is defined as a builtin (primarily
// -fms-extensions) which will conflict with the __cpuidex definition below.
#if !(__has_builtin(__cpuidex))
static __inline void __cpuidex(int __cpu_info[4], int __leaf, int __subleaf) {
__cpuid_count(__leaf, __subleaf, __cpu_info[0], __cpu_info[1], __cpu_info[2],
__cpu_info[3]);
}
#endif

#endif /* __CPUID_H */
21 changes: 19 additions & 2 deletions clang/lib/Parse/ParseCXXInlineMethods.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -511,11 +511,28 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) {
// and the end of the function-definition, member-declarator, or
// declarator.
CXXMethodDecl *Method;
FunctionDecl *FunctionToPush;
if (FunctionTemplateDecl *FunTmpl
= dyn_cast<FunctionTemplateDecl>(LM.Method))
Method = dyn_cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl());
FunctionToPush = FunTmpl->getTemplatedDecl();
else
Method = dyn_cast<CXXMethodDecl>(LM.Method);
FunctionToPush = cast<FunctionDecl>(LM.Method);
Method = dyn_cast<CXXMethodDecl>(FunctionToPush);

// Push a function scope so that tryCaptureVariable() can properly visit
// function scopes involving function parameters that are referenced inside
// the noexcept specifier e.g. through a lambda expression.
// Example:
// struct X {
// void ICE(int val) noexcept(noexcept([val]{}));
// };
// Setup the CurScope to match the function DeclContext - we have such
// assumption in IsInFnTryBlockHandler().
ParseScope FnScope(this, Scope::FnScope);
Sema::ContextRAII FnContext(Actions, FunctionToPush,
/*NewThisContext=*/false);
Sema::FunctionScopeRAII PopFnContext(Actions);
Actions.PushFunctionScope();

Sema::CXXThisScopeRAII ThisScope(
Actions, Method ? Method->getParent() : nullptr,
Expand Down
7 changes: 3 additions & 4 deletions clang/lib/Parse/ParseExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2343,10 +2343,9 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
}

if (!LHS.isInvalid())
LHS = Actions.ActOnMemberAccessExpr(getCurScope(), LHS.get(), OpLoc,
OpKind, SS, TemplateKWLoc, Name,
CurParsedObjCImpl ? CurParsedObjCImpl->Dcl
: nullptr);
LHS = Actions.ActOnMemberAccessExpr(
getCurScope(), LHS.get(), OpLoc, OpKind, SS, TemplateKWLoc, Name,
CurParsedObjCImpl ? CurParsedObjCImpl->Dcl : nullptr);
if (!LHS.isInvalid()) {
if (Tok.is(tok::less))
checkPotentialAngleBracket(LHS);
Expand Down
Loading