Vendor import of clang release_50 branch r311606:
https://llvm.org/svn/llvm-project/cfe/branches/release_50@311606
This commit is contained in:
parent
2c7de53a2c
commit
d56c997a07
@ -49,6 +49,15 @@ Major New Features
|
||||
|
||||
- ...
|
||||
|
||||
C++ coroutines
|
||||
^^^^^^^^^^^^^^
|
||||
`C++ coroutines TS
|
||||
<http://open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4680.pdf>`_
|
||||
implementation has landed. Use ``-fcoroutines-ts -stdlib=libc++`` to enable
|
||||
coroutine support. Here is `an example
|
||||
<https://wandbox.org/permlink/Dth1IO5q8Oe31ew2>`_ to get you started.
|
||||
|
||||
|
||||
Improvements to Clang's diagnostics
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
@ -58,6 +67,25 @@ Improvements to Clang's diagnostics
|
||||
- -Wunused-lambda-capture warns when a variable explicitly captured
|
||||
by a lambda is not used in the body of the lambda.
|
||||
|
||||
- -Wstrict-prototypes is a new warning that warns about non-prototype
|
||||
function and block declarations and types in C and Objective-C.
|
||||
|
||||
- -Wunguarded-availability is a new warning that warns about uses of new
|
||||
APIs that were introduced in a system whose version is newer than the
|
||||
deployment target version. A new Objective-C expression ``@available`` has
|
||||
been introduced to perform system version checking at runtime. This warning
|
||||
is off by default to prevent unexpected warnings in existing projects.
|
||||
However, its less strict sibling -Wunguarded-availability-new is on by
|
||||
default. It warns about unguarded uses of APIs only when they were introduced
|
||||
in or after macOS 10.13, iOS 11, tvOS 11 or watchOS 4.
|
||||
|
||||
- The -Wdocumentation warning now allows the use of ``\param`` and
|
||||
``\returns`` documentation directives in the documentation comments for
|
||||
declarations with a function or a block pointer type.
|
||||
|
||||
- The compiler no longer warns about unreachable ``__builtin_unreachable``
|
||||
statements.
|
||||
|
||||
New Compiler Flags
|
||||
------------------
|
||||
|
||||
@ -76,8 +104,12 @@ future versions of Clang.
|
||||
New Pragmas in Clang
|
||||
-----------------------
|
||||
|
||||
Clang now supports the ...
|
||||
- Clang now supports the ``clang attribute`` pragma that allows users to apply
|
||||
an attribute to multiple declarations.
|
||||
|
||||
- ``pragma pack`` directives that are included in a precompiled header are now
|
||||
applied correctly to the declarations in the compilation unit that includes
|
||||
that precompiled header.
|
||||
|
||||
Attribute Changes in Clang
|
||||
--------------------------
|
||||
@ -85,6 +117,8 @@ Attribute Changes in Clang
|
||||
- The ``overloadable`` attribute now allows at most one function with a given
|
||||
name to lack the ``overloadable`` attribute. This unmarked function will not
|
||||
have its name mangled.
|
||||
- The ```ms_abi`` attribute and the ``__builtin_ms_va_list`` types and builtins
|
||||
are now supported on AArch64.
|
||||
|
||||
Windows Support
|
||||
---------------
|
||||
@ -95,7 +129,41 @@ Clang's support for building native Windows programs ...
|
||||
C Language Changes in Clang
|
||||
---------------------------
|
||||
|
||||
- ...
|
||||
- Added near complete support for implicit scalar to vector conversion, a GNU
|
||||
C/C++ language extension. With this extension, the following code is
|
||||
considered valid:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
typedef unsigned v4i32 __attribute__((vector_size(16)));
|
||||
|
||||
v4i32 foo(v4i32 a) {
|
||||
// Here 5 is implicitly casted to an unsigned value and replicated into a
|
||||
// vector with as many elements as 'a'.
|
||||
return a + 5;
|
||||
}
|
||||
|
||||
The implicit conversion of a scalar value to a vector value--in the context of
|
||||
a vector expression--occurs when:
|
||||
|
||||
- The type of the vector is that of a ``__attribute__((vector_size(size)))``
|
||||
vector, not an OpenCL ``__attribute__((ext_vector_type(size)))`` vector type.
|
||||
|
||||
- The scalar value can be casted to that of the vector element's type without
|
||||
the loss of precision based on the type of the scalar and the type of the
|
||||
vector's elements.
|
||||
|
||||
- For compile time constant values, the above rule is weakened to consider the
|
||||
value of the scalar constant rather than the constant's type.
|
||||
|
||||
- Floating point constants with precise integral representations are not
|
||||
implicitly converted to integer values, this is for compatability with GCC.
|
||||
|
||||
|
||||
Currently the basic integer and floating point types with the following
|
||||
operators are supported: ``+``, ``/``, ``-``, ``*``, ``%``, ``>``, ``<``,
|
||||
``>=``, ``<=``, ``==``, ``!=``, ``&``, ``|``, ``^`` and the corresponding
|
||||
assignment operators where applicable.
|
||||
|
||||
...
|
||||
|
||||
@ -107,6 +175,10 @@ C11 Feature Support
|
||||
C++ Language Changes in Clang
|
||||
-----------------------------
|
||||
|
||||
- As mentioned in `C Language Changes in Clang`_, Clang's support for
|
||||
implicit scalar to vector conversions also applies to C++. Additionally
|
||||
the following operators are also supported: ``&&`` and ``||``.
|
||||
|
||||
...
|
||||
|
||||
C++1z Feature Support
|
||||
@ -117,12 +189,56 @@ C++1z Feature Support
|
||||
Objective-C Language Changes in Clang
|
||||
-------------------------------------
|
||||
|
||||
...
|
||||
- Clang now guarantees that a ``readwrite`` property is synthesized when an
|
||||
ambiguous property (i.e. a property that's declared in multiple protocols)
|
||||
is synthesized. The ``-Wprotocol-property-synthesis-ambiguity`` warning that
|
||||
warns about incompatible property types is now promoted to an error when
|
||||
there's an ambiguity between ``readwrite`` and ``readonly`` properties.
|
||||
|
||||
- Clang now prohibits synthesis of ambiguous properties with incompatible
|
||||
explicit property attributes. The following property attributes are
|
||||
checked for differences: ``copy``, ``retain``/``strong``, ``atomic``,
|
||||
``getter`` and ``setter``.
|
||||
|
||||
OpenCL C Language Changes in Clang
|
||||
----------------------------------
|
||||
|
||||
...
|
||||
Various bug fixes and improvements:
|
||||
|
||||
- Extended OpenCL-related Clang tests.
|
||||
|
||||
- Improved diagnostics across several areas: scoped address space
|
||||
qualified variables, function pointers, atomics, type rank for overloading,
|
||||
block captures, ``reserve_id_t``.
|
||||
|
||||
- Several address space related fixes for constant address space function scope variables,
|
||||
IR generation, mangling of ``generic`` and alloca (post-fix from general Clang
|
||||
refactoring of address spaces).
|
||||
|
||||
- Several improvements in extensions: fixed OpenCL version for ``cl_khr_mipmap_image``,
|
||||
added missing ``cl_khr_3d_image_writes``.
|
||||
|
||||
- Improvements in ``enqueue_kernel``, especially the implementation of ``ndrange_t`` and blocks.
|
||||
|
||||
- OpenCL type related fixes: global samplers, the ``pipe_t`` size, internal type redefinition,
|
||||
and type compatibility checking in ternary and other operations.
|
||||
|
||||
- The OpenCL header has been extended with missing extension guards, and direct mapping of ``as_type``
|
||||
to ``__builtin_astype``.
|
||||
|
||||
- Fixed ``kernel_arg_type_qual`` and OpenCL/SPIR version in metadata.
|
||||
|
||||
- Added proper use of the kernel calling convention to various targets.
|
||||
|
||||
The following new functionalities have been added:
|
||||
|
||||
- Added documentation on OpenCL to Clang user manual.
|
||||
|
||||
- Extended Clang builtins with required ``cl_khr_subgroups`` support.
|
||||
|
||||
- Add ``intel_reqd_sub_group_size`` attribute support.
|
||||
|
||||
- Added OpenCL types to ``CIndex``.
|
||||
|
||||
OpenMP Support in Clang
|
||||
----------------------------------
|
||||
@ -194,8 +310,30 @@ clang-format
|
||||
libclang
|
||||
--------
|
||||
|
||||
...
|
||||
- Libclang now provides code-completion results for more C++ constructs
|
||||
and keywords. The following keywords/identifiers are now included in the
|
||||
code-completion results: ``static_assert``, ``alignas``, ``constexpr``,
|
||||
``final``, ``noexcept``, ``override`` and ``thread_local``.
|
||||
|
||||
- Libclang now provides code-completion results for members from dependent
|
||||
classes. For example:
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
template<typename T>
|
||||
void appendValue(std::vector<T> &dest, const T &value) {
|
||||
dest. // Relevant completion results are now shown after '.'
|
||||
}
|
||||
|
||||
Note that code-completion results are still not provided when the member
|
||||
expression includes a dependent base expression. For example:
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
template<typename T>
|
||||
void appendValue(std::vector<std::vector<T>> &dest, const T &value) {
|
||||
dest.at(0). // Libclang fails to provide completion results after '.'
|
||||
}
|
||||
|
||||
Static Analyzer
|
||||
---------------
|
||||
|
@ -375,6 +375,7 @@ class CXXRecordDecl : public RecordDecl {
|
||||
/// \brief These flags are \c true if a defaulted corresponding special
|
||||
/// member can't be fully analyzed without performing overload resolution.
|
||||
/// @{
|
||||
unsigned NeedOverloadResolutionForCopyConstructor : 1;
|
||||
unsigned NeedOverloadResolutionForMoveConstructor : 1;
|
||||
unsigned NeedOverloadResolutionForMoveAssignment : 1;
|
||||
unsigned NeedOverloadResolutionForDestructor : 1;
|
||||
@ -383,6 +384,7 @@ class CXXRecordDecl : public RecordDecl {
|
||||
/// \brief These flags are \c true if an implicit defaulted corresponding
|
||||
/// special member would be defined as deleted.
|
||||
/// @{
|
||||
unsigned DefaultedCopyConstructorIsDeleted : 1;
|
||||
unsigned DefaultedMoveConstructorIsDeleted : 1;
|
||||
unsigned DefaultedMoveAssignmentIsDeleted : 1;
|
||||
unsigned DefaultedDestructorIsDeleted : 1;
|
||||
@ -415,6 +417,12 @@ class CXXRecordDecl : public RecordDecl {
|
||||
/// constructor.
|
||||
unsigned HasDefaultedDefaultConstructor : 1;
|
||||
|
||||
/// \brief True if this class can be passed in a non-address-preserving
|
||||
/// fashion (such as in registers) according to the C++ language rules.
|
||||
/// This does not imply anything about how the ABI in use will actually
|
||||
/// pass an object of this class.
|
||||
unsigned CanPassInRegisters : 1;
|
||||
|
||||
/// \brief True if a defaulted default constructor for this class would
|
||||
/// be constexpr.
|
||||
unsigned DefaultedDefaultConstructorIsConstexpr : 1;
|
||||
@ -811,18 +819,50 @@ class CXXRecordDecl : public RecordDecl {
|
||||
return data().FirstFriend.isValid();
|
||||
}
|
||||
|
||||
/// \brief \c true if a defaulted copy constructor for this class would be
|
||||
/// deleted.
|
||||
bool defaultedCopyConstructorIsDeleted() const {
|
||||
assert((!needsOverloadResolutionForCopyConstructor() ||
|
||||
(data().DeclaredSpecialMembers & SMF_CopyConstructor)) &&
|
||||
"this property has not yet been computed by Sema");
|
||||
return data().DefaultedCopyConstructorIsDeleted;
|
||||
}
|
||||
|
||||
/// \brief \c true if a defaulted move constructor for this class would be
|
||||
/// deleted.
|
||||
bool defaultedMoveConstructorIsDeleted() const {
|
||||
assert((!needsOverloadResolutionForMoveConstructor() ||
|
||||
(data().DeclaredSpecialMembers & SMF_MoveConstructor)) &&
|
||||
"this property has not yet been computed by Sema");
|
||||
return data().DefaultedMoveConstructorIsDeleted;
|
||||
}
|
||||
|
||||
/// \brief \c true if a defaulted destructor for this class would be deleted.
|
||||
bool defaultedDestructorIsDeleted() const {
|
||||
return !data().DefaultedDestructorIsDeleted;
|
||||
}
|
||||
|
||||
/// \brief \c true if we know for sure that this class has a single,
|
||||
/// accessible, unambiguous copy constructor that is not deleted.
|
||||
bool hasSimpleCopyConstructor() const {
|
||||
return !hasUserDeclaredCopyConstructor() &&
|
||||
!data().DefaultedCopyConstructorIsDeleted;
|
||||
}
|
||||
|
||||
/// \brief \c true if we know for sure that this class has a single,
|
||||
/// accessible, unambiguous move constructor that is not deleted.
|
||||
bool hasSimpleMoveConstructor() const {
|
||||
return !hasUserDeclaredMoveConstructor() && hasMoveConstructor() &&
|
||||
!data().DefaultedMoveConstructorIsDeleted;
|
||||
}
|
||||
|
||||
/// \brief \c true if we know for sure that this class has a single,
|
||||
/// accessible, unambiguous move assignment operator that is not deleted.
|
||||
bool hasSimpleMoveAssignment() const {
|
||||
return !hasUserDeclaredMoveAssignment() && hasMoveAssignment() &&
|
||||
!data().DefaultedMoveAssignmentIsDeleted;
|
||||
}
|
||||
|
||||
/// \brief \c true if we know for sure that this class has an accessible
|
||||
/// destructor that is not deleted.
|
||||
bool hasSimpleDestructor() const {
|
||||
@ -878,7 +918,16 @@ class CXXRecordDecl : public RecordDecl {
|
||||
/// \brief Determine whether we need to eagerly declare a defaulted copy
|
||||
/// constructor for this class.
|
||||
bool needsOverloadResolutionForCopyConstructor() const {
|
||||
return data().HasMutableFields;
|
||||
// C++17 [class.copy.ctor]p6:
|
||||
// If the class definition declares a move constructor or move assignment
|
||||
// operator, the implicitly declared copy constructor is defined as
|
||||
// deleted.
|
||||
// In MSVC mode, sometimes a declared move assignment does not delete an
|
||||
// implicit copy constructor, so defer this choice to Sema.
|
||||
if (data().UserDeclaredSpecialMembers &
|
||||
(SMF_MoveConstructor | SMF_MoveAssignment))
|
||||
return true;
|
||||
return data().NeedOverloadResolutionForCopyConstructor;
|
||||
}
|
||||
|
||||
/// \brief Determine whether an implicit copy constructor for this type
|
||||
@ -919,7 +968,16 @@ class CXXRecordDecl : public RecordDecl {
|
||||
needsImplicitMoveConstructor();
|
||||
}
|
||||
|
||||
/// \brief Set that we attempted to declare an implicitly move
|
||||
/// \brief Set that we attempted to declare an implicit copy
|
||||
/// constructor, but overload resolution failed so we deleted it.
|
||||
void setImplicitCopyConstructorIsDeleted() {
|
||||
assert((data().DefaultedCopyConstructorIsDeleted ||
|
||||
needsOverloadResolutionForCopyConstructor()) &&
|
||||
"Copy constructor should not be deleted");
|
||||
data().DefaultedCopyConstructorIsDeleted = true;
|
||||
}
|
||||
|
||||
/// \brief Set that we attempted to declare an implicit move
|
||||
/// constructor, but overload resolution failed so we deleted it.
|
||||
void setImplicitMoveConstructorIsDeleted() {
|
||||
assert((data().DefaultedMoveConstructorIsDeleted ||
|
||||
@ -1316,6 +1374,18 @@ class CXXRecordDecl : public RecordDecl {
|
||||
return data().HasIrrelevantDestructor;
|
||||
}
|
||||
|
||||
/// \brief Determine whether this class has at least one trivial, non-deleted
|
||||
/// copy or move constructor.
|
||||
bool canPassInRegisters() const {
|
||||
return data().CanPassInRegisters;
|
||||
}
|
||||
|
||||
/// \brief Set that we can pass this RecordDecl in registers.
|
||||
// FIXME: This should be set as part of completeDefinition.
|
||||
void setCanPassInRegisters(bool CanPass) {
|
||||
data().CanPassInRegisters = CanPass;
|
||||
}
|
||||
|
||||
/// \brief Determine whether this class has a non-literal or/ volatile type
|
||||
/// non-static data member or base class.
|
||||
bool hasNonLiteralTypeFieldsOrBases() const {
|
||||
|
@ -1048,10 +1048,6 @@ class Preprocessor {
|
||||
/// which implicitly adds the builtin defines etc.
|
||||
void EnterMainSourceFile();
|
||||
|
||||
/// \brief After parser warm-up, initialize the conditional stack from
|
||||
/// the preamble.
|
||||
void replayPreambleConditionalStack();
|
||||
|
||||
/// \brief Inform the preprocessor callbacks that processing is complete.
|
||||
void EndSourceFile();
|
||||
|
||||
@ -2025,6 +2021,10 @@ class Preprocessor {
|
||||
}
|
||||
|
||||
private:
|
||||
/// \brief After processing predefined file, initialize the conditional stack from
|
||||
/// the preamble.
|
||||
void replayPreambleConditionalStack();
|
||||
|
||||
// Macro handling.
|
||||
void HandleDefineDirective(Token &Tok, bool ImmediatelyAfterTopLevelIfndef);
|
||||
void HandleUndefDirective();
|
||||
|
@ -956,12 +956,16 @@ bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To,
|
||||
ToData.HasUninitializedFields = FromData.HasUninitializedFields;
|
||||
ToData.HasInheritedConstructor = FromData.HasInheritedConstructor;
|
||||
ToData.HasInheritedAssignment = FromData.HasInheritedAssignment;
|
||||
ToData.NeedOverloadResolutionForCopyConstructor
|
||||
= FromData.NeedOverloadResolutionForCopyConstructor;
|
||||
ToData.NeedOverloadResolutionForMoveConstructor
|
||||
= FromData.NeedOverloadResolutionForMoveConstructor;
|
||||
ToData.NeedOverloadResolutionForMoveAssignment
|
||||
= FromData.NeedOverloadResolutionForMoveAssignment;
|
||||
ToData.NeedOverloadResolutionForDestructor
|
||||
= FromData.NeedOverloadResolutionForDestructor;
|
||||
ToData.DefaultedCopyConstructorIsDeleted
|
||||
= FromData.DefaultedCopyConstructorIsDeleted;
|
||||
ToData.DefaultedMoveConstructorIsDeleted
|
||||
= FromData.DefaultedMoveConstructorIsDeleted;
|
||||
ToData.DefaultedMoveAssignmentIsDeleted
|
||||
@ -973,6 +977,7 @@ bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To,
|
||||
= FromData.HasConstexprNonCopyMoveConstructor;
|
||||
ToData.HasDefaultedDefaultConstructor
|
||||
= FromData.HasDefaultedDefaultConstructor;
|
||||
ToData.CanPassInRegisters = FromData.CanPassInRegisters;
|
||||
ToData.DefaultedDefaultConstructorIsConstexpr
|
||||
= FromData.DefaultedDefaultConstructorIsConstexpr;
|
||||
ToData.HasConstexprDefaultConstructor
|
||||
|
@ -55,15 +55,18 @@ CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D)
|
||||
HasOnlyCMembers(true), HasInClassInitializer(false),
|
||||
HasUninitializedReferenceMember(false), HasUninitializedFields(false),
|
||||
HasInheritedConstructor(false), HasInheritedAssignment(false),
|
||||
NeedOverloadResolutionForCopyConstructor(false),
|
||||
NeedOverloadResolutionForMoveConstructor(false),
|
||||
NeedOverloadResolutionForMoveAssignment(false),
|
||||
NeedOverloadResolutionForDestructor(false),
|
||||
DefaultedCopyConstructorIsDeleted(false),
|
||||
DefaultedMoveConstructorIsDeleted(false),
|
||||
DefaultedMoveAssignmentIsDeleted(false),
|
||||
DefaultedDestructorIsDeleted(false), HasTrivialSpecialMembers(SMF_All),
|
||||
DeclaredNonTrivialSpecialMembers(0), HasIrrelevantDestructor(true),
|
||||
HasConstexprNonCopyMoveConstructor(false),
|
||||
HasDefaultedDefaultConstructor(false),
|
||||
CanPassInRegisters(true),
|
||||
DefaultedDefaultConstructorIsConstexpr(true),
|
||||
HasConstexprDefaultConstructor(false),
|
||||
HasNonLiteralTypeFieldsOrBases(false), ComputedVisibleConversions(false),
|
||||
@ -352,8 +355,10 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
|
||||
setHasVolatileMember(true);
|
||||
|
||||
// Keep track of the presence of mutable fields.
|
||||
if (BaseClassDecl->hasMutableFields())
|
||||
if (BaseClassDecl->hasMutableFields()) {
|
||||
data().HasMutableFields = true;
|
||||
data().NeedOverloadResolutionForCopyConstructor = true;
|
||||
}
|
||||
|
||||
if (BaseClassDecl->hasUninitializedReferenceMember())
|
||||
data().HasUninitializedReferenceMember = true;
|
||||
@ -406,6 +411,8 @@ void CXXRecordDecl::addedClassSubobject(CXXRecordDecl *Subobj) {
|
||||
// -- a direct or virtual base class B that cannot be copied/moved [...]
|
||||
// -- a non-static data member of class type M (or array thereof)
|
||||
// that cannot be copied or moved [...]
|
||||
if (!Subobj->hasSimpleCopyConstructor())
|
||||
data().NeedOverloadResolutionForCopyConstructor = true;
|
||||
if (!Subobj->hasSimpleMoveConstructor())
|
||||
data().NeedOverloadResolutionForMoveConstructor = true;
|
||||
|
||||
@ -426,6 +433,7 @@ void CXXRecordDecl::addedClassSubobject(CXXRecordDecl *Subobj) {
|
||||
// -- any non-static data member has a type with a destructor
|
||||
// that is deleted or inaccessible from the defaulted [ctor or dtor].
|
||||
if (!Subobj->hasSimpleDestructor()) {
|
||||
data().NeedOverloadResolutionForCopyConstructor = true;
|
||||
data().NeedOverloadResolutionForMoveConstructor = true;
|
||||
data().NeedOverloadResolutionForDestructor = true;
|
||||
}
|
||||
@ -711,8 +719,10 @@ void CXXRecordDecl::addedMember(Decl *D) {
|
||||
data().IsStandardLayout = false;
|
||||
|
||||
// Keep track of the presence of mutable fields.
|
||||
if (Field->isMutable())
|
||||
if (Field->isMutable()) {
|
||||
data().HasMutableFields = true;
|
||||
data().NeedOverloadResolutionForCopyConstructor = true;
|
||||
}
|
||||
|
||||
// C++11 [class.union]p8, DR1460:
|
||||
// If X is a union, a non-static data member of X that is not an anonymous
|
||||
@ -756,6 +766,12 @@ void CXXRecordDecl::addedMember(Decl *D) {
|
||||
// A standard-layout class is a class that:
|
||||
// -- has no non-static data members of type [...] reference,
|
||||
data().IsStandardLayout = false;
|
||||
|
||||
// C++1z [class.copy.ctor]p10:
|
||||
// A defaulted copy constructor for a class X is defined as deleted if X has:
|
||||
// -- a non-static data member of rvalue reference type
|
||||
if (T->isRValueReferenceType())
|
||||
data().DefaultedCopyConstructorIsDeleted = true;
|
||||
}
|
||||
|
||||
if (!Field->hasInClassInitializer() && !Field->isMutable()) {
|
||||
@ -809,6 +825,10 @@ void CXXRecordDecl::addedMember(Decl *D) {
|
||||
// We may need to perform overload resolution to determine whether a
|
||||
// field can be moved if it's const or volatile qualified.
|
||||
if (T.getCVRQualifiers() & (Qualifiers::Const | Qualifiers::Volatile)) {
|
||||
// We need to care about 'const' for the copy constructor because an
|
||||
// implicit copy constructor might be declared with a non-const
|
||||
// parameter.
|
||||
data().NeedOverloadResolutionForCopyConstructor = true;
|
||||
data().NeedOverloadResolutionForMoveConstructor = true;
|
||||
data().NeedOverloadResolutionForMoveAssignment = true;
|
||||
}
|
||||
@ -819,6 +839,8 @@ void CXXRecordDecl::addedMember(Decl *D) {
|
||||
// -- X is a union-like class that has a variant member with a
|
||||
// non-trivial [corresponding special member]
|
||||
if (isUnion()) {
|
||||
if (FieldRec->hasNonTrivialCopyConstructor())
|
||||
data().DefaultedCopyConstructorIsDeleted = true;
|
||||
if (FieldRec->hasNonTrivialMoveConstructor())
|
||||
data().DefaultedMoveConstructorIsDeleted = true;
|
||||
if (FieldRec->hasNonTrivialMoveAssignment())
|
||||
@ -830,6 +852,8 @@ void CXXRecordDecl::addedMember(Decl *D) {
|
||||
// For an anonymous union member, our overload resolution will perform
|
||||
// overload resolution for its members.
|
||||
if (Field->isAnonymousStructOrUnion()) {
|
||||
data().NeedOverloadResolutionForCopyConstructor |=
|
||||
FieldRec->data().NeedOverloadResolutionForCopyConstructor;
|
||||
data().NeedOverloadResolutionForMoveConstructor |=
|
||||
FieldRec->data().NeedOverloadResolutionForMoveConstructor;
|
||||
data().NeedOverloadResolutionForMoveAssignment |=
|
||||
@ -915,8 +939,10 @@ void CXXRecordDecl::addedMember(Decl *D) {
|
||||
}
|
||||
|
||||
// Keep track of the presence of mutable fields.
|
||||
if (FieldRec->hasMutableFields())
|
||||
if (FieldRec->hasMutableFields()) {
|
||||
data().HasMutableFields = true;
|
||||
data().NeedOverloadResolutionForCopyConstructor = true;
|
||||
}
|
||||
|
||||
// C++11 [class.copy]p13:
|
||||
// If the implicitly-defined constructor would satisfy the
|
||||
@ -1450,7 +1476,7 @@ void CXXRecordDecl::completeDefinition() {
|
||||
|
||||
void CXXRecordDecl::completeDefinition(CXXFinalOverriderMap *FinalOverriders) {
|
||||
RecordDecl::completeDefinition();
|
||||
|
||||
|
||||
// If the class may be abstract (but hasn't been marked as such), check for
|
||||
// any pure final overriders.
|
||||
if (mayBeAbstract()) {
|
||||
|
@ -30,38 +30,9 @@ void CGCXXABI::ErrorUnsupportedABI(CodeGenFunction &CGF, StringRef S) {
|
||||
}
|
||||
|
||||
bool CGCXXABI::canCopyArgument(const CXXRecordDecl *RD) const {
|
||||
// If RD has a non-trivial move or copy constructor, we cannot copy the
|
||||
// argument.
|
||||
if (RD->hasNonTrivialCopyConstructor() || RD->hasNonTrivialMoveConstructor())
|
||||
return false;
|
||||
|
||||
// If RD has a non-trivial destructor, we cannot copy the argument.
|
||||
if (RD->hasNonTrivialDestructor())
|
||||
return false;
|
||||
|
||||
// We can only copy the argument if there exists at least one trivial,
|
||||
// non-deleted copy or move constructor.
|
||||
// FIXME: This assumes that all lazily declared copy and move constructors are
|
||||
// not deleted. This assumption might not be true in some corner cases.
|
||||
bool CopyDeleted = false;
|
||||
bool MoveDeleted = false;
|
||||
for (const CXXConstructorDecl *CD : RD->ctors()) {
|
||||
if (CD->isCopyConstructor() || CD->isMoveConstructor()) {
|
||||
assert(CD->isTrivial());
|
||||
// We had at least one undeleted trivial copy or move ctor. Return
|
||||
// directly.
|
||||
if (!CD->isDeleted())
|
||||
return true;
|
||||
if (CD->isCopyConstructor())
|
||||
CopyDeleted = true;
|
||||
else
|
||||
MoveDeleted = true;
|
||||
}
|
||||
}
|
||||
|
||||
// If all trivial copy and move constructors are deleted, we cannot copy the
|
||||
// argument.
|
||||
return !(CopyDeleted && MoveDeleted);
|
||||
return RD->canPassInRegisters();
|
||||
}
|
||||
|
||||
llvm::Constant *CGCXXABI::GetBogusMemberPointer(QualType T) {
|
||||
|
@ -63,11 +63,8 @@ class ItaniumCXXABI : public CodeGen::CGCXXABI {
|
||||
bool classifyReturnType(CGFunctionInfo &FI) const override;
|
||||
|
||||
RecordArgABI getRecordArgABI(const CXXRecordDecl *RD) const override {
|
||||
// Structures with either a non-trivial destructor or a non-trivial
|
||||
// copy constructor are always indirect.
|
||||
// FIXME: Use canCopyArgument() when it is fixed to handle lazily declared
|
||||
// special members.
|
||||
if (RD->hasNonTrivialDestructor() || RD->hasNonTrivialCopyConstructor())
|
||||
// If C++ prohibits us from making a copy, pass by address.
|
||||
if (!canCopyArgument(RD))
|
||||
return RAA_Indirect;
|
||||
return RAA_Default;
|
||||
}
|
||||
@ -998,10 +995,8 @@ bool ItaniumCXXABI::classifyReturnType(CGFunctionInfo &FI) const {
|
||||
if (!RD)
|
||||
return false;
|
||||
|
||||
// Return indirectly if we have a non-trivial copy ctor or non-trivial dtor.
|
||||
// FIXME: Use canCopyArgument() when it is fixed to handle lazily declared
|
||||
// special members.
|
||||
if (RD->hasNonTrivialDestructor() || RD->hasNonTrivialCopyConstructor()) {
|
||||
// If C++ prohibits us from making a copy, return by address.
|
||||
if (!canCopyArgument(RD)) {
|
||||
auto Align = CGM.getContext().getTypeAlignInChars(FI.getReturnType());
|
||||
FI.getReturnInfo() = ABIArgInfo::getIndirect(Align, /*ByVal=*/false);
|
||||
return true;
|
||||
|
@ -819,46 +819,44 @@ MicrosoftCXXABI::getRecordArgABI(const CXXRecordDecl *RD) const {
|
||||
return RAA_Default;
|
||||
|
||||
case llvm::Triple::x86_64:
|
||||
// Win64 passes objects with non-trivial copy ctors indirectly.
|
||||
if (RD->hasNonTrivialCopyConstructor())
|
||||
return RAA_Indirect;
|
||||
|
||||
// If an object has a destructor, we'd really like to pass it indirectly
|
||||
// If a class has a destructor, we'd really like to pass it indirectly
|
||||
// because it allows us to elide copies. Unfortunately, MSVC makes that
|
||||
// impossible for small types, which it will pass in a single register or
|
||||
// stack slot. Most objects with dtors are large-ish, so handle that early.
|
||||
// We can't call out all large objects as being indirect because there are
|
||||
// multiple x64 calling conventions and the C++ ABI code shouldn't dictate
|
||||
// how we pass large POD types.
|
||||
//
|
||||
// Note: This permits small classes with nontrivial destructors to be
|
||||
// passed in registers, which is non-conforming.
|
||||
if (RD->hasNonTrivialDestructor() &&
|
||||
getContext().getTypeSize(RD->getTypeForDecl()) > 64)
|
||||
return RAA_Indirect;
|
||||
|
||||
// If this is true, the implicit copy constructor that Sema would have
|
||||
// created would not be deleted. FIXME: We should provide a more direct way
|
||||
// for CodeGen to ask whether the constructor was deleted.
|
||||
if (!RD->hasUserDeclaredCopyConstructor() &&
|
||||
!RD->hasUserDeclaredMoveConstructor() &&
|
||||
!RD->needsOverloadResolutionForMoveConstructor() &&
|
||||
!RD->hasUserDeclaredMoveAssignment() &&
|
||||
!RD->needsOverloadResolutionForMoveAssignment())
|
||||
return RAA_Default;
|
||||
|
||||
// Otherwise, Sema should have created an implicit copy constructor if
|
||||
// needed.
|
||||
assert(!RD->needsImplicitCopyConstructor());
|
||||
|
||||
// We have to make sure the trivial copy constructor isn't deleted.
|
||||
for (const CXXConstructorDecl *CD : RD->ctors()) {
|
||||
if (CD->isCopyConstructor()) {
|
||||
assert(CD->isTrivial());
|
||||
// We had at least one undeleted trivial copy ctor. Return directly.
|
||||
if (!CD->isDeleted())
|
||||
return RAA_Default;
|
||||
// If a class has at least one non-deleted, trivial copy constructor, it
|
||||
// is passed according to the C ABI. Otherwise, it is passed indirectly.
|
||||
//
|
||||
// Note: This permits classes with non-trivial copy or move ctors to be
|
||||
// passed in registers, so long as they *also* have a trivial copy ctor,
|
||||
// which is non-conforming.
|
||||
if (RD->needsImplicitCopyConstructor()) {
|
||||
// If the copy ctor has not yet been declared, we can read its triviality
|
||||
// off the AST.
|
||||
if (!RD->defaultedCopyConstructorIsDeleted() &&
|
||||
RD->hasTrivialCopyConstructor())
|
||||
return RAA_Default;
|
||||
} else {
|
||||
// Otherwise, we need to find the copy constructor(s) and ask.
|
||||
for (const CXXConstructorDecl *CD : RD->ctors()) {
|
||||
if (CD->isCopyConstructor()) {
|
||||
// We had at least one nondeleted trivial copy ctor. Return directly.
|
||||
if (!CD->isDeleted() && CD->isTrivial())
|
||||
return RAA_Default;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The trivial copy constructor was deleted. Return indirectly.
|
||||
// We have no trivial, non-deleted copy constructor.
|
||||
return RAA_Indirect;
|
||||
}
|
||||
|
||||
|
@ -1837,7 +1837,12 @@ Darwin::TranslateArgs(const DerivedArgList &Args, StringRef BoundArch,
|
||||
}
|
||||
|
||||
bool MachO::IsUnwindTablesDefault(const ArgList &Args) const {
|
||||
return !UseSjLjExceptions(Args);
|
||||
// Unwind tables are not emitted if -fno-exceptions is supplied (except when
|
||||
// targeting x86_64).
|
||||
return getArch() == llvm::Triple::x86_64 ||
|
||||
(!UseSjLjExceptions(Args) &&
|
||||
Args.hasFlag(options::OPT_fexceptions, options::OPT_fno_exceptions,
|
||||
true));
|
||||
}
|
||||
|
||||
bool MachO::UseDwarfDebugFlags() const {
|
||||
|
@ -76,7 +76,7 @@ static bool getSystemRegistryString(const char *keyPath, const char *valueName,
|
||||
|
||||
// Check various environment variables to try and find a toolchain.
|
||||
static bool findVCToolChainViaEnvironment(std::string &Path,
|
||||
bool &IsVS2017OrNewer) {
|
||||
MSVCToolChain::ToolsetLayout &VSLayout) {
|
||||
// These variables are typically set by vcvarsall.bat
|
||||
// when launching a developer command prompt.
|
||||
if (llvm::Optional<std::string> VCToolsInstallDir =
|
||||
@ -84,7 +84,7 @@ static bool findVCToolChainViaEnvironment(std::string &Path,
|
||||
// This is only set by newer Visual Studios, and it leads straight to
|
||||
// the toolchain directory.
|
||||
Path = std::move(*VCToolsInstallDir);
|
||||
IsVS2017OrNewer = true;
|
||||
VSLayout = MSVCToolChain::ToolsetLayout::VS2017OrNewer;
|
||||
return true;
|
||||
}
|
||||
if (llvm::Optional<std::string> VCInstallDir =
|
||||
@ -94,7 +94,7 @@ static bool findVCToolChainViaEnvironment(std::string &Path,
|
||||
// so this check has to appear second.
|
||||
// In older Visual Studios, the VC directory is the toolchain.
|
||||
Path = std::move(*VCInstallDir);
|
||||
IsVS2017OrNewer = false;
|
||||
VSLayout = MSVCToolChain::ToolsetLayout::OlderVS;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -134,9 +134,16 @@ static bool findVCToolChainViaEnvironment(std::string &Path,
|
||||
}
|
||||
if (IsBin) {
|
||||
llvm::StringRef ParentPath = llvm::sys::path::parent_path(TestPath);
|
||||
if (llvm::sys::path::filename(ParentPath) == "VC") {
|
||||
llvm::StringRef ParentFilename = llvm::sys::path::filename(ParentPath);
|
||||
if (ParentFilename == "VC") {
|
||||
Path = ParentPath;
|
||||
IsVS2017OrNewer = false;
|
||||
VSLayout = MSVCToolChain::ToolsetLayout::OlderVS;
|
||||
return true;
|
||||
}
|
||||
if (ParentFilename == "x86ret" || ParentFilename == "x86chk"
|
||||
|| ParentFilename == "amd64ret" || ParentFilename == "amd64chk") {
|
||||
Path = ParentPath;
|
||||
VSLayout = MSVCToolChain::ToolsetLayout::DevDivInternal;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -165,7 +172,7 @@ static bool findVCToolChainViaEnvironment(std::string &Path,
|
||||
ToolChainPath = llvm::sys::path::parent_path(ToolChainPath);
|
||||
|
||||
Path = ToolChainPath;
|
||||
IsVS2017OrNewer = true;
|
||||
VSLayout = MSVCToolChain::ToolsetLayout::VS2017OrNewer;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -181,7 +188,7 @@ static bool findVCToolChainViaEnvironment(std::string &Path,
|
||||
// This is the preferred way to discover new Visual Studios, as they're no
|
||||
// longer listed in the registry.
|
||||
static bool findVCToolChainViaSetupConfig(std::string &Path,
|
||||
bool &IsVS2017OrNewer) {
|
||||
MSVCToolChain::ToolsetLayout &VSLayout) {
|
||||
#if !defined(USE_MSVC_SETUP_API)
|
||||
return false;
|
||||
#else
|
||||
@ -263,7 +270,7 @@ static bool findVCToolChainViaSetupConfig(std::string &Path,
|
||||
return false;
|
||||
|
||||
Path = ToolchainPath.str();
|
||||
IsVS2017OrNewer = true;
|
||||
VSLayout = MSVCToolChain::ToolsetLayout::VS2017OrNewer;
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
@ -272,7 +279,7 @@ static bool findVCToolChainViaSetupConfig(std::string &Path,
|
||||
// a toolchain path. VS2017 and newer don't get added to the registry.
|
||||
// So if we find something here, we know that it's an older version.
|
||||
static bool findVCToolChainViaRegistry(std::string &Path,
|
||||
bool &IsVS2017OrNewer) {
|
||||
MSVCToolChain::ToolsetLayout &VSLayout) {
|
||||
std::string VSInstallPath;
|
||||
if (getSystemRegistryString(R"(SOFTWARE\Microsoft\VisualStudio\$VERSION)",
|
||||
"InstallDir", VSInstallPath, nullptr) ||
|
||||
@ -284,7 +291,7 @@ static bool findVCToolChainViaRegistry(std::string &Path,
|
||||
llvm::sys::path::append(VCPath, "VC");
|
||||
|
||||
Path = VCPath.str();
|
||||
IsVS2017OrNewer = false;
|
||||
VSLayout = MSVCToolChain::ToolsetLayout::OlderVS;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -475,6 +482,7 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
|
||||
// native target bin directory.
|
||||
// e.g. when compiling for x86 on an x64 host, PATH should start with:
|
||||
// /bin/HostX64/x86;/bin/HostX64/x64
|
||||
// This doesn't attempt to handle ToolsetLayout::DevDivInternal.
|
||||
if (TC.getIsVS2017OrNewer() &&
|
||||
llvm::Triple(llvm::sys::getProcessTriple()).getArch() != TC.getArch()) {
|
||||
auto HostArch = llvm::Triple(llvm::sys::getProcessTriple()).getArch();
|
||||
@ -677,9 +685,9 @@ MSVCToolChain::MSVCToolChain(const Driver &D, const llvm::Triple &Triple,
|
||||
// what they want to use.
|
||||
// Failing that, just try to find the newest Visual Studio version we can
|
||||
// and use its default VC toolchain.
|
||||
findVCToolChainViaEnvironment(VCToolChainPath, IsVS2017OrNewer) ||
|
||||
findVCToolChainViaSetupConfig(VCToolChainPath, IsVS2017OrNewer) ||
|
||||
findVCToolChainViaRegistry(VCToolChainPath, IsVS2017OrNewer);
|
||||
findVCToolChainViaEnvironment(VCToolChainPath, VSLayout) ||
|
||||
findVCToolChainViaSetupConfig(VCToolChainPath, VSLayout) ||
|
||||
findVCToolChainViaRegistry(VCToolChainPath, VSLayout);
|
||||
}
|
||||
|
||||
Tool *MSVCToolChain::buildLinker() const {
|
||||
@ -766,6 +774,21 @@ static const char *llvmArchToLegacyVCArch(llvm::Triple::ArchType Arch) {
|
||||
}
|
||||
}
|
||||
|
||||
// Similar to the above function, but for DevDiv internal builds.
|
||||
static const char *llvmArchToDevDivInternalArch(llvm::Triple::ArchType Arch) {
|
||||
using ArchType = llvm::Triple::ArchType;
|
||||
switch (Arch) {
|
||||
case ArchType::x86:
|
||||
return "i386";
|
||||
case ArchType::x86_64:
|
||||
return "amd64";
|
||||
case ArchType::arm:
|
||||
return "arm";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
// Get the path to a specific subdirectory in the current toolchain for
|
||||
// a given target architecture.
|
||||
// VS2017 changed the VC toolchain layout, so this should be used instead
|
||||
@ -773,26 +796,40 @@ static const char *llvmArchToLegacyVCArch(llvm::Triple::ArchType Arch) {
|
||||
std::string
|
||||
MSVCToolChain::getSubDirectoryPath(SubDirectoryType Type,
|
||||
llvm::Triple::ArchType TargetArch) const {
|
||||
const char *SubdirName;
|
||||
const char *IncludeName;
|
||||
switch (VSLayout) {
|
||||
case ToolsetLayout::OlderVS:
|
||||
SubdirName = llvmArchToLegacyVCArch(TargetArch);
|
||||
IncludeName = "include";
|
||||
break;
|
||||
case ToolsetLayout::VS2017OrNewer:
|
||||
SubdirName = llvmArchToWindowsSDKArch(TargetArch);
|
||||
IncludeName = "include";
|
||||
break;
|
||||
case ToolsetLayout::DevDivInternal:
|
||||
SubdirName = llvmArchToDevDivInternalArch(TargetArch);
|
||||
IncludeName = "inc";
|
||||
break;
|
||||
}
|
||||
|
||||
llvm::SmallString<256> Path(VCToolChainPath);
|
||||
switch (Type) {
|
||||
case SubDirectoryType::Bin:
|
||||
if (IsVS2017OrNewer) {
|
||||
bool HostIsX64 =
|
||||
if (VSLayout == ToolsetLayout::VS2017OrNewer) {
|
||||
const bool HostIsX64 =
|
||||
llvm::Triple(llvm::sys::getProcessTriple()).isArch64Bit();
|
||||
llvm::sys::path::append(Path, "bin", (HostIsX64 ? "HostX64" : "HostX86"),
|
||||
llvmArchToWindowsSDKArch(TargetArch));
|
||||
|
||||
} else {
|
||||
llvm::sys::path::append(Path, "bin", llvmArchToLegacyVCArch(TargetArch));
|
||||
const char *const HostName = HostIsX64 ? "HostX64" : "HostX86";
|
||||
llvm::sys::path::append(Path, "bin", HostName, SubdirName);
|
||||
} else { // OlderVS or DevDivInternal
|
||||
llvm::sys::path::append(Path, "bin", SubdirName);
|
||||
}
|
||||
break;
|
||||
case SubDirectoryType::Include:
|
||||
llvm::sys::path::append(Path, "include");
|
||||
llvm::sys::path::append(Path, IncludeName);
|
||||
break;
|
||||
case SubDirectoryType::Lib:
|
||||
llvm::sys::path::append(
|
||||
Path, "lib", IsVS2017OrNewer ? llvmArchToWindowsSDKArch(TargetArch)
|
||||
: llvmArchToLegacyVCArch(TargetArch));
|
||||
llvm::sys::path::append(Path, "lib", SubdirName);
|
||||
break;
|
||||
}
|
||||
return Path.str();
|
||||
|
@ -92,7 +92,12 @@ class LLVM_LIBRARY_VISIBILITY MSVCToolChain : public ToolChain {
|
||||
return getSubDirectoryPath(Type, getArch());
|
||||
}
|
||||
|
||||
bool getIsVS2017OrNewer() const { return IsVS2017OrNewer; }
|
||||
enum class ToolsetLayout {
|
||||
OlderVS,
|
||||
VS2017OrNewer,
|
||||
DevDivInternal,
|
||||
};
|
||||
bool getIsVS2017OrNewer() const { return VSLayout == ToolsetLayout::VS2017OrNewer; }
|
||||
|
||||
void
|
||||
AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
|
||||
@ -130,7 +135,7 @@ class LLVM_LIBRARY_VISIBILITY MSVCToolChain : public ToolChain {
|
||||
Tool *buildAssembler() const override;
|
||||
private:
|
||||
std::string VCToolChainPath;
|
||||
bool IsVS2017OrNewer = false;
|
||||
ToolsetLayout VSLayout = ToolsetLayout::OlderVS;
|
||||
CudaInstallationDetector CudaInstallation;
|
||||
};
|
||||
|
||||
|
@ -472,9 +472,14 @@ void WhitespaceManager::alignTrailingComments() {
|
||||
continue;
|
||||
|
||||
unsigned ChangeMinColumn = Changes[i].StartOfTokenColumn;
|
||||
unsigned ChangeMaxColumn = Style.ColumnLimit >= Changes[i].TokenLength
|
||||
? Style.ColumnLimit - Changes[i].TokenLength
|
||||
: ChangeMinColumn;
|
||||
unsigned ChangeMaxColumn;
|
||||
|
||||
if (Style.ColumnLimit == 0)
|
||||
ChangeMaxColumn = UINT_MAX;
|
||||
else if (Style.ColumnLimit >= Changes[i].TokenLength)
|
||||
ChangeMaxColumn = Style.ColumnLimit - Changes[i].TokenLength;
|
||||
else
|
||||
ChangeMaxColumn = ChangeMinColumn;
|
||||
|
||||
// If we don't create a replacement for this change, we have to consider
|
||||
// it to be immovable.
|
||||
|
@ -76,13 +76,7 @@ typedef intptr_t _sleb128_t;
|
||||
typedef uintptr_t _uleb128_t;
|
||||
|
||||
struct _Unwind_Context;
|
||||
#if defined(__arm__) && !(defined(__USING_SJLJ_EXCEPTIONS__) || defined(__ARM_DWARF_EH___))
|
||||
struct _Unwind_Control_Block;
|
||||
typedef struct _Unwind_Control_Block _Unwind_Exception; /* Alias */
|
||||
#else
|
||||
struct _Unwind_Exception;
|
||||
typedef struct _Unwind_Exception _Unwind_Exception;
|
||||
#endif
|
||||
typedef enum {
|
||||
_URC_NO_REASON = 0,
|
||||
#if defined(__arm__) && !defined(__USING_SJLJ_EXCEPTIONS__) && \
|
||||
@ -115,42 +109,8 @@ typedef enum {
|
||||
} _Unwind_Action;
|
||||
|
||||
typedef void (*_Unwind_Exception_Cleanup_Fn)(_Unwind_Reason_Code,
|
||||
_Unwind_Exception *);
|
||||
struct _Unwind_Exception *);
|
||||
|
||||
#if defined(__arm__) && !(defined(__USING_SJLJ_EXCEPTIONS__) || defined(__ARM_DWARF_EH___))
|
||||
typedef struct _Unwind_Control_Block _Unwind_Control_Block;
|
||||
typedef uint32_t _Unwind_EHT_Header;
|
||||
|
||||
struct _Unwind_Control_Block {
|
||||
uint64_t exception_class;
|
||||
void (*exception_cleanup)(_Unwind_Reason_Code, _Unwind_Control_Block *);
|
||||
/* unwinder cache (private fields for the unwinder's use) */
|
||||
struct {
|
||||
uint32_t reserved1; /* forced unwind stop function, 0 if not forced */
|
||||
uint32_t reserved2; /* personality routine */
|
||||
uint32_t reserved3; /* callsite */
|
||||
uint32_t reserved4; /* forced unwind stop argument */
|
||||
uint32_t reserved5;
|
||||
} unwinder_cache;
|
||||
/* propagation barrier cache (valid after phase 1) */
|
||||
struct {
|
||||
uint32_t sp;
|
||||
uint32_t bitpattern[5];
|
||||
} barrier_cache;
|
||||
/* cleanup cache (preserved over cleanup) */
|
||||
struct {
|
||||
uint32_t bitpattern[4];
|
||||
} cleanup_cache;
|
||||
/* personality cache (for personality's benefit) */
|
||||
struct {
|
||||
uint32_t fnstart; /* function start address */
|
||||
_Unwind_EHT_Header *ehtp; /* pointer to EHT entry header word */
|
||||
uint32_t additional; /* additional data */
|
||||
uint32_t reserved1;
|
||||
} pr_cache;
|
||||
long long int : 0; /* force alignment of next item to 8-byte boundary */
|
||||
};
|
||||
#else
|
||||
struct _Unwind_Exception {
|
||||
_Unwind_Exception_Class exception_class;
|
||||
_Unwind_Exception_Cleanup_Fn exception_cleanup;
|
||||
@ -160,24 +120,23 @@ struct _Unwind_Exception {
|
||||
* aligned". GCC has interpreted this to mean "use the maximum useful
|
||||
* alignment for the target"; so do we. */
|
||||
} __attribute__((__aligned__));
|
||||
#endif
|
||||
|
||||
typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn)(int, _Unwind_Action,
|
||||
_Unwind_Exception_Class,
|
||||
_Unwind_Exception *,
|
||||
struct _Unwind_Exception *,
|
||||
struct _Unwind_Context *,
|
||||
void *);
|
||||
|
||||
typedef _Unwind_Reason_Code (*_Unwind_Personality_Fn)(int, _Unwind_Action,
|
||||
_Unwind_Exception_Class,
|
||||
_Unwind_Exception *,
|
||||
struct _Unwind_Context *);
|
||||
typedef _Unwind_Reason_Code (*_Unwind_Personality_Fn)(
|
||||
int, _Unwind_Action, _Unwind_Exception_Class, struct _Unwind_Exception *,
|
||||
struct _Unwind_Context *);
|
||||
typedef _Unwind_Personality_Fn __personality_routine;
|
||||
|
||||
typedef _Unwind_Reason_Code (*_Unwind_Trace_Fn)(struct _Unwind_Context *,
|
||||
void *);
|
||||
|
||||
#if defined(__arm__) && !(defined(__USING_SJLJ_EXCEPTIONS__) || defined(__ARM_DWARF_EH___))
|
||||
#if defined(__arm__) && !defined(__APPLE__)
|
||||
|
||||
typedef enum {
|
||||
_UVRSC_CORE = 0, /* integer register */
|
||||
_UVRSC_VFP = 1, /* vfp */
|
||||
@ -199,12 +158,14 @@ typedef enum {
|
||||
_UVRSR_FAILED = 2
|
||||
} _Unwind_VRS_Result;
|
||||
|
||||
#if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__ARM_DWARF_EH__)
|
||||
typedef uint32_t _Unwind_State;
|
||||
#define _US_VIRTUAL_UNWIND_FRAME ((_Unwind_State)0)
|
||||
#define _US_UNWIND_FRAME_STARTING ((_Unwind_State)1)
|
||||
#define _US_UNWIND_FRAME_RESUME ((_Unwind_State)2)
|
||||
#define _US_ACTION_MASK ((_Unwind_State)3)
|
||||
#define _US_FORCE_UNWIND ((_Unwind_State)8)
|
||||
#endif
|
||||
|
||||
_Unwind_VRS_Result _Unwind_VRS_Get(struct _Unwind_Context *__context,
|
||||
_Unwind_VRS_RegClass __regclass,
|
||||
@ -263,12 +224,13 @@ _Unwind_Ptr _Unwind_GetRegionStart(struct _Unwind_Context *);
|
||||
|
||||
/* DWARF EH functions; currently not available on Darwin/ARM */
|
||||
#if !defined(__APPLE__) || !defined(__arm__)
|
||||
_Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Exception *);
|
||||
_Unwind_Reason_Code _Unwind_ForcedUnwind(_Unwind_Exception *, _Unwind_Stop_Fn,
|
||||
void *);
|
||||
void _Unwind_DeleteException(_Unwind_Exception *);
|
||||
void _Unwind_Resume(_Unwind_Exception *);
|
||||
_Unwind_Reason_Code _Unwind_Resume_or_Rethrow(_Unwind_Exception *);
|
||||
|
||||
_Unwind_Reason_Code _Unwind_RaiseException(struct _Unwind_Exception *);
|
||||
_Unwind_Reason_Code _Unwind_ForcedUnwind(struct _Unwind_Exception *,
|
||||
_Unwind_Stop_Fn, void *);
|
||||
void _Unwind_DeleteException(struct _Unwind_Exception *);
|
||||
void _Unwind_Resume(struct _Unwind_Exception *);
|
||||
_Unwind_Reason_Code _Unwind_Resume_or_Rethrow(struct _Unwind_Exception *);
|
||||
|
||||
#endif
|
||||
|
||||
@ -279,11 +241,11 @@ typedef struct SjLj_Function_Context *_Unwind_FunctionContext_t;
|
||||
|
||||
void _Unwind_SjLj_Register(_Unwind_FunctionContext_t);
|
||||
void _Unwind_SjLj_Unregister(_Unwind_FunctionContext_t);
|
||||
_Unwind_Reason_Code _Unwind_SjLj_RaiseException(_Unwind_Exception *);
|
||||
_Unwind_Reason_Code _Unwind_SjLj_ForcedUnwind(_Unwind_Exception *,
|
||||
_Unwind_Reason_Code _Unwind_SjLj_RaiseException(struct _Unwind_Exception *);
|
||||
_Unwind_Reason_Code _Unwind_SjLj_ForcedUnwind(struct _Unwind_Exception *,
|
||||
_Unwind_Stop_Fn, void *);
|
||||
void _Unwind_SjLj_Resume(_Unwind_Exception *);
|
||||
_Unwind_Reason_Code _Unwind_SjLj_Resume_or_Rethrow(_Unwind_Exception *);
|
||||
void _Unwind_SjLj_Resume(struct _Unwind_Exception *);
|
||||
_Unwind_Reason_Code _Unwind_SjLj_Resume_or_Rethrow(struct _Unwind_Exception *);
|
||||
|
||||
void *_Unwind_FindEnclosingFunction(void *);
|
||||
|
||||
|
@ -458,10 +458,16 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) {
|
||||
SourceMgr.setNumCreatedFIDsForFileID(CurPPLexer->getFileID(), NumFIDs);
|
||||
}
|
||||
|
||||
bool ExitedFromPredefinesFile = false;
|
||||
FileID ExitedFID;
|
||||
if (Callbacks && !isEndOfMacro && CurPPLexer)
|
||||
if (!isEndOfMacro && CurPPLexer) {
|
||||
ExitedFID = CurPPLexer->getFileID();
|
||||
|
||||
assert(PredefinesFileID.isValid() &&
|
||||
"HandleEndOfFile is called before PredefinesFileId is set");
|
||||
ExitedFromPredefinesFile = (PredefinesFileID == ExitedFID);
|
||||
}
|
||||
|
||||
if (LeavingSubmodule) {
|
||||
// We're done with this submodule.
|
||||
Module *M = LeaveSubmodule(/*ForPragma*/false);
|
||||
@ -489,6 +495,11 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) {
|
||||
PPCallbacks::ExitFile, FileType, ExitedFID);
|
||||
}
|
||||
|
||||
// Restore conditional stack from the preamble right after exiting from the
|
||||
// predefines file.
|
||||
if (ExitedFromPredefinesFile)
|
||||
replayPreambleConditionalStack();
|
||||
|
||||
// Client should lex another token unless we generated an EOM.
|
||||
return LeavingSubmodule;
|
||||
}
|
||||
|
@ -540,6 +540,8 @@ void Preprocessor::EnterMainSourceFile() {
|
||||
void Preprocessor::replayPreambleConditionalStack() {
|
||||
// Restore the conditional stack from the preamble, if there is one.
|
||||
if (PreambleConditionalStack.isReplaying()) {
|
||||
assert(CurPPLexer &&
|
||||
"CurPPLexer is null when calling replayPreambleConditionalStack.");
|
||||
CurPPLexer->setConditionalLevels(PreambleConditionalStack.getStack());
|
||||
PreambleConditionalStack.doneReplaying();
|
||||
}
|
||||
|
@ -516,8 +516,6 @@ void Parser::Initialize() {
|
||||
|
||||
// Prime the lexer look-ahead.
|
||||
ConsumeToken();
|
||||
|
||||
PP.replayPreambleConditionalStack();
|
||||
}
|
||||
|
||||
void Parser::LateTemplateParserCleanupCallback(void *P) {
|
||||
|
@ -5726,6 +5726,53 @@ static void DefineImplicitSpecialMember(Sema &S, CXXMethodDecl *MD,
|
||||
}
|
||||
}
|
||||
|
||||
/// Determine whether a type is permitted to be passed or returned in
|
||||
/// registers, per C++ [class.temporary]p3.
|
||||
static bool computeCanPassInRegisters(Sema &S, CXXRecordDecl *D) {
|
||||
if (D->isDependentType() || D->isInvalidDecl())
|
||||
return false;
|
||||
|
||||
// Per C++ [class.temporary]p3, the relevant condition is:
|
||||
// each copy constructor, move constructor, and destructor of X is
|
||||
// either trivial or deleted, and X has at least one non-deleted copy
|
||||
// or move constructor
|
||||
bool HasNonDeletedCopyOrMove = false;
|
||||
|
||||
if (D->needsImplicitCopyConstructor() &&
|
||||
!D->defaultedCopyConstructorIsDeleted()) {
|
||||
if (!D->hasTrivialCopyConstructor())
|
||||
return false;
|
||||
HasNonDeletedCopyOrMove = true;
|
||||
}
|
||||
|
||||
if (S.getLangOpts().CPlusPlus11 && D->needsImplicitMoveConstructor() &&
|
||||
!D->defaultedMoveConstructorIsDeleted()) {
|
||||
if (!D->hasTrivialMoveConstructor())
|
||||
return false;
|
||||
HasNonDeletedCopyOrMove = true;
|
||||
}
|
||||
|
||||
if (D->needsImplicitDestructor() && !D->defaultedDestructorIsDeleted() &&
|
||||
!D->hasTrivialDestructor())
|
||||
return false;
|
||||
|
||||
for (const CXXMethodDecl *MD : D->methods()) {
|
||||
if (MD->isDeleted())
|
||||
continue;
|
||||
|
||||
auto *CD = dyn_cast<CXXConstructorDecl>(MD);
|
||||
if (CD && CD->isCopyOrMoveConstructor())
|
||||
HasNonDeletedCopyOrMove = true;
|
||||
else if (!isa<CXXDestructorDecl>(MD))
|
||||
continue;
|
||||
|
||||
if (!MD->isTrivial())
|
||||
return false;
|
||||
}
|
||||
|
||||
return HasNonDeletedCopyOrMove;
|
||||
}
|
||||
|
||||
/// \brief Perform semantic checks on a class definition that has been
|
||||
/// completing, introducing implicitly-declared members, checking for
|
||||
/// abstract types, etc.
|
||||
@ -5870,6 +5917,8 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
|
||||
}
|
||||
|
||||
checkClassLevelDLLAttribute(Record);
|
||||
|
||||
Record->setCanPassInRegisters(computeCanPassInRegisters(*this, Record));
|
||||
}
|
||||
|
||||
/// Look up the special member function that would be called by a special
|
||||
@ -7496,8 +7545,7 @@ void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,
|
||||
reinterpret_cast<Decl**>(FieldCollector->getCurFields()),
|
||||
FieldCollector->getCurNumFields()), LBrac, RBrac, AttrList);
|
||||
|
||||
CheckCompletedCXXClass(
|
||||
dyn_cast_or_null<CXXRecordDecl>(TagDecl));
|
||||
CheckCompletedCXXClass(dyn_cast_or_null<CXXRecordDecl>(TagDecl));
|
||||
}
|
||||
|
||||
/// AddImplicitlyDeclaredMembersToClass - Adds any implicitly-declared
|
||||
@ -11929,8 +11977,10 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(
|
||||
Scope *S = getScopeForContext(ClassDecl);
|
||||
CheckImplicitSpecialMemberDeclaration(S, CopyConstructor);
|
||||
|
||||
if (ShouldDeleteSpecialMember(CopyConstructor, CXXCopyConstructor))
|
||||
if (ShouldDeleteSpecialMember(CopyConstructor, CXXCopyConstructor)) {
|
||||
ClassDecl->setImplicitCopyConstructorIsDeleted();
|
||||
SetDeclDeleted(CopyConstructor, ClassLoc);
|
||||
}
|
||||
|
||||
if (S)
|
||||
PushOnScopeChains(CopyConstructor, S, false);
|
||||
|
@ -872,7 +872,7 @@ SelectPropertyForSynthesisFromProtocols(Sema &S, SourceLocation AtLoc,
|
||||
}
|
||||
|
||||
QualType RHSType = S.Context.getCanonicalType(Property->getType());
|
||||
unsigned OriginalAttributes = Property->getPropertyAttributes();
|
||||
unsigned OriginalAttributes = Property->getPropertyAttributesAsWritten();
|
||||
enum MismatchKind {
|
||||
IncompatibleType = 0,
|
||||
HasNoExpectedAttribute,
|
||||
@ -890,7 +890,7 @@ SelectPropertyForSynthesisFromProtocols(Sema &S, SourceLocation AtLoc,
|
||||
SmallVector<MismatchingProperty, 4> Mismatches;
|
||||
for (ObjCPropertyDecl *Prop : Properties) {
|
||||
// Verify the property attributes.
|
||||
unsigned Attr = Prop->getPropertyAttributes();
|
||||
unsigned Attr = Prop->getPropertyAttributesAsWritten();
|
||||
if (Attr != OriginalAttributes) {
|
||||
auto Diag = [&](bool OriginalHasAttribute, StringRef AttributeName) {
|
||||
MismatchKind Kind = OriginalHasAttribute ? HasNoExpectedAttribute
|
||||
|
@ -1559,9 +1559,11 @@ void ASTDeclReader::ReadCXXDefinitionData(
|
||||
Data.HasUninitializedFields = Record.readInt();
|
||||
Data.HasInheritedConstructor = Record.readInt();
|
||||
Data.HasInheritedAssignment = Record.readInt();
|
||||
Data.NeedOverloadResolutionForCopyConstructor = Record.readInt();
|
||||
Data.NeedOverloadResolutionForMoveConstructor = Record.readInt();
|
||||
Data.NeedOverloadResolutionForMoveAssignment = Record.readInt();
|
||||
Data.NeedOverloadResolutionForDestructor = Record.readInt();
|
||||
Data.DefaultedCopyConstructorIsDeleted = Record.readInt();
|
||||
Data.DefaultedMoveConstructorIsDeleted = Record.readInt();
|
||||
Data.DefaultedMoveAssignmentIsDeleted = Record.readInt();
|
||||
Data.DefaultedDestructorIsDeleted = Record.readInt();
|
||||
@ -1570,6 +1572,7 @@ void ASTDeclReader::ReadCXXDefinitionData(
|
||||
Data.HasIrrelevantDestructor = Record.readInt();
|
||||
Data.HasConstexprNonCopyMoveConstructor = Record.readInt();
|
||||
Data.HasDefaultedDefaultConstructor = Record.readInt();
|
||||
Data.CanPassInRegisters = Record.readInt();
|
||||
Data.DefaultedDefaultConstructorIsConstexpr = Record.readInt();
|
||||
Data.HasConstexprDefaultConstructor = Record.readInt();
|
||||
Data.HasNonLiteralTypeFieldsOrBases = Record.readInt();
|
||||
@ -1697,9 +1700,11 @@ void ASTDeclReader::MergeDefinitionData(
|
||||
MATCH_FIELD(HasUninitializedFields)
|
||||
MATCH_FIELD(HasInheritedConstructor)
|
||||
MATCH_FIELD(HasInheritedAssignment)
|
||||
MATCH_FIELD(NeedOverloadResolutionForCopyConstructor)
|
||||
MATCH_FIELD(NeedOverloadResolutionForMoveConstructor)
|
||||
MATCH_FIELD(NeedOverloadResolutionForMoveAssignment)
|
||||
MATCH_FIELD(NeedOverloadResolutionForDestructor)
|
||||
MATCH_FIELD(DefaultedCopyConstructorIsDeleted)
|
||||
MATCH_FIELD(DefaultedMoveConstructorIsDeleted)
|
||||
MATCH_FIELD(DefaultedMoveAssignmentIsDeleted)
|
||||
MATCH_FIELD(DefaultedDestructorIsDeleted)
|
||||
@ -1708,6 +1713,7 @@ void ASTDeclReader::MergeDefinitionData(
|
||||
MATCH_FIELD(HasIrrelevantDestructor)
|
||||
OR_FIELD(HasConstexprNonCopyMoveConstructor)
|
||||
OR_FIELD(HasDefaultedDefaultConstructor)
|
||||
MATCH_FIELD(CanPassInRegisters)
|
||||
MATCH_FIELD(DefaultedDefaultConstructorIsConstexpr)
|
||||
OR_FIELD(HasConstexprDefaultConstructor)
|
||||
MATCH_FIELD(HasNonLiteralTypeFieldsOrBases)
|
||||
|
@ -5874,9 +5874,11 @@ void ASTRecordWriter::AddCXXDefinitionData(const CXXRecordDecl *D) {
|
||||
Record->push_back(Data.HasUninitializedFields);
|
||||
Record->push_back(Data.HasInheritedConstructor);
|
||||
Record->push_back(Data.HasInheritedAssignment);
|
||||
Record->push_back(Data.NeedOverloadResolutionForCopyConstructor);
|
||||
Record->push_back(Data.NeedOverloadResolutionForMoveConstructor);
|
||||
Record->push_back(Data.NeedOverloadResolutionForMoveAssignment);
|
||||
Record->push_back(Data.NeedOverloadResolutionForDestructor);
|
||||
Record->push_back(Data.DefaultedCopyConstructorIsDeleted);
|
||||
Record->push_back(Data.DefaultedMoveConstructorIsDeleted);
|
||||
Record->push_back(Data.DefaultedMoveAssignmentIsDeleted);
|
||||
Record->push_back(Data.DefaultedDestructorIsDeleted);
|
||||
@ -5885,6 +5887,7 @@ void ASTRecordWriter::AddCXXDefinitionData(const CXXRecordDecl *D) {
|
||||
Record->push_back(Data.HasIrrelevantDestructor);
|
||||
Record->push_back(Data.HasConstexprNonCopyMoveConstructor);
|
||||
Record->push_back(Data.HasDefaultedDefaultConstructor);
|
||||
Record->push_back(Data.CanPassInRegisters);
|
||||
Record->push_back(Data.DefaultedDefaultConstructorIsConstexpr);
|
||||
Record->push_back(Data.HasConstexprDefaultConstructor);
|
||||
Record->push_back(Data.HasNonLiteralTypeFieldsOrBases);
|
||||
|
@ -409,6 +409,19 @@ class RegionStoreManager : public StoreManager {
|
||||
|
||||
// BindDefault is only used to initialize a region with a default value.
|
||||
StoreRef BindDefault(Store store, const MemRegion *R, SVal V) override {
|
||||
// FIXME: The offsets of empty bases can be tricky because of
|
||||
// of the so called "empty base class optimization".
|
||||
// If a base class has been optimized out
|
||||
// we should not try to create a binding, otherwise we should.
|
||||
// Unfortunately, at the moment ASTRecordLayout doesn't expose
|
||||
// the actual sizes of the empty bases
|
||||
// and trying to infer them from offsets/alignments
|
||||
// seems to be error-prone and non-trivial because of the trailing padding.
|
||||
// As a temporary mitigation we don't create bindings for empty bases.
|
||||
if (R->getKind() == MemRegion::CXXBaseObjectRegionKind &&
|
||||
cast<CXXBaseObjectRegion>(R)->getDecl()->isEmpty())
|
||||
return StoreRef(store, *this);
|
||||
|
||||
RegionBindingsRef B = getRegionBindings(store);
|
||||
assert(!B.lookup(R, BindingKey::Direct));
|
||||
|
||||
|
@ -704,3 +704,20 @@ namespace PR19579 {
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
namespace NoCrashOnEmptyBaseOptimization {
|
||||
struct NonEmptyBase {
|
||||
int X;
|
||||
explicit NonEmptyBase(int X) : X(X) {}
|
||||
};
|
||||
|
||||
struct EmptyBase {};
|
||||
|
||||
struct S : NonEmptyBase, EmptyBase {
|
||||
S() : NonEmptyBase(0), EmptyBase() {}
|
||||
};
|
||||
|
||||
void testSCtorNoCrash() {
|
||||
S s;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s
|
||||
// RUN: %clang_cc1 -std=c++11 -triple x86_64-windows-msvc -emit-llvm -o - %s | FileCheck %s -check-prefix=WIN64
|
||||
// RUN: %clang_cc1 -std=c++11 -triple x86_64-windows-msvc -emit-llvm -o - %s -fms-compatibility -fms-compatibility-version=18 | FileCheck %s -check-prefix=WIN64 -check-prefix=WIN64-18
|
||||
// RUN: %clang_cc1 -std=c++11 -triple x86_64-windows-msvc -emit-llvm -o - %s -fms-compatibility -fms-compatibility-version=19 | FileCheck %s -check-prefix=WIN64 -check-prefix=WIN64-19
|
||||
|
||||
namespace trivial {
|
||||
// Trivial structs should be passed directly.
|
||||
@ -52,12 +53,11 @@ void foo(A);
|
||||
void bar() {
|
||||
foo({});
|
||||
}
|
||||
// FIXME: The copy ctor is implicitly deleted.
|
||||
// CHECK-DISABLED-LABEL: define void @_ZN9move_ctor3barEv()
|
||||
// CHECK-DISABLED: call void @_Z{{.*}}C1Ev(
|
||||
// CHECK-DISABLED-NOT: call
|
||||
// CHECK-DISABLED: call void @_ZN9move_ctor3fooENS_1AE(%"struct.move_ctor::A"* %{{.*}})
|
||||
// CHECK-DISABLED-LABEL: declare void @_ZN9move_ctor3fooENS_1AE(%"struct.move_ctor::A"*)
|
||||
// CHECK-LABEL: define void @_ZN9move_ctor3barEv()
|
||||
// CHECK: call void @_Z{{.*}}C1Ev(
|
||||
// CHECK-NOT: call
|
||||
// CHECK: call void @_ZN9move_ctor3fooENS_1AE(%"struct.move_ctor::A"* %{{.*}})
|
||||
// CHECK-LABEL: declare void @_ZN9move_ctor3fooENS_1AE(%"struct.move_ctor::A"*)
|
||||
|
||||
// WIN64-LABEL: declare void @"\01?foo@move_ctor@@YAXUA@1@@Z"(%"struct.move_ctor::A"*)
|
||||
}
|
||||
@ -73,12 +73,11 @@ void foo(A);
|
||||
void bar() {
|
||||
foo({});
|
||||
}
|
||||
// FIXME: The copy ctor is deleted.
|
||||
// CHECK-DISABLED-LABEL: define void @_ZN11all_deleted3barEv()
|
||||
// CHECK-DISABLED: call void @_Z{{.*}}C1Ev(
|
||||
// CHECK-DISABLED-NOT: call
|
||||
// CHECK-DISABLED: call void @_ZN11all_deleted3fooENS_1AE(%"struct.all_deleted::A"* %{{.*}})
|
||||
// CHECK-DISABLED-LABEL: declare void @_ZN11all_deleted3fooENS_1AE(%"struct.all_deleted::A"*)
|
||||
// CHECK-LABEL: define void @_ZN11all_deleted3barEv()
|
||||
// CHECK: call void @_Z{{.*}}C1Ev(
|
||||
// CHECK-NOT: call
|
||||
// CHECK: call void @_ZN11all_deleted3fooENS_1AE(%"struct.all_deleted::A"* %{{.*}})
|
||||
// CHECK-LABEL: declare void @_ZN11all_deleted3fooENS_1AE(%"struct.all_deleted::A"*)
|
||||
|
||||
// WIN64-LABEL: declare void @"\01?foo@all_deleted@@YAXUA@1@@Z"(%"struct.all_deleted::A"*)
|
||||
}
|
||||
@ -93,14 +92,15 @@ void foo(A);
|
||||
void bar() {
|
||||
foo({});
|
||||
}
|
||||
// FIXME: The copy and move ctors are implicitly deleted.
|
||||
// CHECK-DISABLED-LABEL: define void @_ZN18implicitly_deleted3barEv()
|
||||
// CHECK-DISABLED: call void @_Z{{.*}}C1Ev(
|
||||
// CHECK-DISABLED-NOT: call
|
||||
// CHECK-DISABLED: call void @_ZN18implicitly_deleted3fooENS_1AE(%"struct.implicitly_deleted::A"* %{{.*}})
|
||||
// CHECK-DISABLED-LABEL: declare void @_ZN18implicitly_deleted3fooENS_1AE(%"struct.implicitly_deleted::A"*)
|
||||
// CHECK-LABEL: define void @_ZN18implicitly_deleted3barEv()
|
||||
// CHECK: call void @_Z{{.*}}C1Ev(
|
||||
// CHECK-NOT: call
|
||||
// CHECK: call void @_ZN18implicitly_deleted3fooENS_1AE(%"struct.implicitly_deleted::A"* %{{.*}})
|
||||
// CHECK-LABEL: declare void @_ZN18implicitly_deleted3fooENS_1AE(%"struct.implicitly_deleted::A"*)
|
||||
|
||||
// WIN64-LABEL: declare void @"\01?foo@implicitly_deleted@@YAXUA@1@@Z"(%"struct.implicitly_deleted::A"*)
|
||||
// In MSVC 2013, the copy ctor is not deleted by a move assignment. In MSVC 2015, it is.
|
||||
// WIN64-18-LABEL: declare void @"\01?foo@implicitly_deleted@@YAXUA@1@@Z"(i64
|
||||
// WIN64-19-LABEL: declare void @"\01?foo@implicitly_deleted@@YAXUA@1@@Z"(%"struct.implicitly_deleted::A"*)
|
||||
}
|
||||
|
||||
namespace one_deleted {
|
||||
@ -113,12 +113,11 @@ void foo(A);
|
||||
void bar() {
|
||||
foo({});
|
||||
}
|
||||
// FIXME: The copy constructor is implicitly deleted.
|
||||
// CHECK-DISABLED-LABEL: define void @_ZN11one_deleted3barEv()
|
||||
// CHECK-DISABLED: call void @_Z{{.*}}C1Ev(
|
||||
// CHECK-DISABLED-NOT: call
|
||||
// CHECK-DISABLED: call void @_ZN11one_deleted3fooENS_1AE(%"struct.one_deleted::A"* %{{.*}})
|
||||
// CHECK-DISABLED-LABEL: declare void @_ZN11one_deleted3fooENS_1AE(%"struct.one_deleted::A"*)
|
||||
// CHECK-LABEL: define void @_ZN11one_deleted3barEv()
|
||||
// CHECK: call void @_Z{{.*}}C1Ev(
|
||||
// CHECK-NOT: call
|
||||
// CHECK: call void @_ZN11one_deleted3fooENS_1AE(%"struct.one_deleted::A"* %{{.*}})
|
||||
// CHECK-LABEL: declare void @_ZN11one_deleted3fooENS_1AE(%"struct.one_deleted::A"*)
|
||||
|
||||
// WIN64-LABEL: declare void @"\01?foo@one_deleted@@YAXUA@1@@Z"(%"struct.one_deleted::A"*)
|
||||
}
|
||||
@ -195,12 +194,10 @@ void foo(B);
|
||||
void bar() {
|
||||
foo({});
|
||||
}
|
||||
// FIXME: This class has a non-trivial copy ctor and a trivial copy ctor. It's
|
||||
// not clear whether we should pass by address or in registers.
|
||||
// CHECK-DISABLED-LABEL: define void @_ZN14two_copy_ctors3barEv()
|
||||
// CHECK-DISABLED: call void @_Z{{.*}}C1Ev(
|
||||
// CHECK-DISABLED: call void @_ZN14two_copy_ctors3fooENS_1BE(%"struct.two_copy_ctors::B"* %{{.*}})
|
||||
// CHECK-DISABLED-LABEL: declare void @_ZN14two_copy_ctors3fooENS_1BE(%"struct.two_copy_ctors::B"*)
|
||||
// CHECK-LABEL: define void @_ZN14two_copy_ctors3barEv()
|
||||
// CHECK: call void @_Z{{.*}}C1Ev(
|
||||
// CHECK: call void @_ZN14two_copy_ctors3fooENS_1BE(%"struct.two_copy_ctors::B"* %{{.*}})
|
||||
// CHECK-LABEL: declare void @_ZN14two_copy_ctors3fooENS_1BE(%"struct.two_copy_ctors::B"*)
|
||||
|
||||
// WIN64-LABEL: declare void @"\01?foo@two_copy_ctors@@YAXUB@1@@Z"(%"struct.two_copy_ctors::B"*)
|
||||
}
|
||||
@ -212,6 +209,7 @@ struct A {
|
||||
void *p;
|
||||
};
|
||||
void *foo(A a) { return a.p; }
|
||||
// CHECK-LABEL: define i8* @_ZN15definition_only3fooENS_1AE(%"struct.definition_only::A"*
|
||||
// WIN64-LABEL: define i8* @"\01?foo@definition_only@@YAPEAXUA@1@@Z"(%"struct.definition_only::A"*
|
||||
}
|
||||
|
||||
@ -226,6 +224,7 @@ struct A {
|
||||
B b;
|
||||
};
|
||||
void *foo(A a) { return a.b.p; }
|
||||
// CHECK-LABEL: define i8* @_ZN17deleted_by_member3fooENS_1AE(%"struct.deleted_by_member::A"*
|
||||
// WIN64-LABEL: define i8* @"\01?foo@deleted_by_member@@YAPEAXUA@1@@Z"(%"struct.deleted_by_member::A"*
|
||||
}
|
||||
|
||||
@ -239,6 +238,7 @@ struct A : B {
|
||||
A();
|
||||
};
|
||||
void *foo(A a) { return a.p; }
|
||||
// CHECK-LABEL: define i8* @_ZN15deleted_by_base3fooENS_1AE(%"struct.deleted_by_base::A"*
|
||||
// WIN64-LABEL: define i8* @"\01?foo@deleted_by_base@@YAPEAXUA@1@@Z"(%"struct.deleted_by_base::A"*
|
||||
}
|
||||
|
||||
@ -253,6 +253,7 @@ struct A {
|
||||
B b;
|
||||
};
|
||||
void *foo(A a) { return a.b.p; }
|
||||
// CHECK-LABEL: define i8* @_ZN22deleted_by_member_copy3fooENS_1AE(%"struct.deleted_by_member_copy::A"*
|
||||
// WIN64-LABEL: define i8* @"\01?foo@deleted_by_member_copy@@YAPEAXUA@1@@Z"(%"struct.deleted_by_member_copy::A"*
|
||||
}
|
||||
|
||||
@ -266,6 +267,7 @@ struct A : B {
|
||||
A();
|
||||
};
|
||||
void *foo(A a) { return a.p; }
|
||||
// CHECK-LABEL: define i8* @_ZN20deleted_by_base_copy3fooENS_1AE(%"struct.deleted_by_base_copy::A"*
|
||||
// WIN64-LABEL: define i8* @"\01?foo@deleted_by_base_copy@@YAPEAXUA@1@@Z"(%"struct.deleted_by_base_copy::A"*
|
||||
}
|
||||
|
||||
@ -275,6 +277,75 @@ struct A {
|
||||
A(const A &o) = delete;
|
||||
void *p;
|
||||
};
|
||||
// CHECK-LABEL: define i8* @_ZN15explicit_delete3fooENS_1AE(%"struct.explicit_delete::A"*
|
||||
// WIN64-LABEL: define i8* @"\01?foo@explicit_delete@@YAPEAXUA@1@@Z"(%"struct.explicit_delete::A"*
|
||||
void *foo(A a) { return a.p; }
|
||||
}
|
||||
|
||||
namespace implicitly_deleted_copy_ctor {
|
||||
struct A {
|
||||
// No move ctor due to copy assignment.
|
||||
A &operator=(const A&);
|
||||
// Deleted copy ctor due to rvalue ref member.
|
||||
int &&ref;
|
||||
};
|
||||
// CHECK-LABEL: define {{.*}} @_ZN28implicitly_deleted_copy_ctor3fooENS_1AE(%"struct.implicitly_deleted_copy_ctor::A"*
|
||||
// WIN64-LABEL: define {{.*}} @"\01?foo@implicitly_deleted_copy_ctor@@YAAEAHUA@1@@Z"(%"struct.implicitly_deleted_copy_ctor::A"*
|
||||
int &foo(A a) { return a.ref; }
|
||||
|
||||
struct B {
|
||||
// Passed direct: has non-deleted trivial copy ctor.
|
||||
B &operator=(const B&);
|
||||
int &ref;
|
||||
};
|
||||
int &foo(B b) { return b.ref; }
|
||||
// CHECK-LABEL: define {{.*}} @_ZN28implicitly_deleted_copy_ctor3fooENS_1BE(i32*
|
||||
// WIN64-LABEL: define {{.*}} @"\01?foo@implicitly_deleted_copy_ctor@@YAAEAHUB@1@@Z"(i64
|
||||
|
||||
struct X { X(const X&); };
|
||||
struct Y { Y(const Y&) = default; };
|
||||
|
||||
union C {
|
||||
C &operator=(const C&);
|
||||
// Passed indirect: copy ctor deleted due to variant member with nontrivial copy ctor.
|
||||
X x;
|
||||
int n;
|
||||
};
|
||||
int foo(C c) { return c.n; }
|
||||
// CHECK-LABEL: define {{.*}} @_ZN28implicitly_deleted_copy_ctor3fooENS_1CE(%"union.implicitly_deleted_copy_ctor::C"*
|
||||
// WIN64-LABEL: define {{.*}} @"\01?foo@implicitly_deleted_copy_ctor@@YAHTC@1@@Z"(%"union.implicitly_deleted_copy_ctor::C"*
|
||||
|
||||
struct D {
|
||||
D &operator=(const D&);
|
||||
// Passed indirect: copy ctor deleted due to variant member with nontrivial copy ctor.
|
||||
union {
|
||||
X x;
|
||||
int n;
|
||||
};
|
||||
};
|
||||
int foo(D d) { return d.n; }
|
||||
// CHECK-LABEL: define {{.*}} @_ZN28implicitly_deleted_copy_ctor3fooENS_1DE(%"struct.implicitly_deleted_copy_ctor::D"*
|
||||
// WIN64-LABEL: define {{.*}} @"\01?foo@implicitly_deleted_copy_ctor@@YAHUD@1@@Z"(%"struct.implicitly_deleted_copy_ctor::D"*
|
||||
|
||||
union E {
|
||||
// Passed direct: has non-deleted trivial copy ctor.
|
||||
E &operator=(const E&);
|
||||
Y y;
|
||||
int n;
|
||||
};
|
||||
int foo(E e) { return e.n; }
|
||||
// CHECK-LABEL: define {{.*}} @_ZN28implicitly_deleted_copy_ctor3fooENS_1EE(i32
|
||||
// WIN64-LABEL: define {{.*}} @"\01?foo@implicitly_deleted_copy_ctor@@YAHTE@1@@Z"(i32
|
||||
|
||||
struct F {
|
||||
// Passed direct: has non-deleted trivial copy ctor.
|
||||
F &operator=(const F&);
|
||||
union {
|
||||
Y y;
|
||||
int n;
|
||||
};
|
||||
};
|
||||
int foo(F f) { return f.n; }
|
||||
// CHECK-LABEL: define {{.*}} @_ZN28implicitly_deleted_copy_ctor3fooENS_1FE(i32
|
||||
// WIN64-LABEL: define {{.*}} @"\01?foo@implicitly_deleted_copy_ctor@@YAHUF@1@@Z"(i32
|
||||
}
|
||||
|
@ -73,6 +73,10 @@
|
||||
// RUN: FileCheck -check-prefix=ARM64-APPLE %s
|
||||
// ARM64-APPLE: -munwind-table
|
||||
|
||||
// RUN: %clang -target arm64-apple-ios10 -fno-exceptions -### -S %s -arch arm64 2>&1 | \
|
||||
// RUN: FileCheck -check-prefix=ARM64-APPLE-EXCEP %s
|
||||
// ARM64-APPLE-EXCEP-NOT: -munwind-table
|
||||
|
||||
// RUN: %clang -target armv7k-apple-watchos4.0 -### -S %s -arch armv7k 2>&1 | \
|
||||
// RUN: FileCheck -check-prefix=ARMV7K-APPLE %s
|
||||
// ARMV7K-APPLE: -munwind-table
|
||||
|
12
test/Index/preamble-conditionals-crash.cpp
Normal file
12
test/Index/preamble-conditionals-crash.cpp
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef HEADER_GUARD
|
||||
|
||||
#define FOO int aba;
|
||||
FOO
|
||||
|
||||
#endif
|
||||
// RUN: env CINDEXTEST_EDITING=1 c-index-test -test-load-source-reparse 5 \
|
||||
// RUN: local -std=c++14 %s 2>&1 \
|
||||
// RUN: | FileCheck %s --implicit-check-not "libclang: crash detected" \
|
||||
// RUN: --implicit-check-not "error:"
|
||||
// CHECK: macro expansion=FOO:3:9 Extent=[4:1 - 4:4]
|
||||
// CHECK: VarDecl=aba:4:1 (Definition) Extent=[4:1 - 4:4]
|
8
test/Index/preamble-conditionals.cpp
Normal file
8
test/Index/preamble-conditionals.cpp
Normal file
@ -0,0 +1,8 @@
|
||||
// RUN: env CINDEXTEST_EDITING=1 c-index-test -test-load-source local %s 2>&1 \
|
||||
// RUN: | FileCheck %s --implicit-check-not "error:"
|
||||
#ifndef FOO_H
|
||||
#define FOO_H
|
||||
|
||||
void foo();
|
||||
|
||||
#endif
|
@ -225,3 +225,30 @@ __attribute__((objc_root_class))
|
||||
@implementation TypeVsSetter
|
||||
@synthesize prop; // expected-note {{property synthesized here}}
|
||||
@end
|
||||
|
||||
@protocol AutoStrongProp
|
||||
|
||||
@property (nonatomic, readonly) NSObject *prop;
|
||||
|
||||
@end
|
||||
|
||||
@protocol AutoStrongProp_Internal <AutoStrongProp>
|
||||
|
||||
// This property gets the 'strong' attribute automatically.
|
||||
@property (nonatomic, readwrite) NSObject *prop;
|
||||
|
||||
@end
|
||||
|
||||
@interface SynthesizeWithImplicitStrongNoError : NSObject <AutoStrongProp>
|
||||
@end
|
||||
|
||||
@interface SynthesizeWithImplicitStrongNoError () <AutoStrongProp_Internal>
|
||||
|
||||
@end
|
||||
|
||||
@implementation SynthesizeWithImplicitStrongNoError
|
||||
|
||||
// no error, 'strong' is implicit in the 'readwrite' property.
|
||||
@synthesize prop = _prop;
|
||||
|
||||
@end
|
||||
|
@ -1108,26 +1108,35 @@ TEST(ConstructorDeclaration, IsExplicit) {
|
||||
}
|
||||
|
||||
TEST(ConstructorDeclaration, Kinds) {
|
||||
EXPECT_TRUE(matches("struct S { S(); };",
|
||||
cxxConstructorDecl(isDefaultConstructor())));
|
||||
EXPECT_TRUE(notMatches("struct S { S(); };",
|
||||
cxxConstructorDecl(isCopyConstructor())));
|
||||
EXPECT_TRUE(notMatches("struct S { S(); };",
|
||||
cxxConstructorDecl(isMoveConstructor())));
|
||||
EXPECT_TRUE(matches(
|
||||
"struct S { S(); };",
|
||||
cxxConstructorDecl(isDefaultConstructor(), unless(isImplicit()))));
|
||||
EXPECT_TRUE(notMatches(
|
||||
"struct S { S(); };",
|
||||
cxxConstructorDecl(isCopyConstructor(), unless(isImplicit()))));
|
||||
EXPECT_TRUE(notMatches(
|
||||
"struct S { S(); };",
|
||||
cxxConstructorDecl(isMoveConstructor(), unless(isImplicit()))));
|
||||
|
||||
EXPECT_TRUE(notMatches("struct S { S(const S&); };",
|
||||
cxxConstructorDecl(isDefaultConstructor())));
|
||||
EXPECT_TRUE(matches("struct S { S(const S&); };",
|
||||
cxxConstructorDecl(isCopyConstructor())));
|
||||
EXPECT_TRUE(notMatches("struct S { S(const S&); };",
|
||||
cxxConstructorDecl(isMoveConstructor())));
|
||||
EXPECT_TRUE(notMatches(
|
||||
"struct S { S(const S&); };",
|
||||
cxxConstructorDecl(isDefaultConstructor(), unless(isImplicit()))));
|
||||
EXPECT_TRUE(matches(
|
||||
"struct S { S(const S&); };",
|
||||
cxxConstructorDecl(isCopyConstructor(), unless(isImplicit()))));
|
||||
EXPECT_TRUE(notMatches(
|
||||
"struct S { S(const S&); };",
|
||||
cxxConstructorDecl(isMoveConstructor(), unless(isImplicit()))));
|
||||
|
||||
EXPECT_TRUE(notMatches("struct S { S(S&&); };",
|
||||
cxxConstructorDecl(isDefaultConstructor())));
|
||||
EXPECT_TRUE(notMatches("struct S { S(S&&); };",
|
||||
cxxConstructorDecl(isCopyConstructor())));
|
||||
EXPECT_TRUE(matches("struct S { S(S&&); };",
|
||||
cxxConstructorDecl(isMoveConstructor())));
|
||||
EXPECT_TRUE(notMatches(
|
||||
"struct S { S(S&&); };",
|
||||
cxxConstructorDecl(isDefaultConstructor(), unless(isImplicit()))));
|
||||
EXPECT_TRUE(notMatches(
|
||||
"struct S { S(S&&); };",
|
||||
cxxConstructorDecl(isCopyConstructor(), unless(isImplicit()))));
|
||||
EXPECT_TRUE(matches(
|
||||
"struct S { S(S&&); };",
|
||||
cxxConstructorDecl(isMoveConstructor(), unless(isImplicit()))));
|
||||
}
|
||||
|
||||
TEST(ConstructorDeclaration, IsUserProvided) {
|
||||
|
@ -2267,6 +2267,13 @@ TEST_F(FormatTestComments, AlignTrailingComments) {
|
||||
"int k; // line longg long",
|
||||
getLLVMStyleWithColumns(20)));
|
||||
|
||||
// Always align if ColumnLimit = 0
|
||||
EXPECT_EQ("int i, j; // line 1\n"
|
||||
"int k; // line longg long",
|
||||
format("int i, j; // line 1\n"
|
||||
"int k; // line longg long",
|
||||
getLLVMStyleWithColumns(0)));
|
||||
|
||||
// Align comment line sections aligned with the next token with the next
|
||||
// token.
|
||||
EXPECT_EQ("class A {\n"
|
||||
|
Loading…
Reference in New Issue
Block a user