diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/ASTImporter.cpp | 5 | ||||
-rw-r--r-- | lib/AST/DeclCXX.cpp | 34 | ||||
-rw-r--r-- | lib/CodeGen/CGCXXABI.cpp | 31 | ||||
-rw-r--r-- | lib/CodeGen/ItaniumCXXABI.cpp | 13 | ||||
-rw-r--r-- | lib/CodeGen/MicrosoftCXXABI.cpp | 52 | ||||
-rw-r--r-- | lib/Driver/ToolChains/Darwin.cpp | 7 | ||||
-rw-r--r-- | lib/Driver/ToolChains/MSVC.cpp | 85 | ||||
-rw-r--r-- | lib/Driver/ToolChains/MSVC.h | 9 | ||||
-rw-r--r-- | lib/Format/WhitespaceManager.cpp | 11 | ||||
-rw-r--r-- | lib/Headers/unwind.h | 80 | ||||
-rw-r--r-- | lib/Lex/PPLexerChange.cpp | 13 | ||||
-rw-r--r-- | lib/Lex/Preprocessor.cpp | 2 | ||||
-rw-r--r-- | lib/Parse/Parser.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 56 | ||||
-rw-r--r-- | lib/Sema/SemaObjCProperty.cpp | 4 | ||||
-rw-r--r-- | lib/Serialization/ASTReaderDecl.cpp | 6 | ||||
-rw-r--r-- | lib/Serialization/ASTWriter.cpp | 3 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/RegionStore.cpp | 13 |
18 files changed, 259 insertions, 167 deletions
diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index 6e33b98d2f18c..2c0bb11cc4bc3 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 1caceab85eea6..5782b7b56c963 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 e29e525edd249..033258643ddf9 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 c82b9677eacfd..e7963674fc292 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 78b510bb46650..1bd2937e47477 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 6b7f0c71dfb77..32103a6120d40 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 b871c856d2a09..7978a6941cb85 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<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(); diff --git a/lib/Driver/ToolChains/MSVC.h b/lib/Driver/ToolChains/MSVC.h index d153691a5c905..854f88a36fd2f 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 4b4fd13145fbc..b1a5f1eab552e 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 e94b00b57c268..4f74a3478740e 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 5a589d6a17b36..36d7028da6886 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 d1dc8e1c00105..7979be773aa13 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 4aa9a59719291..1ed7ef9663589 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 e9070881afe4c..c05e5f020708d 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<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); diff --git a/lib/Sema/SemaObjCProperty.cpp b/lib/Sema/SemaObjCProperty.cpp index e1e85dfd5e55e..bfb0071a54f9f 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<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 diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index abed2586561a3..085341571ced4 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 a875e627bdfb4..128e53b91b1d1 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 28f78fa3ff5e2..11902f66df914 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<CXXBaseObjectRegion>(R)->getDecl()->isEmpty()) + return StoreRef(store, *this); + RegionBindingsRef B = getRegionBindings(store); assert(!B.lookup(R, BindingKey::Direct)); |