From a75fa8aaf2005c6cb7561a9aa5129a38075939a4 Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Thu, 24 Aug 2017 16:35:14 +0000 Subject: Vendor import of clang release_50 branch r311606: https://llvm.org/svn/llvm-project/cfe/branches/release_50@311606 --- docs/ReleaseNotes.rst | 148 ++++++++++++++++++++- include/clang/AST/DeclCXX.h | 74 ++++++++++- include/clang/Lex/Preprocessor.h | 8 +- lib/AST/ASTImporter.cpp | 5 + lib/AST/DeclCXX.cpp | 34 ++++- lib/CodeGen/CGCXXABI.cpp | 31 +---- lib/CodeGen/ItaniumCXXABI.cpp | 13 +- lib/CodeGen/MicrosoftCXXABI.cpp | 52 ++++---- lib/Driver/ToolChains/Darwin.cpp | 7 +- lib/Driver/ToolChains/MSVC.cpp | 85 ++++++++---- lib/Driver/ToolChains/MSVC.h | 9 +- lib/Format/WhitespaceManager.cpp | 11 +- lib/Headers/unwind.h | 80 +++-------- lib/Lex/PPLexerChange.cpp | 13 +- lib/Lex/Preprocessor.cpp | 2 + lib/Parse/Parser.cpp | 2 - lib/Sema/SemaDeclCXX.cpp | 56 +++++++- lib/Sema/SemaObjCProperty.cpp | 4 +- lib/Serialization/ASTReaderDecl.cpp | 6 + lib/Serialization/ASTWriter.cpp | 3 + lib/StaticAnalyzer/Core/RegionStore.cpp | 13 ++ test/Analysis/ctor.mm | 17 +++ test/CodeGenCXX/uncopyable-args.cpp | 137 ++++++++++++++----- test/Driver/clang-translation.c | 4 + test/Index/preamble-conditionals-crash.cpp | 12 ++ test/Index/preamble-conditionals.cpp | 8 ++ test/SemaObjC/arc-property-decl-attrs.m | 27 ++++ unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp | 49 ++++--- unittests/Format/FormatTestComments.cpp | 7 + 29 files changed, 686 insertions(+), 231 deletions(-) create mode 100644 test/Index/preamble-conditionals-crash.cpp create mode 100644 test/Index/preamble-conditionals.cpp diff --git a/docs/ReleaseNotes.rst b/docs/ReleaseNotes.rst index 982abb024525..5f9991439697 100644 --- a/docs/ReleaseNotes.rst +++ b/docs/ReleaseNotes.rst @@ -49,6 +49,15 @@ Major New Features - ... +C++ coroutines +^^^^^^^^^^^^^^ +`C++ coroutines TS +`_ +implementation has landed. Use ``-fcoroutines-ts -stdlib=libc++`` to enable +coroutine support. Here is `an example +`_ 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 + void appendValue(std::vector &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 + void appendValue(std::vector> &dest, const T &value) { + dest.at(0). // Libclang fails to provide completion results after '.' + } Static Analyzer --------------- diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 9d64f0244ec3..c39eaee9b124 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -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 @@ public: 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 @@ public: /// \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 @@ public: 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 @@ public: 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 { diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index a058fbfbb4cf..dba4b80f6071 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/include/clang/Lex/Preprocessor.h @@ -1048,10 +1048,6 @@ public: /// 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 @@ public: } 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(); diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index 6e33b98d2f18..2c0bb11cc4bc 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -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 diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index 1caceab85eea..5782b7b56c96 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -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()) { diff --git a/lib/CodeGen/CGCXXABI.cpp b/lib/CodeGen/CGCXXABI.cpp index e29e525edd24..033258643ddf 100644 --- a/lib/CodeGen/CGCXXABI.cpp +++ b/lib/CodeGen/CGCXXABI.cpp @@ -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) { diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp index c82b9677eacf..e7963674fc29 100644 --- a/lib/CodeGen/ItaniumCXXABI.cpp +++ b/lib/CodeGen/ItaniumCXXABI.cpp @@ -63,11 +63,8 @@ public: 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; diff --git a/lib/CodeGen/MicrosoftCXXABI.cpp b/lib/CodeGen/MicrosoftCXXABI.cpp index 78b510bb4665..1bd2937e4747 100644 --- a/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/lib/CodeGen/MicrosoftCXXABI.cpp @@ -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; } diff --git a/lib/Driver/ToolChains/Darwin.cpp b/lib/Driver/ToolChains/Darwin.cpp index 6b7f0c71dfb7..32103a6120d4 100644 --- a/lib/Driver/ToolChains/Darwin.cpp +++ b/lib/Driver/ToolChains/Darwin.cpp @@ -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 { diff --git a/lib/Driver/ToolChains/MSVC.cpp b/lib/Driver/ToolChains/MSVC.cpp index b871c856d2a0..7978a6941cb8 100644 --- a/lib/Driver/ToolChains/MSVC.cpp +++ b/lib/Driver/ToolChains/MSVC.cpp @@ -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 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 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(); diff --git a/lib/Driver/ToolChains/MSVC.h b/lib/Driver/ToolChains/MSVC.h index d153691a5c90..854f88a36fd2 100644 --- a/lib/Driver/ToolChains/MSVC.h +++ b/lib/Driver/ToolChains/MSVC.h @@ -92,7 +92,12 @@ public: 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 @@ protected: Tool *buildAssembler() const override; private: std::string VCToolChainPath; - bool IsVS2017OrNewer = false; + ToolsetLayout VSLayout = ToolsetLayout::OlderVS; CudaInstallationDetector CudaInstallation; }; diff --git a/lib/Format/WhitespaceManager.cpp b/lib/Format/WhitespaceManager.cpp index 4b4fd13145fb..b1a5f1eab552 100644 --- a/lib/Format/WhitespaceManager.cpp +++ b/lib/Format/WhitespaceManager.cpp @@ -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. diff --git a/lib/Headers/unwind.h b/lib/Headers/unwind.h index e94b00b57c26..4f74a3478740 100644 --- a/lib/Headers/unwind.h +++ b/lib/Headers/unwind.h @@ -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 *); - -#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 *); + 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 *); diff --git a/lib/Lex/PPLexerChange.cpp b/lib/Lex/PPLexerChange.cpp index 5a589d6a17b3..36d7028da688 100644 --- a/lib/Lex/PPLexerChange.cpp +++ b/lib/Lex/PPLexerChange.cpp @@ -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; } diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp index d1dc8e1c0010..7979be773aa1 100644 --- a/lib/Lex/Preprocessor.cpp +++ b/lib/Lex/Preprocessor.cpp @@ -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(); } diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index 4aa9a5971929..1ed7ef966358 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -516,8 +516,6 @@ void Parser::Initialize() { // Prime the lexer look-ahead. ConsumeToken(); - - PP.replayPreambleConditionalStack(); } void Parser::LateTemplateParserCleanupCallback(void *P) { diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index e9070881afe4..c05e5f020708 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -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(MD); + if (CD && CD->isCopyOrMoveConstructor()) + HasNonDeletedCopyOrMove = true; + else if (!isa(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(FieldCollector->getCurFields()), FieldCollector->getCurNumFields()), LBrac, RBrac, AttrList); - CheckCompletedCXXClass( - dyn_cast_or_null(TagDecl)); + CheckCompletedCXXClass(dyn_cast_or_null(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); diff --git a/lib/Sema/SemaObjCProperty.cpp b/lib/Sema/SemaObjCProperty.cpp index e1e85dfd5e55..bfb0071a54f9 100644 --- a/lib/Sema/SemaObjCProperty.cpp +++ b/lib/Sema/SemaObjCProperty.cpp @@ -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 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 diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index abed2586561a..085341571ced 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -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) diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index a875e627bdfb..128e53b91b1d 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -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); diff --git a/lib/StaticAnalyzer/Core/RegionStore.cpp b/lib/StaticAnalyzer/Core/RegionStore.cpp index 28f78fa3ff5e..11902f66df91 100644 --- a/lib/StaticAnalyzer/Core/RegionStore.cpp +++ b/lib/StaticAnalyzer/Core/RegionStore.cpp @@ -409,6 +409,19 @@ public: // Part of public interface to class. // 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(R)->getDecl()->isEmpty()) + return StoreRef(store, *this); + RegionBindingsRef B = getRegionBindings(store); assert(!B.lookup(R, BindingKey::Direct)); diff --git a/test/Analysis/ctor.mm b/test/Analysis/ctor.mm index 646229aac989..619e2cb0f044 100644 --- a/test/Analysis/ctor.mm +++ b/test/Analysis/ctor.mm @@ -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; + } +} diff --git a/test/CodeGenCXX/uncopyable-args.cpp b/test/CodeGenCXX/uncopyable-args.cpp index 307a5cf11b6b..ef7168cdaaf7 100644 --- a/test/CodeGenCXX/uncopyable-args.cpp +++ b/test/CodeGenCXX/uncopyable-args.cpp @@ -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"*) - -// WIN64-LABEL: declare void @"\01?foo@implicitly_deleted@@YAXUA@1@@Z"(%"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"*) + +// 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 +} diff --git a/test/Driver/clang-translation.c b/test/Driver/clang-translation.c index 545951d5aa11..3b30f7af76dc 100644 --- a/test/Driver/clang-translation.c +++ b/test/Driver/clang-translation.c @@ -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 diff --git a/test/Index/preamble-conditionals-crash.cpp b/test/Index/preamble-conditionals-crash.cpp new file mode 100644 index 000000000000..6b18c87d19f9 --- /dev/null +++ b/test/Index/preamble-conditionals-crash.cpp @@ -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] diff --git a/test/Index/preamble-conditionals.cpp b/test/Index/preamble-conditionals.cpp new file mode 100644 index 000000000000..81ef8265e829 --- /dev/null +++ b/test/Index/preamble-conditionals.cpp @@ -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 diff --git a/test/SemaObjC/arc-property-decl-attrs.m b/test/SemaObjC/arc-property-decl-attrs.m index ee48d310edc0..7393f58199f9 100644 --- a/test/SemaObjC/arc-property-decl-attrs.m +++ b/test/SemaObjC/arc-property-decl-attrs.m @@ -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 + +// This property gets the 'strong' attribute automatically. +@property (nonatomic, readwrite) NSObject *prop; + +@end + +@interface SynthesizeWithImplicitStrongNoError : NSObject +@end + +@interface SynthesizeWithImplicitStrongNoError () + +@end + +@implementation SynthesizeWithImplicitStrongNoError + +// no error, 'strong' is implicit in the 'readwrite' property. +@synthesize prop = _prop; + +@end diff --git a/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp b/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp index 6037127feb52..7bc8421bab2f 100644 --- a/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp +++ b/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp @@ -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(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(S&&); };", - cxxConstructorDecl(isDefaultConstructor()))); - EXPECT_TRUE(notMatches("struct S { S(S&&); };", - cxxConstructorDecl(isCopyConstructor()))); - EXPECT_TRUE(matches("struct S { 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(), 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(), 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) { diff --git a/unittests/Format/FormatTestComments.cpp b/unittests/Format/FormatTestComments.cpp index 7916e65e5114..f3c45fac34a9 100644 --- a/unittests/Format/FormatTestComments.cpp +++ b/unittests/Format/FormatTestComments.cpp @@ -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" -- cgit v1.2.3