diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-06-10 13:44:22 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-06-10 13:44:22 +0000 |
commit | 1b08b196ac845675036ac78f3ac927d0a37f707c (patch) | |
tree | 1fbd923674e903831dc097fdb4fdfd64dd6e47b1 /lib | |
parent | 551c698530debaae81139c7c76a29fb762793362 (diff) | |
download | src-1b08b196ac845675036ac78f3ac927d0a37f707c.tar.gz src-1b08b196ac845675036ac78f3ac927d0a37f707c.zip |
Notes
Diffstat (limited to 'lib')
82 files changed, 1809 insertions, 821 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 34c4d2617ec9..62b19685c677 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -1939,9 +1939,8 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { break; case Type::Pipe: { - TypeInfo Info = getTypeInfo(cast<PipeType>(T)->getElementType()); - Width = Info.Width; - Align = Info.Align; + Width = Target->getPointerWidth(getTargetAddressSpace(LangAS::opencl_global)); + Align = Target->getPointerAlign(getTargetAddressSpace(LangAS::opencl_global)); } } diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index 847638b7bbeb..493cb6df8b83 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -2462,10 +2462,9 @@ Decl *ASTNodeImporter::VisitImplicitParamDecl(ImplicitParamDecl *D) { return nullptr; // Create the imported parameter. - ImplicitParamDecl *ToParm - = ImplicitParamDecl::Create(Importer.getToContext(), DC, - Loc, Name.getAsIdentifierInfo(), - T); + auto *ToParm = ImplicitParamDecl::Create(Importer.getToContext(), DC, Loc, + Name.getAsIdentifierInfo(), T, + D->getParameterKind()); return Importer.Imported(D, ToParm); } diff --git a/lib/AST/CMakeLists.txt b/lib/AST/CMakeLists.txt index bbebf758212e..ab9b59184294 100644 --- a/lib/AST/CMakeLists.txt +++ b/lib/AST/CMakeLists.txt @@ -1,4 +1,7 @@ -set(LLVM_LINK_COMPONENTS support) +set(LLVM_LINK_COMPONENTS + BinaryFormat + Support + ) add_clang_library(clangAST APValue.cpp diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index a1342f477b68..9862f4f26473 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -2534,9 +2534,8 @@ bool FunctionDecl::hasTrivialBody() const bool FunctionDecl::isDefined(const FunctionDecl *&Definition) const { for (auto I : redecls()) { - if (I->IsDeleted || I->IsDefaulted || I->Body || I->IsLateTemplateParsed || - I->hasDefiningAttr()) { - Definition = I->IsDeleted ? I->getCanonicalDecl() : I; + if (I->isThisDeclarationADefinition()) { + Definition = I; return true; } } @@ -4107,15 +4106,19 @@ void ImplicitParamDecl::anchor() { } ImplicitParamDecl *ImplicitParamDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, - IdentifierInfo *Id, - QualType Type) { - return new (C, DC) ImplicitParamDecl(C, DC, IdLoc, Id, Type); + IdentifierInfo *Id, QualType Type, + ImplicitParamKind ParamKind) { + return new (C, DC) ImplicitParamDecl(C, DC, IdLoc, Id, Type, ParamKind); +} + +ImplicitParamDecl *ImplicitParamDecl::Create(ASTContext &C, QualType Type, + ImplicitParamKind ParamKind) { + return new (C, nullptr) ImplicitParamDecl(C, Type, ParamKind); } ImplicitParamDecl *ImplicitParamDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - return new (C, ID) ImplicitParamDecl(C, nullptr, SourceLocation(), nullptr, - QualType()); + return new (C, ID) ImplicitParamDecl(C, QualType(), ImplicitParamKind::Other); } FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC, diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp index a12a38033c4a..a0ec0c2b251e 100644 --- a/lib/AST/DeclObjC.cpp +++ b/lib/AST/DeclObjC.cpp @@ -1070,20 +1070,20 @@ void ObjCMethodDecl::createImplicitParams(ASTContext &Context, bool selfIsPseudoStrong, selfIsConsumed; QualType selfTy = getSelfType(Context, OID, selfIsPseudoStrong, selfIsConsumed); - ImplicitParamDecl *self - = ImplicitParamDecl::Create(Context, this, SourceLocation(), - &Context.Idents.get("self"), selfTy); - setSelfDecl(self); + auto *Self = ImplicitParamDecl::Create(Context, this, SourceLocation(), + &Context.Idents.get("self"), selfTy, + ImplicitParamDecl::ObjCSelf); + setSelfDecl(Self); if (selfIsConsumed) - self->addAttr(NSConsumedAttr::CreateImplicit(Context)); + Self->addAttr(NSConsumedAttr::CreateImplicit(Context)); if (selfIsPseudoStrong) - self->setARCPseudoStrong(true); + Self->setARCPseudoStrong(true); - setCmdDecl(ImplicitParamDecl::Create(Context, this, SourceLocation(), - &Context.Idents.get("_cmd"), - Context.getObjCSelType())); + setCmdDecl(ImplicitParamDecl::Create( + Context, this, SourceLocation(), &Context.Idents.get("_cmd"), + Context.getObjCSelType(), ImplicitParamDecl::ObjCCmd)); } ObjCInterfaceDecl *ObjCMethodDecl::getClassInterface() { diff --git a/lib/AST/ODRHash.cpp b/lib/AST/ODRHash.cpp index 0e822ce35b8c..08593da89bbd 100644 --- a/lib/AST/ODRHash.cpp +++ b/lib/AST/ODRHash.cpp @@ -82,13 +82,25 @@ void ODRHash::AddDeclarationName(DeclarationName Name) { } void ODRHash::AddNestedNameSpecifier(const NestedNameSpecifier *NNS) { - assert(NNS && "Expecting non-null pointer."); - const auto *Prefix = NNS->getPrefix(); - AddBoolean(Prefix); - if (Prefix) { - AddNestedNameSpecifier(Prefix); + // Unlike the other pointer handling functions, allow null pointers here. + if (!NNS) { + AddBoolean(false); + return; } + + // Skip inlined namespaces. auto Kind = NNS->getKind(); + if (Kind == NestedNameSpecifier::Namespace) { + if (NNS->getAsNamespace()->isInline()) { + return AddNestedNameSpecifier(NNS->getPrefix()); + } + } + + AddBoolean(true); + + // Process prefix + AddNestedNameSpecifier(NNS->getPrefix()); + ID.AddInteger(Kind); switch (Kind) { case NestedNameSpecifier::Identifier: @@ -381,10 +393,7 @@ public: } void AddNestedNameSpecifier(const NestedNameSpecifier *NNS) { - Hash.AddBoolean(NNS); - if (NNS) { - Hash.AddNestedNameSpecifier(NNS); - } + Hash.AddNestedNameSpecifier(NNS); } void AddIdentifierInfo(const IdentifierInfo *II) { diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp index f1fbe2806b5d..99a25f342526 100644 --- a/lib/AST/StmtProfile.cpp +++ b/lib/AST/StmtProfile.cpp @@ -186,10 +186,7 @@ namespace { Hash.AddTemplateName(Name); } void VisitNestedNameSpecifier(NestedNameSpecifier *NNS) override { - ID.AddBoolean(NNS); - if (NNS) { - Hash.AddNestedNameSpecifier(NNS); - } + Hash.AddNestedNameSpecifier(NNS); } }; } diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 1e10094aeeea..a62ca5f9b4d7 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -1344,7 +1344,7 @@ Optional<ArrayRef<QualType>> Type::getObjCSubstitutions( } else if (getAs<BlockPointerType>()) { ASTContext &ctx = dc->getParentASTContext(); objectType = ctx.getObjCObjectType(ctx.ObjCBuiltinIdTy, { }, { }) - ->castAs<ObjCObjectType>();; + ->castAs<ObjCObjectType>(); } else { objectType = getAs<ObjCObjectType>(); } diff --git a/lib/ASTMatchers/Dynamic/Diagnostics.cpp b/lib/ASTMatchers/Dynamic/Diagnostics.cpp index 787b780c4243..9cddcf93caef 100644 --- a/lib/ASTMatchers/Dynamic/Diagnostics.cpp +++ b/lib/ASTMatchers/Dynamic/Diagnostics.cpp @@ -118,8 +118,8 @@ static StringRef errorTypeToFormatString(Diagnostics::ErrorType Type) { return "Malformed bind() expression."; case Diagnostics::ET_ParserTrailingCode: return "Expected end of code."; - case Diagnostics::ET_ParserUnsignedError: - return "Error parsing unsigned token: <$0>"; + case Diagnostics::ET_ParserNumberError: + return "Error parsing numeric literal: <$0>"; case Diagnostics::ET_ParserOverloadedType: return "Input value has unresolved overloaded type: $0"; diff --git a/lib/ASTMatchers/Dynamic/Marshallers.h b/lib/ASTMatchers/Dynamic/Marshallers.h index fb6b349a811c..c557ff162691 100644 --- a/lib/ASTMatchers/Dynamic/Marshallers.h +++ b/lib/ASTMatchers/Dynamic/Marshallers.h @@ -65,6 +65,26 @@ template <class T> struct ArgTypeTraits<ast_matchers::internal::Matcher<T> > { } }; +template <> struct ArgTypeTraits<bool> { + static bool is(const VariantValue &Value) { return Value.isBoolean(); } + static bool get(const VariantValue &Value) { + return Value.getBoolean(); + } + static ArgKind getKind() { + return ArgKind(ArgKind::AK_Boolean); + } +}; + +template <> struct ArgTypeTraits<double> { + static bool is(const VariantValue &Value) { return Value.isDouble(); } + static double get(const VariantValue &Value) { + return Value.getDouble(); + } + static ArgKind getKind() { + return ArgKind(ArgKind::AK_Double); + } +}; + template <> struct ArgTypeTraits<unsigned> { static bool is(const VariantValue &Value) { return Value.isUnsigned(); } static unsigned get(const VariantValue &Value) { diff --git a/lib/ASTMatchers/Dynamic/Parser.cpp b/lib/ASTMatchers/Dynamic/Parser.cpp index ce8d0a9a0206..f5bd29668995 100644 --- a/lib/ASTMatchers/Dynamic/Parser.cpp +++ b/lib/ASTMatchers/Dynamic/Parser.cpp @@ -130,8 +130,8 @@ private: case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': - // Parse an unsigned literal. - consumeUnsignedLiteral(&Result); + // Parse an unsigned and float literal. + consumeNumberLiteral(&Result); break; default: @@ -153,8 +153,16 @@ private: break; ++TokenLength; } - Result.Kind = TokenInfo::TK_Ident; - Result.Text = Code.substr(0, TokenLength); + if (TokenLength == 4 && Code.startswith("true")) { + Result.Kind = TokenInfo::TK_Literal; + Result.Value = true; + } else if (TokenLength == 5 && Code.startswith("false")) { + Result.Kind = TokenInfo::TK_Literal; + Result.Value = false; + } else { + Result.Kind = TokenInfo::TK_Ident; + Result.Text = Code.substr(0, TokenLength); + } Code = Code.drop_front(TokenLength); } else { Result.Kind = TokenInfo::TK_InvalidChar; @@ -168,8 +176,9 @@ private: return Result; } - /// \brief Consume an unsigned literal. - void consumeUnsignedLiteral(TokenInfo *Result) { + /// \brief Consume an unsigned and float literal. + void consumeNumberLiteral(TokenInfo *Result) { + bool isFloatingLiteral = false; unsigned Length = 1; if (Code.size() > 1) { // Consume the 'x' or 'b' radix modifier, if present. @@ -180,20 +189,44 @@ private: while (Length < Code.size() && isHexDigit(Code[Length])) ++Length; + // Try to recognize a floating point literal. + while (Length < Code.size()) { + char c = Code[Length]; + if (c == '-' || c == '+' || c == '.' || isHexDigit(c)) { + isFloatingLiteral = true; + Length++; + } else { + break; + } + } + Result->Text = Code.substr(0, Length); Code = Code.drop_front(Length); - unsigned Value; - if (!Result->Text.getAsInteger(0, Value)) { - Result->Kind = TokenInfo::TK_Literal; - Result->Value = Value; + if (isFloatingLiteral) { + char *end; + errno = 0; + std::string Text = Result->Text.str(); + double doubleValue = strtod(Text.c_str(), &end); + if (*end == 0 && errno == 0) { + Result->Kind = TokenInfo::TK_Literal; + Result->Value = doubleValue; + return; + } } else { - SourceRange Range; - Range.Start = Result->Range.Start; - Range.End = currentLocation(); - Error->addError(Range, Error->ET_ParserUnsignedError) << Result->Text; - Result->Kind = TokenInfo::TK_Error; + unsigned Value; + if (!Result->Text.getAsInteger(0, Value)) { + Result->Kind = TokenInfo::TK_Literal; + Result->Value = Value; + return; + } } + + SourceRange Range; + Range.Start = Result->Range.Start; + Range.End = currentLocation(); + Error->addError(Range, Error->ET_ParserNumberError) << Result->Text; + Result->Kind = TokenInfo::TK_Error; } /// \brief Consume a string literal. diff --git a/lib/ASTMatchers/Dynamic/Registry.cpp b/lib/ASTMatchers/Dynamic/Registry.cpp index 26743d86f5e7..031ceb320306 100644 --- a/lib/ASTMatchers/Dynamic/Registry.cpp +++ b/lib/ASTMatchers/Dynamic/Registry.cpp @@ -56,20 +56,24 @@ void RegistryMaps::registerMatcher( registerMatcher(#name, internal::makeMatcherAutoMarshall( \ ::clang::ast_matchers::name, #name)); +#define REGISTER_MATCHER_OVERLOAD(name) \ + registerMatcher(#name, \ + llvm::make_unique<internal::OverloadedMatcherDescriptor>(name##Callbacks)) + #define SPECIFIC_MATCHER_OVERLOAD(name, Id) \ static_cast<::clang::ast_matchers::name##_Type##Id>( \ ::clang::ast_matchers::name) +#define MATCHER_OVERLOAD_ENTRY(name, Id) \ + internal::makeMatcherAutoMarshall(SPECIFIC_MATCHER_OVERLOAD(name, Id), \ + #name) + #define REGISTER_OVERLOADED_2(name) \ do { \ - std::unique_ptr<MatcherDescriptor> Callbacks[] = { \ - internal::makeMatcherAutoMarshall(SPECIFIC_MATCHER_OVERLOAD(name, 0), \ - #name), \ - internal::makeMatcherAutoMarshall(SPECIFIC_MATCHER_OVERLOAD(name, 1), \ - #name)}; \ - registerMatcher( \ - #name, \ - llvm::make_unique<internal::OverloadedMatcherDescriptor>(Callbacks)); \ + std::unique_ptr<MatcherDescriptor> name##Callbacks[] = { \ + MATCHER_OVERLOAD_ENTRY(name, 0), \ + MATCHER_OVERLOAD_ENTRY(name, 1)}; \ + REGISTER_MATCHER_OVERLOAD(name); \ } while (0) /// \brief Generate a registry map with all the known matchers. @@ -83,7 +87,6 @@ RegistryMaps::RegistryMaps() { // findAll // // Other: - // equals // equalsNode REGISTER_OVERLOADED_2(callee); @@ -96,6 +99,13 @@ RegistryMaps::RegistryMaps() { REGISTER_OVERLOADED_2(references); REGISTER_OVERLOADED_2(thisPointerType); + std::unique_ptr<MatcherDescriptor> equalsCallbacks[] = { + MATCHER_OVERLOAD_ENTRY(equals, 0), + MATCHER_OVERLOAD_ENTRY(equals, 1), + MATCHER_OVERLOAD_ENTRY(equals, 2), + }; + REGISTER_MATCHER_OVERLOAD(equals); + REGISTER_MATCHER(accessSpecDecl); REGISTER_MATCHER(addrLabelExpr); REGISTER_MATCHER(alignOfExpr); diff --git a/lib/ASTMatchers/Dynamic/VariantValue.cpp b/lib/ASTMatchers/Dynamic/VariantValue.cpp index f0339ed479cd..57858d00acb4 100644 --- a/lib/ASTMatchers/Dynamic/VariantValue.cpp +++ b/lib/ASTMatchers/Dynamic/VariantValue.cpp @@ -24,6 +24,10 @@ std::string ArgKind::asString() const { switch (getArgKind()) { case AK_Matcher: return (Twine("Matcher<") + MatcherKind.asStringRef() + ">").str(); + case AK_Boolean: + return "boolean"; + case AK_Double: + return "double"; case AK_Unsigned: return "unsigned"; case AK_String: @@ -247,6 +251,14 @@ VariantValue::VariantValue(const VariantValue &Other) : Type(VT_Nothing) { *this = Other; } +VariantValue::VariantValue(bool Boolean) : Type(VT_Nothing) { + setBoolean(Boolean); +} + +VariantValue::VariantValue(double Double) : Type(VT_Nothing) { + setDouble(Double); +} + VariantValue::VariantValue(unsigned Unsigned) : Type(VT_Nothing) { setUnsigned(Unsigned); } @@ -265,6 +277,12 @@ VariantValue &VariantValue::operator=(const VariantValue &Other) { if (this == &Other) return *this; reset(); switch (Other.Type) { + case VT_Boolean: + setBoolean(Other.getBoolean()); + break; + case VT_Double: + setDouble(Other.getDouble()); + break; case VT_Unsigned: setUnsigned(Other.getUnsigned()); break; @@ -290,6 +308,8 @@ void VariantValue::reset() { delete Value.Matcher; break; // Cases that do nothing. + case VT_Boolean: + case VT_Double: case VT_Unsigned: case VT_Nothing: break; @@ -297,6 +317,36 @@ void VariantValue::reset() { Type = VT_Nothing; } +bool VariantValue::isBoolean() const { + return Type == VT_Boolean; +} + +bool VariantValue::getBoolean() const { + assert(isBoolean()); + return Value.Boolean; +} + +void VariantValue::setBoolean(bool NewValue) { + reset(); + Type = VT_Boolean; + Value.Boolean = NewValue; +} + +bool VariantValue::isDouble() const { + return Type == VT_Double; +} + +double VariantValue::getDouble() const { + assert(isDouble()); + return Value.Double; +} + +void VariantValue::setDouble(double NewValue) { + reset(); + Type = VT_Double; + Value.Double = NewValue; +} + bool VariantValue::isUnsigned() const { return Type == VT_Unsigned; } @@ -344,6 +394,18 @@ void VariantValue::setMatcher(const VariantMatcher &NewValue) { bool VariantValue::isConvertibleTo(ArgKind Kind, unsigned *Specificity) const { switch (Kind.getArgKind()) { + case ArgKind::AK_Boolean: + if (!isBoolean()) + return false; + *Specificity = 1; + return true; + + case ArgKind::AK_Double: + if (!isDouble()) + return false; + *Specificity = 1; + return true; + case ArgKind::AK_Unsigned: if (!isUnsigned()) return false; @@ -383,6 +445,8 @@ std::string VariantValue::getTypeAsString() const { switch (Type) { case VT_String: return "String"; case VT_Matcher: return getMatcher().getTypeAsString(); + case VT_Boolean: return "Boolean"; + case VT_Double: return "Double"; case VT_Unsigned: return "Unsigned"; case VT_Nothing: return "Nothing"; } diff --git a/lib/Basic/SourceManager.cpp b/lib/Basic/SourceManager.cpp index c5cff74ac97d..fc4c6d303801 100644 --- a/lib/Basic/SourceManager.cpp +++ b/lib/Basic/SourceManager.cpp @@ -73,11 +73,11 @@ void ContentCache::replaceBuffer(llvm::MemoryBuffer *B, bool DoNotFree) { Buffer.setInt(DoNotFree? DoNotFreeFlag : 0); return; } - + if (shouldFreeBuffer()) delete Buffer.getPointer(); Buffer.setPointer(B); - Buffer.setInt(DoNotFree? DoNotFreeFlag : 0); + Buffer.setInt((B && DoNotFree) ? DoNotFreeFlag : 0); } llvm::MemoryBuffer *ContentCache::getBuffer(DiagnosticsEngine &Diag, @@ -345,6 +345,43 @@ void SourceManager::clearIDTables() { createExpansionLoc(SourceLocation(),SourceLocation(),SourceLocation(), 1); } +void SourceManager::initializeForReplay(const SourceManager &Old) { + assert(MainFileID.isInvalid() && "expected uninitialized SourceManager"); + + auto CloneContentCache = [&](const ContentCache *Cache) -> ContentCache * { + auto *Clone = new (ContentCacheAlloc.Allocate<ContentCache>()) ContentCache; + Clone->OrigEntry = Cache->OrigEntry; + Clone->ContentsEntry = Cache->ContentsEntry; + Clone->BufferOverridden = Cache->BufferOverridden; + Clone->IsSystemFile = Cache->IsSystemFile; + Clone->IsTransient = Cache->IsTransient; + Clone->replaceBuffer(Cache->getRawBuffer(), /*DoNotFree*/true); + return Clone; + }; + + // Set up our main file ID as a copy of the old source manager's main file. + const SLocEntry &OldMainFile = Old.getSLocEntry(Old.getMainFileID()); + assert(OldMainFile.isFile() && "main file is macro expansion?"); + auto *MainCC = CloneContentCache(OldMainFile.getFile().getContentCache()); + MemBufferInfos.push_back(MainCC); + setMainFileID(createFileID(MainCC, SourceLocation(), + OldMainFile.getFile().getFileCharacteristic(), + 0, 0)); + + // Ensure all SLocEntries are loaded from the external source. + for (unsigned I = 0, N = Old.LoadedSLocEntryTable.size(); I != N; ++I) + if (!Old.SLocEntryLoaded[I]) + Old.loadSLocEntry(I, nullptr); + + // Inherit any content cache data from the old source manager. + for (auto &FileInfo : Old.FileInfos) { + SrcMgr::ContentCache *&Slot = FileInfos[FileInfo.first]; + if (Slot) + continue; + Slot = CloneContentCache(FileInfo.second); + } +} + /// getOrCreateContentCache - Create or return a cached ContentCache for the /// specified file. const ContentCache * diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp index 605f73802afb..a3b8330707b9 100644 --- a/lib/Basic/Targets.cpp +++ b/lib/Basic/Targets.cpp @@ -5385,6 +5385,10 @@ public: // ARM has atomics up to 8 bytes setAtomic(); + // Maximum alignment for ARM NEON data types should be 64-bits (AAPCS) + if (IsAAPCS && (Triple.getEnvironment() != llvm::Triple::Android)) + MaxVectorAlign = 64; + // Do force alignment of members that follow zero length bitfields. If // the alignment of the zero-length bitfield is greater than the member // that follows it, `bar', `bar' will be aligned as the type of the @@ -5438,7 +5442,24 @@ public: if (Feature[0] == '+') Features[Feature.drop_front(1)] = true; - return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec); + // Enable or disable thumb-mode explicitly per function to enable mixed + // ARM and Thumb code generation. + if (isThumb()) + Features["thumb-mode"] = true; + else + Features["thumb-mode"] = false; + + // Convert user-provided arm and thumb GNU target attributes to + // [-|+]thumb-mode target features respectively. + std::vector<std::string> UpdatedFeaturesVec(FeaturesVec); + for (auto &Feature : UpdatedFeaturesVec) { + if (Feature.compare("+arm") == 0) + Feature = "-thumb-mode"; + else if (Feature.compare("+thumb") == 0) + Feature = "+thumb-mode"; + } + + return TargetInfo::initFeatureMap(Features, Diags, CPU, UpdatedFeaturesVec); } bool handleTargetFeatures(std::vector<std::string> &Features, @@ -7716,6 +7737,7 @@ class MipsTargetInfo : public TargetInfo { NoDSP, DSP1, DSP2 } DspRev; bool HasMSA; + bool DisableMadd4; protected: bool HasFP64; @@ -7726,7 +7748,7 @@ public: : TargetInfo(Triple), IsMips16(false), IsMicromips(false), IsNan2008(false), IsSingleFloat(false), IsNoABICalls(false), CanUseBSDABICalls(false), FloatABI(HardFloat), DspRev(NoDSP), - HasMSA(false), HasFP64(false) { + HasMSA(false), DisableMadd4(false), HasFP64(false) { TheCXXABI.set(TargetCXXABI::GenericMIPS); setABI((getTriple().getArch() == llvm::Triple::mips || @@ -7972,6 +7994,9 @@ public: if (HasMSA) Builder.defineMacro("__mips_msa", Twine(1)); + if (DisableMadd4) + Builder.defineMacro("__mips_no_madd4", Twine(1)); + Builder.defineMacro("_MIPS_SZPTR", Twine(getPointerWidth(0))); Builder.defineMacro("_MIPS_SZINT", Twine(getIntWidth())); Builder.defineMacro("_MIPS_SZLONG", Twine(getLongWidth())); @@ -8134,6 +8159,8 @@ public: DspRev = std::max(DspRev, DSP2); else if (Feature == "+msa") HasMSA = true; + else if (Feature == "+nomadd4") + DisableMadd4 = true; else if (Feature == "+fp64") HasFP64 = true; else if (Feature == "-fp64") @@ -8466,7 +8493,7 @@ public: explicit WebAssembly32TargetInfo(const llvm::Triple &T, const TargetOptions &Opts) : WebAssemblyTargetInfo(T, Opts) { - MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 32; + MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64; resetDataLayout("e-m:e-p:32:32-i64:64-n32:64-S128"); } diff --git a/lib/CodeGen/BackendUtil.cpp b/lib/CodeGen/BackendUtil.cpp index fd193bcf1a69..9c4316fb1cd5 100644 --- a/lib/CodeGen/BackendUtil.cpp +++ b/lib/CodeGen/BackendUtil.cpp @@ -410,7 +410,7 @@ static void initTargetOptions(llvm::TargetOptions &Options, Options.UseInitArray = CodeGenOpts.UseInitArray; Options.DisableIntegratedAS = CodeGenOpts.DisableIntegratedAS; - Options.CompressDebugSections = CodeGenOpts.CompressDebugSections; + Options.CompressDebugSections = CodeGenOpts.getCompressDebugSections(); Options.RelaxELFRelocations = CodeGenOpts.RelaxELFRelocations; // Set EABI version. diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp index 2e423b25f0fb..528a2b33acf8 100644 --- a/lib/CodeGen/CGBlocks.cpp +++ b/lib/CodeGen/CGBlocks.cpp @@ -903,9 +903,8 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) { } else { // Fake up a new variable so that EmitScalarInit doesn't think // we're referring to the variable in its own initializer. - ImplicitParamDecl blockFieldPseudoVar(getContext(), /*DC*/ nullptr, - SourceLocation(), /*name*/ nullptr, - type); + ImplicitParamDecl BlockFieldPseudoVar(getContext(), type, + ImplicitParamDecl::Other); // We use one of these or the other depending on whether the // reference is nested. @@ -919,7 +918,7 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) { // attributed to a reasonable location - otherwise it may be attributed to // locations of subexpressions in the initialization. LValueBaseInfo BaseInfo(AlignmentSource::Decl, false); - EmitExprAsInit(&l2r, &blockFieldPseudoVar, + EmitExprAsInit(&l2r, &BlockFieldPseudoVar, MakeAddrLValue(blockField, type, BaseInfo), /*captured by init*/ false); } @@ -1264,9 +1263,10 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD, IdentifierInfo *II = &CGM.getContext().Idents.get(".block_descriptor"); - ImplicitParamDecl selfDecl(getContext(), const_cast<BlockDecl*>(blockDecl), - SourceLocation(), II, selfTy); - args.push_back(&selfDecl); + ImplicitParamDecl SelfDecl(getContext(), const_cast<BlockDecl *>(blockDecl), + SourceLocation(), II, selfTy, + ImplicitParamDecl::ObjCSelf); + args.push_back(&SelfDecl); // Now add the rest of the parameters. args.append(blockDecl->param_begin(), blockDecl->param_end()); @@ -1499,12 +1499,12 @@ CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) { ASTContext &C = getContext(); FunctionArgList args; - ImplicitParamDecl dstDecl(getContext(), nullptr, SourceLocation(), nullptr, - C.VoidPtrTy); - args.push_back(&dstDecl); - ImplicitParamDecl srcDecl(getContext(), nullptr, SourceLocation(), nullptr, - C.VoidPtrTy); - args.push_back(&srcDecl); + ImplicitParamDecl DstDecl(getContext(), C.VoidPtrTy, + ImplicitParamDecl::Other); + args.push_back(&DstDecl); + ImplicitParamDecl SrcDecl(getContext(), C.VoidPtrTy, + ImplicitParamDecl::Other); + args.push_back(&SrcDecl); const CGFunctionInfo &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, args); @@ -1536,11 +1536,11 @@ CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) { auto AL = ApplyDebugLocation::CreateArtificial(*this); llvm::Type *structPtrTy = blockInfo.StructureType->getPointerTo(); - Address src = GetAddrOfLocalVar(&srcDecl); + Address src = GetAddrOfLocalVar(&SrcDecl); src = Address(Builder.CreateLoad(src), blockInfo.BlockAlign); src = Builder.CreateBitCast(src, structPtrTy, "block.source"); - Address dst = GetAddrOfLocalVar(&dstDecl); + Address dst = GetAddrOfLocalVar(&DstDecl); dst = Address(Builder.CreateLoad(dst), blockInfo.BlockAlign); dst = Builder.CreateBitCast(dst, structPtrTy, "block.dest"); @@ -1676,9 +1676,9 @@ CodeGenFunction::GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo) { ASTContext &C = getContext(); FunctionArgList args; - ImplicitParamDecl srcDecl(getContext(), nullptr, SourceLocation(), nullptr, - C.VoidPtrTy); - args.push_back(&srcDecl); + ImplicitParamDecl SrcDecl(getContext(), C.VoidPtrTy, + ImplicitParamDecl::Other); + args.push_back(&SrcDecl); const CGFunctionInfo &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, args); @@ -1709,7 +1709,7 @@ CodeGenFunction::GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo) { llvm::Type *structPtrTy = blockInfo.StructureType->getPointerTo(); - Address src = GetAddrOfLocalVar(&srcDecl); + Address src = GetAddrOfLocalVar(&SrcDecl); src = Address(Builder.CreateLoad(src), blockInfo.BlockAlign); src = Builder.CreateBitCast(src, structPtrTy, "block"); @@ -1918,13 +1918,13 @@ generateByrefCopyHelper(CodeGenFunction &CGF, const BlockByrefInfo &byrefInfo, QualType R = Context.VoidTy; FunctionArgList args; - ImplicitParamDecl dst(CGF.getContext(), nullptr, SourceLocation(), nullptr, - Context.VoidPtrTy); - args.push_back(&dst); + ImplicitParamDecl Dst(CGF.getContext(), Context.VoidPtrTy, + ImplicitParamDecl::Other); + args.push_back(&Dst); - ImplicitParamDecl src(CGF.getContext(), nullptr, SourceLocation(), nullptr, - Context.VoidPtrTy); - args.push_back(&src); + ImplicitParamDecl Src(CGF.getContext(), Context.VoidPtrTy, + ImplicitParamDecl::Other); + args.push_back(&Src); const CGFunctionInfo &FI = CGF.CGM.getTypes().arrangeBuiltinFunctionDeclaration(R, args); @@ -1955,7 +1955,7 @@ generateByrefCopyHelper(CodeGenFunction &CGF, const BlockByrefInfo &byrefInfo, llvm::Type *byrefPtrType = byrefInfo.Type->getPointerTo(0); // dst->x - Address destField = CGF.GetAddrOfLocalVar(&dst); + Address destField = CGF.GetAddrOfLocalVar(&Dst); destField = Address(CGF.Builder.CreateLoad(destField), byrefInfo.ByrefAlignment); destField = CGF.Builder.CreateBitCast(destField, byrefPtrType); @@ -1963,7 +1963,7 @@ generateByrefCopyHelper(CodeGenFunction &CGF, const BlockByrefInfo &byrefInfo, "dest-object"); // src->x - Address srcField = CGF.GetAddrOfLocalVar(&src); + Address srcField = CGF.GetAddrOfLocalVar(&Src); srcField = Address(CGF.Builder.CreateLoad(srcField), byrefInfo.ByrefAlignment); srcField = CGF.Builder.CreateBitCast(srcField, byrefPtrType); @@ -1995,9 +1995,9 @@ generateByrefDisposeHelper(CodeGenFunction &CGF, QualType R = Context.VoidTy; FunctionArgList args; - ImplicitParamDecl src(CGF.getContext(), nullptr, SourceLocation(), nullptr, - Context.VoidPtrTy); - args.push_back(&src); + ImplicitParamDecl Src(CGF.getContext(), Context.VoidPtrTy, + ImplicitParamDecl::Other); + args.push_back(&Src); const CGFunctionInfo &FI = CGF.CGM.getTypes().arrangeBuiltinFunctionDeclaration(R, args); @@ -2026,7 +2026,7 @@ generateByrefDisposeHelper(CodeGenFunction &CGF, CGF.StartFunction(FD, R, Fn, FI, args); if (generator.needsDispose()) { - Address addr = CGF.GetAddrOfLocalVar(&src); + Address addr = CGF.GetAddrOfLocalVar(&Src); addr = Address(CGF.Builder.CreateLoad(addr), byrefInfo.ByrefAlignment); auto byrefPtrType = byrefInfo.Type->getPointerTo(0); addr = CGF.Builder.CreateBitCast(addr, byrefPtrType); diff --git a/lib/CodeGen/CGCXXABI.cpp b/lib/CodeGen/CGCXXABI.cpp index df75a7d7ffde..e29e525edd24 100644 --- a/lib/CodeGen/CGCXXABI.cpp +++ b/lib/CodeGen/CGCXXABI.cpp @@ -159,10 +159,10 @@ void CGCXXABI::buildThisParam(CodeGenFunction &CGF, FunctionArgList ¶ms) { // FIXME: I'm not entirely sure I like using a fake decl just for code // generation. Maybe we can come up with a better way? - ImplicitParamDecl *ThisDecl - = ImplicitParamDecl::Create(CGM.getContext(), nullptr, MD->getLocation(), - &CGM.getContext().Idents.get("this"), - MD->getThisType(CGM.getContext())); + auto *ThisDecl = ImplicitParamDecl::Create( + CGM.getContext(), nullptr, MD->getLocation(), + &CGM.getContext().Idents.get("this"), MD->getThisType(CGM.getContext()), + ImplicitParamDecl::CXXThis); params.push_back(ThisDecl); CGF.CXXABIThisDecl = ThisDecl; diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index 02db79159b58..ebb264eb61c9 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -3466,13 +3466,13 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, llvm::Value *Storage, unsigned AddressSpace = CGM.getContext().getTargetAddressSpace(VD->getType()); AppendAddressSpaceXDeref(AddressSpace, Expr); - // If this is the first argument and it is implicit then - // give it an object pointer flag. - // FIXME: There has to be a better way to do this, but for static - // functions there won't be an implicit param at arg1 and - // otherwise it is 'self' or 'this'. - if (isa<ImplicitParamDecl>(VD) && ArgNo && *ArgNo == 1) - Flags |= llvm::DINode::FlagObjectPointer; + // If this is implicit parameter of CXXThis or ObjCSelf kind, then give it an + // object pointer flag. + if (const auto *IPD = dyn_cast<ImplicitParamDecl>(VD)) { + if (IPD->getParameterKind() == ImplicitParamDecl::CXXThis || + IPD->getParameterKind() == ImplicitParamDecl::ObjCSelf) + Flags |= llvm::DINode::FlagObjectPointer; + } // Note: Older versions of clang used to emit byval references with an extra // DW_OP_deref, because they referenced the IR arg directly instead of @@ -3583,8 +3583,9 @@ void CGDebugInfo::EmitDeclareOfBlockDeclRefVariable( // Self is passed along as an implicit non-arg variable in a // block. Mark it as the object pointer. - if (isa<ImplicitParamDecl>(VD) && VD->getName() == "self") - Ty = CreateSelfType(VD->getType(), Ty); + if (const auto *IPD = dyn_cast<ImplicitParamDecl>(VD)) + if (IPD->getParameterKind() == ImplicitParamDecl::ObjCSelf) + Ty = CreateSelfType(VD->getType(), Ty); // Get location information. unsigned Line = getLineNumber(VD->getLocation()); diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index d6abfa15e541..87bfa507a8c0 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -406,6 +406,13 @@ void CodeGenFunction::EmitStaticVarDecl(const VarDecl &D, if (D.hasAttr<AnnotateAttr>()) CGM.AddGlobalAnnotations(&D, var); + if (auto *SA = D.getAttr<PragmaClangBSSSectionAttr>()) + var->addAttribute("bss-section", SA->getName()); + if (auto *SA = D.getAttr<PragmaClangDataSectionAttr>()) + var->addAttribute("data-section", SA->getName()); + if (auto *SA = D.getAttr<PragmaClangRodataSectionAttr>()) + var->addAttribute("rodata-section", SA->getName()); + if (const SectionAttr *SA = D.getAttr<SectionAttr>()) var->setSection(SA->getName()); diff --git a/lib/CodeGen/CGDeclCXX.cpp b/lib/CodeGen/CGDeclCXX.cpp index ff766e6b3b9c..d8768bee2cdf 100644 --- a/lib/CodeGen/CGDeclCXX.cpp +++ b/lib/CodeGen/CGDeclCXX.cpp @@ -603,9 +603,9 @@ llvm::Function *CodeGenFunction::generateDestroyHelper( Address addr, QualType type, Destroyer *destroyer, bool useEHCleanupForArray, const VarDecl *VD) { FunctionArgList args; - ImplicitParamDecl dst(getContext(), nullptr, SourceLocation(), nullptr, - getContext().VoidPtrTy); - args.push_back(&dst); + ImplicitParamDecl Dst(getContext(), getContext().VoidPtrTy, + ImplicitParamDecl::Other); + args.push_back(&Dst); const CGFunctionInfo &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(getContext().VoidTy, args); diff --git a/lib/CodeGen/CGException.cpp b/lib/CodeGen/CGException.cpp index e65fa863fe31..40ae0921098c 100644 --- a/lib/CodeGen/CGException.cpp +++ b/lib/CodeGen/CGException.cpp @@ -1649,18 +1649,19 @@ void CodeGenFunction::startOutlinedSEHHelper(CodeGenFunction &ParentCGF, // parameters. Win32 filters take no parameters. if (IsFilter) { Args.push_back(ImplicitParamDecl::Create( - getContext(), nullptr, StartLoc, + getContext(), /*DC=*/nullptr, StartLoc, &getContext().Idents.get("exception_pointers"), - getContext().VoidPtrTy)); + getContext().VoidPtrTy, ImplicitParamDecl::Other)); } else { Args.push_back(ImplicitParamDecl::Create( - getContext(), nullptr, StartLoc, + getContext(), /*DC=*/nullptr, StartLoc, &getContext().Idents.get("abnormal_termination"), - getContext().UnsignedCharTy)); + getContext().UnsignedCharTy, ImplicitParamDecl::Other)); } Args.push_back(ImplicitParamDecl::Create( - getContext(), nullptr, StartLoc, - &getContext().Idents.get("frame_pointer"), getContext().VoidPtrTy)); + getContext(), /*DC=*/nullptr, StartLoc, + &getContext().Idents.get("frame_pointer"), getContext().VoidPtrTy, + ImplicitParamDecl::Other)); } QualType RetTy = IsFilter ? getContext().LongTy : getContext().VoidTy; diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 2aa045879213..9f800a75b5bc 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -2847,10 +2847,10 @@ void CodeGenFunction::EmitCfiCheckStub() { void CodeGenFunction::EmitCfiCheckFail() { SanitizerScope SanScope(this); FunctionArgList Args; - ImplicitParamDecl ArgData(getContext(), nullptr, SourceLocation(), nullptr, - getContext().VoidPtrTy); - ImplicitParamDecl ArgAddr(getContext(), nullptr, SourceLocation(), nullptr, - getContext().VoidPtrTy); + ImplicitParamDecl ArgData(getContext(), getContext().VoidPtrTy, + ImplicitParamDecl::Other); + ImplicitParamDecl ArgAddr(getContext(), getContext().VoidPtrTy, + ImplicitParamDecl::Other); Args.push_back(&ArgData); Args.push_back(&ArgAddr); diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp index 820520121763..90fcad261415 100644 --- a/lib/CodeGen/CGObjC.cpp +++ b/lib/CodeGen/CGObjC.cpp @@ -3246,10 +3246,12 @@ CodeGenFunction::GenerateObjCAtomicSetterCopyHelperFunction( SrcTy = C.getPointerType(SrcTy); FunctionArgList args; - ImplicitParamDecl dstDecl(getContext(), FD, SourceLocation(), nullptr,DestTy); - args.push_back(&dstDecl); - ImplicitParamDecl srcDecl(getContext(), FD, SourceLocation(), nullptr, SrcTy); - args.push_back(&srcDecl); + ImplicitParamDecl DstDecl(getContext(), FD, SourceLocation(), /*Id=*/nullptr, + DestTy, ImplicitParamDecl::Other); + args.push_back(&DstDecl); + ImplicitParamDecl SrcDecl(getContext(), FD, SourceLocation(), /*Id=*/nullptr, + SrcTy, ImplicitParamDecl::Other); + args.push_back(&SrcDecl); const CGFunctionInfo &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, args); @@ -3265,12 +3267,12 @@ CodeGenFunction::GenerateObjCAtomicSetterCopyHelperFunction( StartFunction(FD, C.VoidTy, Fn, FI, args); - DeclRefExpr DstExpr(&dstDecl, false, DestTy, + DeclRefExpr DstExpr(&DstDecl, false, DestTy, VK_RValue, SourceLocation()); UnaryOperator DST(&DstExpr, UO_Deref, DestTy->getPointeeType(), VK_LValue, OK_Ordinary, SourceLocation()); - DeclRefExpr SrcExpr(&srcDecl, false, SrcTy, + DeclRefExpr SrcExpr(&SrcDecl, false, SrcTy, VK_RValue, SourceLocation()); UnaryOperator SRC(&SrcExpr, UO_Deref, SrcTy->getPointeeType(), VK_LValue, OK_Ordinary, SourceLocation()); @@ -3327,10 +3329,12 @@ CodeGenFunction::GenerateObjCAtomicGetterCopyHelperFunction( SrcTy = C.getPointerType(SrcTy); FunctionArgList args; - ImplicitParamDecl dstDecl(getContext(), FD, SourceLocation(), nullptr,DestTy); - args.push_back(&dstDecl); - ImplicitParamDecl srcDecl(getContext(), FD, SourceLocation(), nullptr, SrcTy); - args.push_back(&srcDecl); + ImplicitParamDecl DstDecl(getContext(), FD, SourceLocation(), /*Id=*/nullptr, + DestTy, ImplicitParamDecl::Other); + args.push_back(&DstDecl); + ImplicitParamDecl SrcDecl(getContext(), FD, SourceLocation(), /*Id=*/nullptr, + SrcTy, ImplicitParamDecl::Other); + args.push_back(&SrcDecl); const CGFunctionInfo &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, args); @@ -3345,7 +3349,7 @@ CodeGenFunction::GenerateObjCAtomicGetterCopyHelperFunction( StartFunction(FD, C.VoidTy, Fn, FI, args); - DeclRefExpr SrcExpr(&srcDecl, false, SrcTy, + DeclRefExpr SrcExpr(&SrcDecl, false, SrcTy, VK_RValue, SourceLocation()); UnaryOperator SRC(&SrcExpr, UO_Deref, SrcTy->getPointeeType(), @@ -3371,7 +3375,7 @@ CodeGenFunction::GenerateObjCAtomicGetterCopyHelperFunction( CXXConstExpr->getConstructionKind(), SourceRange()); - DeclRefExpr DstExpr(&dstDecl, false, DestTy, + DeclRefExpr DstExpr(&DstDecl, false, DestTy, VK_RValue, SourceLocation()); RValue DV = EmitAnyExpr(&DstExpr); diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index 9c048423285b..c78d3febd4cd 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -1004,6 +1004,8 @@ protected: const ObjCInterfaceDecl *ID, ObjCCommonTypesHelper &ObjCTypes); + std::string GetSectionName(StringRef Section, StringRef MachOAttributes); + public: /// CreateMetadataVar - Create a global variable with internal /// linkage for use by the Objective-C runtime. @@ -4786,6 +4788,27 @@ llvm::Value *CGObjCMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF, /* *** Private Interface *** */ +std::string CGObjCCommonMac::GetSectionName(StringRef Section, + StringRef MachOAttributes) { + switch (CGM.getTriple().getObjectFormat()) { + default: + llvm_unreachable("unexpected object file format"); + case llvm::Triple::MachO: { + if (MachOAttributes.empty()) + return ("__DATA," + Section).str(); + return ("__DATA," + Section + "," + MachOAttributes).str(); + } + case llvm::Triple::ELF: + assert(Section.substr(0, 2) == "__" && + "expected the name to begin with __"); + return Section.substr(2).str(); + case llvm::Triple::COFF: + assert(Section.substr(0, 2) == "__" && + "expected the name to begin with __"); + return ("." + Section.substr(2) + "$B").str(); + } +} + /// EmitImageInfo - Emit the image info marker used to encode some module /// level information. /// @@ -4809,9 +4832,10 @@ enum ImageInfoFlags { void CGObjCCommonMac::EmitImageInfo() { unsigned version = 0; // Version is unused? - const char *Section = (ObjCABI == 1) ? - "__OBJC, __image_info,regular" : - "__DATA, __objc_imageinfo, regular, no_dead_strip"; + std::string Section = + (ObjCABI == 1) + ? "__OBJC,__image_info,regular" + : GetSectionName("__objc_imageinfo", "regular,no_dead_strip"); // Generate module-level named metadata to convey this information to the // linker and code-gen. @@ -4822,7 +4846,7 @@ void CGObjCCommonMac::EmitImageInfo() { Mod.addModuleFlag(llvm::Module::Error, "Objective-C Image Info Version", version); Mod.addModuleFlag(llvm::Module::Error, "Objective-C Image Info Section", - llvm::MDString::get(VMContext,Section)); + llvm::MDString::get(VMContext, Section)); if (CGM.getLangOpts().getGC() == LangOptions::NonGC) { // Non-GC overrides those files which specify GC. @@ -5930,17 +5954,21 @@ void CGObjCNonFragileABIMac::FinishNonFragileABIModule() { } AddModuleClassList(DefinedClasses, "OBJC_LABEL_CLASS_$", - "__DATA, __objc_classlist, regular, no_dead_strip"); + GetSectionName("__objc_classlist", + "regular,no_dead_strip")); AddModuleClassList(DefinedNonLazyClasses, "OBJC_LABEL_NONLAZY_CLASS_$", - "__DATA, __objc_nlclslist, regular, no_dead_strip"); + GetSectionName("__objc_nlclslist", + "regular,no_dead_strip")); // Build list of all implemented category addresses in array // L_OBJC_LABEL_CATEGORY_$. AddModuleClassList(DefinedCategories, "OBJC_LABEL_CATEGORY_$", - "__DATA, __objc_catlist, regular, no_dead_strip"); + GetSectionName("__objc_catlist", + "regular,no_dead_strip")); AddModuleClassList(DefinedNonLazyCategories, "OBJC_LABEL_NONLAZY_CATEGORY_$", - "__DATA, __objc_nlcatlist, regular, no_dead_strip"); + GetSectionName("__objc_nlcatlist", + "regular,no_dead_strip")); EmitImageInfo(); } @@ -6359,7 +6387,8 @@ llvm::Value *CGObjCNonFragileABIMac::GenerateProtocolRef(CodeGenFunction &CGF, llvm::GlobalValue::WeakAnyLinkage, Init, ProtocolName); - PTGV->setSection("__DATA, __objc_protorefs, coalesced, no_dead_strip"); + PTGV->setSection(GetSectionName("__objc_protorefs", + "coalesced,no_dead_strip")); PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility); PTGV->setAlignment(Align.getQuantity()); CGM.addCompilerUsedGlobal(PTGV); @@ -6818,8 +6847,8 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol( PTGV->setComdat(CGM.getModule().getOrInsertComdat(ProtocolRef)); PTGV->setAlignment( CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ProtocolnfABIPtrTy)); - if (CGM.getTriple().isOSBinFormatMachO()) - PTGV->setSection("__DATA, __objc_protolist, coalesced, no_dead_strip"); + PTGV->setSection(GetSectionName("__objc_protolist", + "coalesced,no_dead_strip")); PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility); CGM.addCompilerUsedGlobal(PTGV); return Entry; @@ -7015,7 +7044,7 @@ CGObjCNonFragileABIMac::EmitVTableMessageSend(CodeGenFunction &CGF, /*constant*/ false, llvm::GlobalValue::WeakAnyLinkage); messageRef->setVisibility(llvm::GlobalValue::HiddenVisibility); - messageRef->setSection("__DATA, __objc_msgrefs, coalesced"); + messageRef->setSection(GetSectionName("__objc_msgrefs", "coalesced")); } bool requiresnullCheck = false; @@ -7126,7 +7155,8 @@ CGObjCNonFragileABIMac::EmitClassRefFromId(CodeGenFunction &CGF, false, llvm::GlobalValue::PrivateLinkage, ClassGV, "OBJC_CLASSLIST_REFERENCES_$_"); Entry->setAlignment(Align.getQuantity()); - Entry->setSection("__DATA, __objc_classrefs, regular, no_dead_strip"); + Entry->setSection(GetSectionName("__objc_classrefs", + "regular,no_dead_strip")); CGM.addCompilerUsedGlobal(Entry); } return CGF.Builder.CreateAlignedLoad(Entry, Align); @@ -7160,7 +7190,8 @@ CGObjCNonFragileABIMac::EmitSuperClassRef(CodeGenFunction &CGF, false, llvm::GlobalValue::PrivateLinkage, ClassGV, "OBJC_CLASSLIST_SUP_REFS_$_"); Entry->setAlignment(Align.getQuantity()); - Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip"); + Entry->setSection(GetSectionName("__objc_superrefs", + "regular,no_dead_strip")); CGM.addCompilerUsedGlobal(Entry); } return CGF.Builder.CreateAlignedLoad(Entry, Align); @@ -7182,7 +7213,8 @@ llvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CodeGenFunction &CGF, MetaClassGV, "OBJC_CLASSLIST_SUP_REFS_$_"); Entry->setAlignment(Align.getQuantity()); - Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip"); + Entry->setSection(GetSectionName("__objc_superrefs", + "regular,no_dead_strip")); CGM.addCompilerUsedGlobal(Entry); } @@ -7278,7 +7310,8 @@ Address CGObjCNonFragileABIMac::EmitSelectorAddr(CodeGenFunction &CGF, false, llvm::GlobalValue::PrivateLinkage, Casted, "OBJC_SELECTOR_REFERENCES_"); Entry->setExternallyInitialized(true); - Entry->setSection("__DATA, __objc_selrefs, literal_pointers, no_dead_strip"); + Entry->setSection(GetSectionName("__objc_selrefs", + "literal_pointers,no_dead_strip")); Entry->setAlignment(Align.getQuantity()); CGM.addCompilerUsedGlobal(Entry); } diff --git a/lib/CodeGen/CGOpenMPRuntime.cpp b/lib/CodeGen/CGOpenMPRuntime.cpp index 63300e25d37e..468838e56e38 100644 --- a/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/lib/CodeGen/CGOpenMPRuntime.cpp @@ -747,9 +747,9 @@ emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty, QualType PtrTy = C.getPointerType(Ty).withRestrict(); FunctionArgList Args; ImplicitParamDecl OmpOutParm(C, /*DC=*/nullptr, Out->getLocation(), - /*Id=*/nullptr, PtrTy); + /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other); ImplicitParamDecl OmpInParm(C, /*DC=*/nullptr, In->getLocation(), - /*Id=*/nullptr, PtrTy); + /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other); Args.push_back(&OmpOutParm); Args.push_back(&OmpInParm); auto &FnInfo = @@ -1808,8 +1808,8 @@ llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition( // threadprivate copy of the variable VD CodeGenFunction CtorCGF(CGM); FunctionArgList Args; - ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, SourceLocation(), - /*Id=*/nullptr, CGM.getContext().VoidPtrTy); + ImplicitParamDecl Dst(CGM.getContext(), CGM.getContext().VoidPtrTy, + ImplicitParamDecl::Other); Args.push_back(&Dst); auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration( @@ -1839,8 +1839,8 @@ llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition( // of the variable VD CodeGenFunction DtorCGF(CGM); FunctionArgList Args; - ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, SourceLocation(), - /*Id=*/nullptr, CGM.getContext().VoidPtrTy); + ImplicitParamDecl Dst(CGM.getContext(), CGM.getContext().VoidPtrTy, + ImplicitParamDecl::Other); Args.push_back(&Dst); auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration( @@ -2191,10 +2191,8 @@ static llvm::Value *emitCopyprivateCopyFunction( auto &C = CGM.getContext(); // void copy_func(void *LHSArg, void *RHSArg); FunctionArgList Args; - ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr, - C.VoidPtrTy); - ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr, - C.VoidPtrTy); + ImplicitParamDecl LHSArg(C, C.VoidPtrTy, ImplicitParamDecl::Other); + ImplicitParamDecl RHSArg(C, C.VoidPtrTy, ImplicitParamDecl::Other); Args.push_back(&LHSArg); Args.push_back(&RHSArg); auto &CGFI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); @@ -2785,8 +2783,7 @@ createOffloadingBinaryDescriptorFunction(CodeGenModule &CGM, StringRef Name, const RegionCodeGenTy &Codegen) { auto &C = CGM.getContext(); FunctionArgList Args; - ImplicitParamDecl DummyPtr(C, /*DC=*/nullptr, SourceLocation(), - /*Id=*/nullptr, C.VoidPtrTy); + ImplicitParamDecl DummyPtr(C, C.VoidPtrTy, ImplicitParamDecl::Other); Args.push_back(&DummyPtr); CodeGenFunction CGF(CGM); @@ -2889,7 +2886,7 @@ CGOpenMPRuntime::createOffloadingBinaryDescriptorRegistration() { // descriptor, so we can reuse the logic that emits Ctors and Dtors. auto *IdentInfo = &C.Idents.get(".omp_offloading.reg_unreg_var"); ImplicitParamDecl RegUnregVar(C, C.getTranslationUnitDecl(), SourceLocation(), - IdentInfo, C.CharTy); + IdentInfo, C.CharTy, ImplicitParamDecl::Other); auto *UnRegFn = createOffloadingBinaryDescriptorFunction( CGM, ".omp_offloading.descriptor_unreg", @@ -3319,10 +3316,11 @@ emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc, llvm::Value *TaskPrivatesMap) { auto &C = CGM.getContext(); FunctionArgList Args; - ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty); - ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, - /*Id=*/nullptr, - KmpTaskTWithPrivatesPtrQTy.withRestrict()); + ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty, + ImplicitParamDecl::Other); + ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, + KmpTaskTWithPrivatesPtrQTy.withRestrict(), + ImplicitParamDecl::Other); Args.push_back(&GtidArg); Args.push_back(&TaskTypeArg); auto &TaskEntryFnInfo = @@ -3413,10 +3411,11 @@ static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM, QualType KmpTaskTWithPrivatesQTy) { auto &C = CGM.getContext(); FunctionArgList Args; - ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty); - ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, - /*Id=*/nullptr, - KmpTaskTWithPrivatesPtrQTy.withRestrict()); + ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty, + ImplicitParamDecl::Other); + ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, + KmpTaskTWithPrivatesPtrQTy.withRestrict(), + ImplicitParamDecl::Other); Args.push_back(&GtidArg); Args.push_back(&TaskTypeArg); FunctionType::ExtInfo Info; @@ -3472,36 +3471,40 @@ emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc, FunctionArgList Args; ImplicitParamDecl TaskPrivatesArg( C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, - C.getPointerType(PrivatesQTy).withConst().withRestrict()); + C.getPointerType(PrivatesQTy).withConst().withRestrict(), + ImplicitParamDecl::Other); Args.push_back(&TaskPrivatesArg); llvm::DenseMap<const VarDecl *, unsigned> PrivateVarsPos; unsigned Counter = 1; for (auto *E: PrivateVars) { Args.push_back(ImplicitParamDecl::Create( - C, /*DC=*/nullptr, Loc, - /*Id=*/nullptr, C.getPointerType(C.getPointerType(E->getType())) - .withConst() - .withRestrict())); + C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, + C.getPointerType(C.getPointerType(E->getType())) + .withConst() + .withRestrict(), + ImplicitParamDecl::Other)); auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); PrivateVarsPos[VD] = Counter; ++Counter; } for (auto *E : FirstprivateVars) { Args.push_back(ImplicitParamDecl::Create( - C, /*DC=*/nullptr, Loc, - /*Id=*/nullptr, C.getPointerType(C.getPointerType(E->getType())) - .withConst() - .withRestrict())); + C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, + C.getPointerType(C.getPointerType(E->getType())) + .withConst() + .withRestrict(), + ImplicitParamDecl::Other)); auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); PrivateVarsPos[VD] = Counter; ++Counter; } for (auto *E: LastprivateVars) { Args.push_back(ImplicitParamDecl::Create( - C, /*DC=*/nullptr, Loc, - /*Id=*/nullptr, C.getPointerType(C.getPointerType(E->getType())) - .withConst() - .withRestrict())); + C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, + C.getPointerType(C.getPointerType(E->getType())) + .withConst() + .withRestrict(), + ImplicitParamDecl::Other)); auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); PrivateVarsPos[VD] = Counter; ++Counter; @@ -3661,12 +3664,14 @@ emitTaskDupFunction(CodeGenModule &CGM, SourceLocation Loc, ArrayRef<PrivateDataTy> Privates, bool WithLastIter) { auto &C = CGM.getContext(); FunctionArgList Args; - ImplicitParamDecl DstArg(C, /*DC=*/nullptr, Loc, - /*Id=*/nullptr, KmpTaskTWithPrivatesPtrQTy); - ImplicitParamDecl SrcArg(C, /*DC=*/nullptr, Loc, - /*Id=*/nullptr, KmpTaskTWithPrivatesPtrQTy); - ImplicitParamDecl LastprivArg(C, /*DC=*/nullptr, Loc, - /*Id=*/nullptr, C.IntTy); + ImplicitParamDecl DstArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, + KmpTaskTWithPrivatesPtrQTy, + ImplicitParamDecl::Other); + ImplicitParamDecl SrcArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, + KmpTaskTWithPrivatesPtrQTy, + ImplicitParamDecl::Other); + ImplicitParamDecl LastprivArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.IntTy, + ImplicitParamDecl::Other); Args.push_back(&DstArg); Args.push_back(&SrcArg); Args.push_back(&LastprivArg); @@ -4278,10 +4283,8 @@ llvm::Value *CGOpenMPRuntime::emitReductionFunction( // void reduction_func(void *LHSArg, void *RHSArg); FunctionArgList Args; - ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr, - C.VoidPtrTy); - ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr, - C.VoidPtrTy); + ImplicitParamDecl LHSArg(C, C.VoidPtrTy, ImplicitParamDecl::Other); + ImplicitParamDecl RHSArg(C, C.VoidPtrTy, ImplicitParamDecl::Other); Args.push_back(&LHSArg); Args.push_back(&RHSArg); auto &CGFI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); diff --git a/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp b/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp index bbedac962d55..3ced05d08a47 100644 --- a/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp +++ b/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp @@ -1252,24 +1252,19 @@ emitReduceScratchpadFunction(CodeGenModule &CGM, auto Int32Ty = C.getIntTypeForBitwidth(32, /* Signed */ true); // Destination of the copy. - ImplicitParamDecl ReduceListArg(C, /*DC=*/nullptr, SourceLocation(), - /*Id=*/nullptr, C.VoidPtrTy); + ImplicitParamDecl ReduceListArg(C, C.VoidPtrTy, ImplicitParamDecl::Other); // Base address of the scratchpad array, with each element storing a // Reduce list per team. - ImplicitParamDecl ScratchPadArg(C, /*DC=*/nullptr, SourceLocation(), - /*Id=*/nullptr, C.VoidPtrTy); + ImplicitParamDecl ScratchPadArg(C, C.VoidPtrTy, ImplicitParamDecl::Other); // A source index into the scratchpad array. - ImplicitParamDecl IndexArg(C, /*DC=*/nullptr, SourceLocation(), - /*Id=*/nullptr, Int32Ty); + ImplicitParamDecl IndexArg(C, Int32Ty, ImplicitParamDecl::Other); // Row width of an element in the scratchpad array, typically // the number of teams. - ImplicitParamDecl WidthArg(C, /*DC=*/nullptr, SourceLocation(), - /*Id=*/nullptr, Int32Ty); + ImplicitParamDecl WidthArg(C, Int32Ty, ImplicitParamDecl::Other); // If should_reduce == 1, then it's load AND reduce, // If should_reduce == 0 (or otherwise), then it only loads (+ copy). // The latter case is used for initialization. - ImplicitParamDecl ShouldReduceArg(C, /*DC=*/nullptr, SourceLocation(), - /*Id=*/nullptr, Int32Ty); + ImplicitParamDecl ShouldReduceArg(C, Int32Ty, ImplicitParamDecl::Other); FunctionArgList Args; Args.push_back(&ReduceListArg); @@ -1381,20 +1376,16 @@ static llvm::Value *emitCopyToScratchpad(CodeGenModule &CGM, auto Int32Ty = C.getIntTypeForBitwidth(32, /* Signed */ true); // Source of the copy. - ImplicitParamDecl ReduceListArg(C, /*DC=*/nullptr, SourceLocation(), - /*Id=*/nullptr, C.VoidPtrTy); + ImplicitParamDecl ReduceListArg(C, C.VoidPtrTy, ImplicitParamDecl::Other); // Base address of the scratchpad array, with each element storing a // Reduce list per team. - ImplicitParamDecl ScratchPadArg(C, /*DC=*/nullptr, SourceLocation(), - /*Id=*/nullptr, C.VoidPtrTy); + ImplicitParamDecl ScratchPadArg(C, C.VoidPtrTy, ImplicitParamDecl::Other); // A destination index into the scratchpad array, typically the team // identifier. - ImplicitParamDecl IndexArg(C, /*DC=*/nullptr, SourceLocation(), - /*Id=*/nullptr, Int32Ty); + ImplicitParamDecl IndexArg(C, Int32Ty, ImplicitParamDecl::Other); // Row width of an element in the scratchpad array, typically // the number of teams. - ImplicitParamDecl WidthArg(C, /*DC=*/nullptr, SourceLocation(), - /*Id=*/nullptr, Int32Ty); + ImplicitParamDecl WidthArg(C, Int32Ty, ImplicitParamDecl::Other); FunctionArgList Args; Args.push_back(&ReduceListArg); @@ -1475,13 +1466,12 @@ static llvm::Value *emitInterWarpCopyFunction(CodeGenModule &CGM, // ReduceList: thread local Reduce list. // At the stage of the computation when this function is called, partially // aggregated values reside in the first lane of every active warp. - ImplicitParamDecl ReduceListArg(C, /*DC=*/nullptr, SourceLocation(), - /*Id=*/nullptr, C.VoidPtrTy); + ImplicitParamDecl ReduceListArg(C, C.VoidPtrTy, ImplicitParamDecl::Other); // NumWarps: number of warps active in the parallel region. This could // be smaller than 32 (max warps in a CTA) for partial block reduction. - ImplicitParamDecl NumWarpsArg(C, /*DC=*/nullptr, SourceLocation(), - /*Id=*/nullptr, - C.getIntTypeForBitwidth(32, /* Signed */ true)); + ImplicitParamDecl NumWarpsArg(C, + C.getIntTypeForBitwidth(32, /* Signed */ true), + ImplicitParamDecl::Other); FunctionArgList Args; Args.push_back(&ReduceListArg); Args.push_back(&NumWarpsArg); @@ -1723,17 +1713,14 @@ emitShuffleAndReduceFunction(CodeGenModule &CGM, auto &C = CGM.getContext(); // Thread local Reduce list used to host the values of data to be reduced. - ImplicitParamDecl ReduceListArg(C, /*DC=*/nullptr, SourceLocation(), - /*Id=*/nullptr, C.VoidPtrTy); + ImplicitParamDecl ReduceListArg(C, C.VoidPtrTy, ImplicitParamDecl::Other); // Current lane id; could be logical. - ImplicitParamDecl LaneIDArg(C, /*DC=*/nullptr, SourceLocation(), - /*Id=*/nullptr, C.ShortTy); + ImplicitParamDecl LaneIDArg(C, C.ShortTy, ImplicitParamDecl::Other); // Offset of the remote source lane relative to the current lane. - ImplicitParamDecl RemoteLaneOffsetArg(C, /*DC=*/nullptr, SourceLocation(), - /*Id=*/nullptr, C.ShortTy); + ImplicitParamDecl RemoteLaneOffsetArg(C, C.ShortTy, + ImplicitParamDecl::Other); // Algorithm version. This is expected to be known at compile time. - ImplicitParamDecl AlgoVerArg(C, /*DC=*/nullptr, SourceLocation(), - /*Id=*/nullptr, C.ShortTy); + ImplicitParamDecl AlgoVerArg(C, C.ShortTy, ImplicitParamDecl::Other); FunctionArgList Args; Args.push_back(&ReduceListArg); Args.push_back(&LaneIDArg); diff --git a/lib/CodeGen/CGStmtOpenMP.cpp b/lib/CodeGen/CGStmtOpenMP.cpp index c8c71dd83e97..77f3c332a12f 100644 --- a/lib/CodeGen/CGStmtOpenMP.cpp +++ b/lib/CodeGen/CGStmtOpenMP.cpp @@ -281,8 +281,9 @@ CodeGenFunction::GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S) { ArgType = getCanonicalParamType(getContext(), ArgType.getNonReferenceType()); } - Args.push_back(ImplicitParamDecl::Create(getContext(), nullptr, - FD->getLocation(), II, ArgType)); + Args.push_back(ImplicitParamDecl::Create(getContext(), /*DC=*/nullptr, + FD->getLocation(), II, ArgType, + ImplicitParamDecl::Other)); ++I; } Args.append( diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index b6d7f0255017..ac1a1334f103 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -1083,10 +1083,9 @@ QualType CodeGenFunction::BuildFunctionArgList(GlobalDecl GD, if (!Param->hasAttr<PassObjectSizeAttr>()) continue; - IdentifierInfo *NoID = nullptr; auto *Implicit = ImplicitParamDecl::Create( - getContext(), Param->getDeclContext(), Param->getLocation(), NoID, - getContext().getSizeType()); + getContext(), Param->getDeclContext(), Param->getLocation(), + /*Id=*/nullptr, getContext().getSizeType(), ImplicitParamDecl::Other); SizeArguments[Param] = Implicit; Args.push_back(Implicit); } diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index dde8f2e36920..77adf7b441a2 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -1026,9 +1026,25 @@ void CodeGenModule::setNonAliasAttributes(const Decl *D, llvm::GlobalObject *GO) { SetCommonAttributes(D, GO); - if (D) + if (D) { + if (auto *GV = dyn_cast<llvm::GlobalVariable>(GO)) { + if (auto *SA = D->getAttr<PragmaClangBSSSectionAttr>()) + GV->addAttribute("bss-section", SA->getName()); + if (auto *SA = D->getAttr<PragmaClangDataSectionAttr>()) + GV->addAttribute("data-section", SA->getName()); + if (auto *SA = D->getAttr<PragmaClangRodataSectionAttr>()) + GV->addAttribute("rodata-section", SA->getName()); + } + + if (auto *F = dyn_cast<llvm::Function>(GO)) { + if (auto *SA = D->getAttr<PragmaClangTextSectionAttr>()) + if (!D->getAttr<SectionAttr>()) + F->addFnAttr("implicit-section-name", SA->getName()); + } + if (const SectionAttr *SA = D->getAttr<SectionAttr>()) GO->setSection(SA->getName()); + } getTargetCodeGenInfo().setTargetAttributes(D, GO, *this); } @@ -1127,6 +1143,10 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F, setLinkageAndVisibilityForGV(F, FD); + if (FD->getAttr<PragmaClangTextSectionAttr>()) { + F->addFnAttr("implicit-section-name"); + } + if (const SectionAttr *SA = FD->getAttr<SectionAttr>()) F->setSection(SA->getName()); @@ -2828,6 +2848,14 @@ static bool isVarDeclStrongDefinition(const ASTContext &Context, if (D->hasAttr<SectionAttr>()) return true; + // A variable cannot be both common and exist in a section. + // We dont try to determine which is the right section in the front-end. + // If no specialized section name is applicable, it will resort to default. + if (D->hasAttr<PragmaClangBSSSectionAttr>() || + D->hasAttr<PragmaClangDataSectionAttr>() || + D->hasAttr<PragmaClangRodataSectionAttr>()) + return true; + // Thread local vars aren't considered common linkage. if (D->getTLSKind()) return true; diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp index 62b0e6155f99..39efb9f43921 100644 --- a/lib/CodeGen/ItaniumCXXABI.cpp +++ b/lib/CodeGen/ItaniumCXXABI.cpp @@ -1408,9 +1408,9 @@ void ItaniumCXXABI::addImplicitStructorParams(CodeGenFunction &CGF, // FIXME: avoid the fake decl QualType T = Context.getPointerType(Context.VoidPtrTy); - ImplicitParamDecl *VTTDecl - = ImplicitParamDecl::Create(Context, nullptr, MD->getLocation(), - &Context.Idents.get("vtt"), T); + auto *VTTDecl = ImplicitParamDecl::Create( + Context, /*DC=*/nullptr, MD->getLocation(), &Context.Idents.get("vtt"), + T, ImplicitParamDecl::CXXVTT); Params.insert(Params.begin() + 1, VTTDecl); getStructorImplicitParamDecl(CGF) = VTTDecl; } diff --git a/lib/CodeGen/MicrosoftCXXABI.cpp b/lib/CodeGen/MicrosoftCXXABI.cpp index ff5aca88131e..e68a16e0bd51 100644 --- a/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/lib/CodeGen/MicrosoftCXXABI.cpp @@ -1413,11 +1413,10 @@ void MicrosoftCXXABI::addImplicitStructorParams(CodeGenFunction &CGF, const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl()); assert(isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD)); if (isa<CXXConstructorDecl>(MD) && MD->getParent()->getNumVBases()) { - ImplicitParamDecl *IsMostDerived - = ImplicitParamDecl::Create(Context, nullptr, - CGF.CurGD.getDecl()->getLocation(), - &Context.Idents.get("is_most_derived"), - Context.IntTy); + auto *IsMostDerived = ImplicitParamDecl::Create( + Context, /*DC=*/nullptr, CGF.CurGD.getDecl()->getLocation(), + &Context.Idents.get("is_most_derived"), Context.IntTy, + ImplicitParamDecl::Other); // The 'most_derived' parameter goes second if the ctor is variadic and last // if it's not. Dtors can't be variadic. const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>(); @@ -1427,11 +1426,10 @@ void MicrosoftCXXABI::addImplicitStructorParams(CodeGenFunction &CGF, Params.push_back(IsMostDerived); getStructorImplicitParamDecl(CGF) = IsMostDerived; } else if (isDeletingDtor(CGF.CurGD)) { - ImplicitParamDecl *ShouldDelete - = ImplicitParamDecl::Create(Context, nullptr, - CGF.CurGD.getDecl()->getLocation(), - &Context.Idents.get("should_call_delete"), - Context.IntTy); + auto *ShouldDelete = ImplicitParamDecl::Create( + Context, /*DC=*/nullptr, CGF.CurGD.getDecl()->getLocation(), + &Context.Idents.get("should_call_delete"), Context.IntTy, + ImplicitParamDecl::Other); Params.push_back(ShouldDelete); getStructorImplicitParamDecl(CGF) = ShouldDelete; } @@ -3875,18 +3873,21 @@ MicrosoftCXXABI::getAddrOfCXXCtorClosure(const CXXConstructorDecl *CD, // Following the 'this' pointer is a reference to the source object that we // are copying from. ImplicitParamDecl SrcParam( - getContext(), nullptr, SourceLocation(), &getContext().Idents.get("src"), + getContext(), /*DC=*/nullptr, SourceLocation(), + &getContext().Idents.get("src"), getContext().getLValueReferenceType(RecordTy, - /*SpelledAsLValue=*/true)); + /*SpelledAsLValue=*/true), + ImplicitParamDecl::Other); if (IsCopy) FunctionArgs.push_back(&SrcParam); // Constructors for classes which utilize virtual bases have an additional // parameter which indicates whether or not it is being delegated to by a more // derived constructor. - ImplicitParamDecl IsMostDerived(getContext(), nullptr, SourceLocation(), + ImplicitParamDecl IsMostDerived(getContext(), /*DC=*/nullptr, + SourceLocation(), &getContext().Idents.get("is_most_derived"), - getContext().IntTy); + getContext().IntTy, ImplicitParamDecl::Other); // Only add the parameter to the list if thie class has virtual bases. if (RD->getNumVBases() > 0) FunctionArgs.push_back(&IsMostDerived); diff --git a/lib/Driver/CMakeLists.txt b/lib/Driver/CMakeLists.txt index 247626d8200e..b639927a95b6 100644 --- a/lib/Driver/CMakeLists.txt +++ b/lib/Driver/CMakeLists.txt @@ -1,4 +1,5 @@ set(LLVM_LINK_COMPONENTS + BinaryFormat Option Support ) diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp index d07ac96a3108..eb504fd4e541 100644 --- a/lib/Driver/Driver.cpp +++ b/lib/Driver/Driver.cpp @@ -68,6 +68,7 @@ #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/Process.h" #include "llvm/Support/Program.h" +#include "llvm/Support/TargetRegistry.h" #include "llvm/Support/raw_ostream.h" #include <map> #include <memory> @@ -1161,6 +1162,10 @@ bool Driver::HandleImmediateArgs(const Compilation &C) { if (C.getArgs().hasArg(options::OPT__version)) { // Follow gcc behavior and use stdout for --version and stderr for -v. PrintVersion(C, llvm::outs()); + + // Print registered targets. + llvm::outs() << '\n'; + llvm::TargetRegistry::printRegisteredTargetsForVersion(llvm::outs()); return false; } @@ -2667,6 +2672,8 @@ Action *Driver::ConstructPhaseAction(Compilation &C, const ArgList &Args, OutputTy = Input->getType(); if (!Args.hasFlag(options::OPT_frewrite_includes, options::OPT_fno_rewrite_includes, false) && + !Args.hasFlag(options::OPT_frewrite_imports, + options::OPT_fno_rewrite_imports, false) && !CCGenDiagnostics) OutputTy = types::getPreprocessedType(OutputTy); assert(OutputTy != types::TY_INVALID && diff --git a/lib/Driver/SanitizerArgs.cpp b/lib/Driver/SanitizerArgs.cpp index ad2b4ada9a83..d6a9c35eda78 100644 --- a/lib/Driver/SanitizerArgs.cpp +++ b/lib/Driver/SanitizerArgs.cpp @@ -31,8 +31,8 @@ enum : SanitizerMask { NotAllowedWithTrap = Vptr, RequiresPIE = DataFlow, NeedsUnwindTables = Address | Thread | Memory | DataFlow, - SupportsCoverage = - Address | Memory | Leak | Undefined | Integer | Nullability | DataFlow, + SupportsCoverage = Address | KernelAddress | Memory | Leak | Undefined | + Integer | Nullability | DataFlow, RecoverableByDefault = Undefined | Integer | Nullability, Unrecoverable = Unreachable | Return, LegacyFsanitizeRecoverMask = Undefined | Integer, diff --git a/lib/Driver/ToolChains/Arch/Mips.cpp b/lib/Driver/ToolChains/Arch/Mips.cpp index f33542477fb5..33eff32b9731 100644 --- a/lib/Driver/ToolChains/Arch/Mips.cpp +++ b/lib/Driver/ToolChains/Arch/Mips.cpp @@ -298,6 +298,13 @@ void mips::getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple, AddTargetFeature(Args, Features, options::OPT_mno_odd_spreg, options::OPT_modd_spreg, "nooddspreg"); + + if (Arg *A = Args.getLastArg(options::OPT_mmadd4, options::OPT_mno_madd4)) { + if (A->getOption().matches(options::OPT_mmadd4)) + Features.push_back("-nomadd4"); + else + Features.push_back("+nomadd4"); + } } mips::NanEncoding mips::getSupportedNanEncoding(StringRef &CPU) { diff --git a/lib/Driver/ToolChains/Clang.cpp b/lib/Driver/ToolChains/Clang.cpp index 698c3aa326cb..6d3dbb5b5204 100644 --- a/lib/Driver/ToolChains/Clang.cpp +++ b/lib/Driver/ToolChains/Clang.cpp @@ -4204,13 +4204,18 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } #endif + bool RewriteImports = Args.hasFlag(options::OPT_frewrite_imports, + options::OPT_fno_rewrite_imports, false); + if (RewriteImports) + CmdArgs.push_back("-frewrite-imports"); + // Enable rewrite includes if the user's asked for it or if we're generating // diagnostics. // TODO: Once -module-dependency-dir works with -frewrite-includes it'd be // nice to enable this when doing a crashdump for modules as well. if (Args.hasFlag(options::OPT_frewrite_includes, options::OPT_fno_rewrite_includes, false) || - (C.isForDiagnostics() && !HaveAnyModules)) + (C.isForDiagnostics() && (RewriteImports || !HaveAnyModules))) CmdArgs.push_back("-frewrite-includes"); // Only allow -traditional or -traditional-cpp outside in preprocessing modes. diff --git a/lib/Driver/ToolChains/Linux.cpp b/lib/Driver/ToolChains/Linux.cpp index 9da366eb55fe..08a27fa7fed1 100644 --- a/lib/Driver/ToolChains/Linux.cpp +++ b/lib/Driver/ToolChains/Linux.cpp @@ -822,8 +822,9 @@ SanitizerMask Linux::getSupportedSanitizers() const { const bool IsAArch64 = getTriple().getArch() == llvm::Triple::aarch64 || getTriple().getArch() == llvm::Triple::aarch64_be; const bool IsArmArch = getTriple().getArch() == llvm::Triple::arm || - llvm::Triple::thumb || llvm::Triple::armeb || - llvm::Triple::thumbeb; + getTriple().getArch() == llvm::Triple::thumb || + getTriple().getArch() == llvm::Triple::armeb || + getTriple().getArch() == llvm::Triple::thumbeb; SanitizerMask Res = ToolChain::getSupportedSanitizers(); Res |= SanitizerKind::Address; Res |= SanitizerKind::Fuzzer; diff --git a/lib/Driver/ToolChains/MSVC.cpp b/lib/Driver/ToolChains/MSVC.cpp index 6f5f54165b3b..9e9d943610be 100644 --- a/lib/Driver/ToolChains/MSVC.cpp +++ b/lib/Driver/ToolChains/MSVC.cpp @@ -529,9 +529,7 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA, SkipSettingEnvironment:; #endif } else { - linkPath = Linker; - llvm::sys::path::replace_extension(linkPath, "exe"); - linkPath = TC.GetProgramPath(linkPath.c_str()); + linkPath = TC.GetProgramPath(Linker.str().c_str()); } auto LinkCmd = llvm::make_unique<Command>( diff --git a/lib/Edit/EditedSource.cpp b/lib/Edit/EditedSource.cpp index 1a7a68cffb62..03d45cf185c9 100644 --- a/lib/Edit/EditedSource.cpp +++ b/lib/Edit/EditedSource.cpp @@ -25,17 +25,16 @@ void EditsReceiver::remove(CharSourceRange range) { void EditedSource::deconstructMacroArgLoc(SourceLocation Loc, SourceLocation &ExpansionLoc, - IdentifierInfo *&II) { + MacroArgUse &ArgUse) { assert(SourceMgr.isMacroArgExpansion(Loc)); SourceLocation DefArgLoc = SourceMgr.getImmediateExpansionRange(Loc).first; ExpansionLoc = SourceMgr.getImmediateExpansionRange(DefArgLoc).first; SmallString<20> Buf; StringRef ArgName = Lexer::getSpelling(SourceMgr.getSpellingLoc(DefArgLoc), Buf, SourceMgr, LangOpts); - II = nullptr; - if (!ArgName.empty()) { - II = &IdentTable.get(ArgName); - } + ArgUse = {nullptr, SourceLocation()}; + if (!ArgName.empty()) + ArgUse = {&IdentTable.get(ArgName), SourceMgr.getSpellingLoc(DefArgLoc)}; } void EditedSource::startingCommit() {} @@ -43,12 +42,11 @@ void EditedSource::startingCommit() {} void EditedSource::finishedCommit() { for (auto &ExpArg : CurrCommitMacroArgExps) { SourceLocation ExpLoc; - IdentifierInfo *II; - std::tie(ExpLoc, II) = ExpArg; - auto &ArgNames = ExpansionToArgMap[ExpLoc.getRawEncoding()]; - if (std::find(ArgNames.begin(), ArgNames.end(), II) == ArgNames.end()) { - ArgNames.push_back(II); - } + MacroArgUse ArgUse; + std::tie(ExpLoc, ArgUse) = ExpArg; + auto &ArgUses = ExpansionToArgMap[ExpLoc.getRawEncoding()]; + if (std::find(ArgUses.begin(), ArgUses.end(), ArgUse) == ArgUses.end()) + ArgUses.push_back(ArgUse); } CurrCommitMacroArgExps.clear(); } @@ -66,12 +64,15 @@ bool EditedSource::canInsertInOffset(SourceLocation OrigLoc, FileOffset Offs) { } if (SourceMgr.isMacroArgExpansion(OrigLoc)) { - IdentifierInfo *II; SourceLocation ExpLoc; - deconstructMacroArgLoc(OrigLoc, ExpLoc, II); + MacroArgUse ArgUse; + deconstructMacroArgLoc(OrigLoc, ExpLoc, ArgUse); auto I = ExpansionToArgMap.find(ExpLoc.getRawEncoding()); if (I != ExpansionToArgMap.end() && - std::find(I->second.begin(), I->second.end(), II) != I->second.end()) { + std::find_if( + I->second.begin(), I->second.end(), [&](const MacroArgUse &U) { + return ArgUse.first == U.first && ArgUse.second != U.second; + }) != I->second.end()) { // Trying to write in a macro argument input that has already been // written by a previous commit for another expansion of the same macro // argument name. For example: @@ -101,11 +102,11 @@ bool EditedSource::commitInsert(SourceLocation OrigLoc, return true; if (SourceMgr.isMacroArgExpansion(OrigLoc)) { - IdentifierInfo *II; SourceLocation ExpLoc; - deconstructMacroArgLoc(OrigLoc, ExpLoc, II); - if (II) - CurrCommitMacroArgExps.emplace_back(ExpLoc, II); + MacroArgUse ArgUse; + deconstructMacroArgLoc(OrigLoc, ExpLoc, ArgUse); + if (ArgUse.first) + CurrCommitMacroArgExps.emplace_back(ExpLoc, ArgUse); } FileEdit &FA = FileEdits[Offs]; diff --git a/lib/Format/ContinuationIndenter.cpp b/lib/Format/ContinuationIndenter.cpp index ae1af753bf46..387923031f85 100644 --- a/lib/Format/ContinuationIndenter.cpp +++ b/lib/Format/ContinuationIndenter.cpp @@ -1036,8 +1036,8 @@ void ContinuationIndenter::moveStatePastScopeOpener(LineState &State, State.Stack.back().NestedBlockIndent); if (Current.isOneOf(tok::l_brace, TT_ArrayInitializerLSquare)) { if (Current.opensBlockOrBlockTypeList(Style)) { - NewIndent = State.Stack.back().NestedBlockIndent + Style.IndentWidth; - NewIndent = std::min(State.Column + 2, NewIndent); + NewIndent = Style.IndentWidth + + std::min(State.Column, State.Stack.back().NestedBlockIndent); } else { NewIndent = State.Stack.back().LastSpace + Style.ContinuationIndentWidth; } diff --git a/lib/Format/TokenAnnotator.cpp b/lib/Format/TokenAnnotator.cpp index 2af931cdf1ba..7ce699cf14a1 100644 --- a/lib/Format/TokenAnnotator.cpp +++ b/lib/Format/TokenAnnotator.cpp @@ -135,8 +135,11 @@ private: if (Left->is(TT_OverloadedOperatorLParen)) { Contexts.back().IsExpression = false; } else if (Style.Language == FormatStyle::LK_JavaScript && - Line.startsWith(Keywords.kw_type, tok::identifier)) { + (Line.startsWith(Keywords.kw_type, tok::identifier) || + Line.startsWith(tok::kw_export, Keywords.kw_type, + tok::identifier))) { // type X = (...); + // export type X = (...); Contexts.back().IsExpression = false; } else if (Left->Previous && (Left->Previous->isOneOf(tok::kw_static_assert, tok::kw_decltype, @@ -979,9 +982,12 @@ private: void modifyContext(const FormatToken &Current) { if (Current.getPrecedence() == prec::Assignment && !Line.First->isOneOf(tok::kw_template, tok::kw_using, tok::kw_return) && - // Type aliases use `type X = ...;` in TypeScript. + // Type aliases use `type X = ...;` in TypeScript and can be exported + // using `export type ...`. !(Style.Language == FormatStyle::LK_JavaScript && - Line.startsWith(Keywords.kw_type, tok::identifier)) && + (Line.startsWith(Keywords.kw_type, tok::identifier) || + Line.startsWith(tok::kw_export, Keywords.kw_type, + tok::identifier))) && (!Current.Previous || Current.Previous->isNot(tok::kw_operator))) { Contexts.back().IsExpression = true; if (!Line.startsWith(TT_UnaryOperator)) { diff --git a/lib/Format/WhitespaceManager.cpp b/lib/Format/WhitespaceManager.cpp index 3b6311d15487..4b4fd13145fb 100644 --- a/lib/Format/WhitespaceManager.cpp +++ b/lib/Format/WhitespaceManager.cpp @@ -100,18 +100,56 @@ void WhitespaceManager::calculateLineBreakInformation() { Changes[0].PreviousEndOfTokenColumn = 0; Change *LastOutsideTokenChange = &Changes[0]; for (unsigned i = 1, e = Changes.size(); i != e; ++i) { - unsigned OriginalWhitespaceStart = - SourceMgr.getFileOffset(Changes[i].OriginalWhitespaceRange.getBegin()); - unsigned PreviousOriginalWhitespaceEnd = SourceMgr.getFileOffset( - Changes[i - 1].OriginalWhitespaceRange.getEnd()); - Changes[i - 1].TokenLength = OriginalWhitespaceStart - - PreviousOriginalWhitespaceEnd + - Changes[i].PreviousLinePostfix.size() + - Changes[i - 1].CurrentLinePrefix.size(); + SourceLocation OriginalWhitespaceStart = + Changes[i].OriginalWhitespaceRange.getBegin(); + SourceLocation PreviousOriginalWhitespaceEnd = + Changes[i - 1].OriginalWhitespaceRange.getEnd(); + unsigned OriginalWhitespaceStartOffset = + SourceMgr.getFileOffset(OriginalWhitespaceStart); + unsigned PreviousOriginalWhitespaceEndOffset = + SourceMgr.getFileOffset(PreviousOriginalWhitespaceEnd); + assert(PreviousOriginalWhitespaceEndOffset <= + OriginalWhitespaceStartOffset); + const char *const PreviousOriginalWhitespaceEndData = + SourceMgr.getCharacterData(PreviousOriginalWhitespaceEnd); + StringRef Text(PreviousOriginalWhitespaceEndData, + SourceMgr.getCharacterData(OriginalWhitespaceStart) - + PreviousOriginalWhitespaceEndData); + // Usually consecutive changes would occur in consecutive tokens. This is + // not the case however when analyzing some preprocessor runs of the + // annotated lines. For example, in this code: + // + // #if A // line 1 + // int i = 1; + // #else B // line 2 + // int i = 2; + // #endif // line 3 + // + // one of the runs will produce the sequence of lines marked with line 1, 2 + // and 3. So the two consecutive whitespace changes just before '// line 2' + // and before '#endif // line 3' span multiple lines and tokens: + // + // #else B{change X}[// line 2 + // int i = 2; + // ]{change Y}#endif // line 3 + // + // For this reason, if the text between consecutive changes spans multiple + // newlines, the token length must be adjusted to the end of the original + // line of the token. + auto NewlinePos = Text.find_first_of('\n'); + if (NewlinePos == StringRef::npos) { + Changes[i - 1].TokenLength = OriginalWhitespaceStartOffset - + PreviousOriginalWhitespaceEndOffset + + Changes[i].PreviousLinePostfix.size() + + Changes[i - 1].CurrentLinePrefix.size(); + } else { + Changes[i - 1].TokenLength = + NewlinePos + Changes[i - 1].CurrentLinePrefix.size(); + } // If there are multiple changes in this token, sum up all the changes until // the end of the line. - if (Changes[i - 1].IsInsideToken) + if (Changes[i - 1].IsInsideToken && Changes[i - 1].NewlinesBefore == 0) LastOutsideTokenChange->TokenLength += Changes[i - 1].TokenLength + Changes[i - 1].Spaces; else @@ -434,7 +472,9 @@ void WhitespaceManager::alignTrailingComments() { continue; unsigned ChangeMinColumn = Changes[i].StartOfTokenColumn; - unsigned ChangeMaxColumn = Style.ColumnLimit - Changes[i].TokenLength; + unsigned ChangeMaxColumn = Style.ColumnLimit >= Changes[i].TokenLength + ? Style.ColumnLimit - Changes[i].TokenLength + : ChangeMinColumn; // If we don't create a replacement for this change, we have to consider // it to be immovable. diff --git a/lib/Frontend/ASTMerge.cpp b/lib/Frontend/ASTMerge.cpp index 51064da270cc..986f98ae598b 100644 --- a/lib/Frontend/ASTMerge.cpp +++ b/lib/Frontend/ASTMerge.cpp @@ -21,14 +21,13 @@ ASTMergeAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { return AdaptedAction->CreateASTConsumer(CI, InFile); } -bool ASTMergeAction::BeginSourceFileAction(CompilerInstance &CI, - StringRef Filename) { +bool ASTMergeAction::BeginSourceFileAction(CompilerInstance &CI) { // FIXME: This is a hack. We need a better way to communicate the // AST file, compiler instance, and file name than member variables // of FrontendAction. AdaptedAction->setCurrentInput(getCurrentInput(), takeCurrentASTUnit()); AdaptedAction->setCompilerInstance(&CI); - return AdaptedAction->BeginSourceFileAction(CI, Filename); + return AdaptedAction->BeginSourceFileAction(CI); } void ASTMergeAction::ExecuteAction() { diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp index 01f7ca8aba9b..8d139f2c0a6d 100644 --- a/lib/Frontend/ASTUnit.cpp +++ b/lib/Frontend/ASTUnit.cpp @@ -486,6 +486,8 @@ namespace { class ASTInfoCollector : public ASTReaderListener { Preprocessor &PP; ASTContext &Context; + HeaderSearchOptions &HSOpts; + PreprocessorOptions &PPOpts; LangOptions &LangOpt; std::shared_ptr<TargetOptions> &TargetOpts; IntrusiveRefCntPtr<TargetInfo> &Target; @@ -493,11 +495,14 @@ class ASTInfoCollector : public ASTReaderListener { bool InitializedLanguage; public: - ASTInfoCollector(Preprocessor &PP, ASTContext &Context, LangOptions &LangOpt, + ASTInfoCollector(Preprocessor &PP, ASTContext &Context, + HeaderSearchOptions &HSOpts, PreprocessorOptions &PPOpts, + LangOptions &LangOpt, std::shared_ptr<TargetOptions> &TargetOpts, IntrusiveRefCntPtr<TargetInfo> &Target, unsigned &Counter) - : PP(PP), Context(Context), LangOpt(LangOpt), TargetOpts(TargetOpts), - Target(Target), Counter(Counter), InitializedLanguage(false) {} + : PP(PP), Context(Context), HSOpts(HSOpts), PPOpts(PPOpts), + LangOpt(LangOpt), TargetOpts(TargetOpts), Target(Target), + Counter(Counter), InitializedLanguage(false) {} bool ReadLanguageOptions(const LangOptions &LangOpts, bool Complain, bool AllowCompatibleDifferences) override { @@ -511,6 +516,20 @@ public: return false; } + virtual bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts, + StringRef SpecificModuleCachePath, + bool Complain) override { + this->HSOpts = HSOpts; + return false; + } + + virtual bool + ReadPreprocessorOptions(const PreprocessorOptions &PPOpts, bool Complain, + std::string &SuggestedPredefines) override { + this->PPOpts = PPOpts; + return false; + } + bool ReadTargetOptions(const TargetOptions &TargetOpts, bool Complain, bool AllowCompatibleDifferences) override { // If we've already initialized the target, don't do it again. @@ -667,6 +686,7 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile( ConfigureDiags(Diags, *AST, CaptureDiagnostics); + AST->LangOpts = std::make_shared<LangOptions>(); AST->OnlyLocalDecls = OnlyLocalDecls; AST->CaptureDiagnostics = CaptureDiagnostics; AST->Diagnostics = Diags; @@ -682,13 +702,12 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile( AST->HeaderInfo.reset(new HeaderSearch(AST->HSOpts, AST->getSourceManager(), AST->getDiagnostics(), - AST->ASTFileLangOpts, + AST->getLangOpts(), /*Target=*/nullptr)); - - auto PPOpts = std::make_shared<PreprocessorOptions>(); + AST->PPOpts = std::make_shared<PreprocessorOptions>(); for (const auto &RemappedFile : RemappedFiles) - PPOpts->addRemappedFile(RemappedFile.first, RemappedFile.second); + AST->PPOpts->addRemappedFile(RemappedFile.first, RemappedFile.second); // Gather Info for preprocessor construction later on. @@ -696,13 +715,13 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile( unsigned Counter; AST->PP = std::make_shared<Preprocessor>( - std::move(PPOpts), AST->getDiagnostics(), AST->ASTFileLangOpts, - AST->getSourceManager(), *AST->PCMCache, HeaderInfo, *AST, + AST->PPOpts, AST->getDiagnostics(), *AST->LangOpts, + AST->getSourceManager(), *AST->PCMCache, HeaderInfo, AST->ModuleLoader, /*IILookup=*/nullptr, /*OwnsHeaderSearch=*/false); Preprocessor &PP = *AST->PP; - AST->Ctx = new ASTContext(AST->ASTFileLangOpts, AST->getSourceManager(), + AST->Ctx = new ASTContext(*AST->LangOpts, AST->getSourceManager(), PP.getIdentifierTable(), PP.getSelectorTable(), PP.getBuiltinInfo()); ASTContext &Context = *AST->Ctx; @@ -716,8 +735,8 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile( AllowPCHWithCompilerErrors); AST->Reader->setListener(llvm::make_unique<ASTInfoCollector>( - *AST->PP, Context, AST->ASTFileLangOpts, AST->TargetOpts, AST->Target, - Counter)); + *AST->PP, Context, *AST->HSOpts, *AST->PPOpts, *AST->LangOpts, + AST->TargetOpts, AST->Target, Counter)); // Attach the AST reader to the AST context as an external AST // source, so that declarations will be deserialized from the @@ -1140,6 +1159,8 @@ bool ASTUnit::Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps, if (SavedMainFileBuffer) TranslateStoredDiagnostics(getFileManager(), getSourceManager(), PreambleDiagnostics, StoredDiagnostics); + else + PreambleSrcLocCache.clear(); if (!Act->Execute()) goto error; @@ -1963,7 +1984,7 @@ ASTUnit *ASTUnit::LoadFromCommandLine( unsigned PrecompilePreambleAfterNParses, TranslationUnitKind TUKind, bool CacheCodeCompletionResults, bool IncludeBriefCommentsInCodeCompletion, bool AllowPCHWithCompilerErrors, bool SkipFunctionBodies, - bool UserFilesAreVolatile, bool ForSerialization, + bool SingleFileParse, bool UserFilesAreVolatile, bool ForSerialization, llvm::Optional<StringRef> ModuleFormat, std::unique_ptr<ASTUnit> *ErrAST, IntrusiveRefCntPtr<vfs::FileSystem> VFS) { assert(Diags.get() && "no DiagnosticsEngine was provided"); @@ -1992,6 +2013,7 @@ ASTUnit *ASTUnit::LoadFromCommandLine( PPOpts.RemappedFilesKeepOriginalName = RemappedFilesKeepOriginalName; PPOpts.AllowPCHWithCompilerErrors = AllowPCHWithCompilerErrors; PPOpts.GeneratePreamble = PrecompilePreambleAfterNParses != 0; + PPOpts.SingleFileParseMode = SingleFileParse; // Override the resources path. CI->getHeaderSearchOpts().ResourceDir = ResourceFilesPath; @@ -2582,11 +2604,9 @@ void ASTUnit::TranslateStoredDiagnostics( // remap all the locations to the new view. This includes the diag location, // any associated source ranges, and the source ranges of associated fix-its. // FIXME: There should be a cleaner way to do this. - SmallVector<StoredDiagnostic, 4> Result; Result.reserve(Diags.size()); - const FileEntry *PreviousFE = nullptr; - FileID FID; + for (const StandaloneDiagnostic &SD : Diags) { // Rebuild the StoredDiagnostic. if (SD.Filename.empty()) @@ -2594,11 +2614,16 @@ void ASTUnit::TranslateStoredDiagnostics( const FileEntry *FE = FileMgr.getFile(SD.Filename); if (!FE) continue; - if (FE != PreviousFE) { - FID = SrcMgr.translateFile(FE); - PreviousFE = FE; + SourceLocation FileLoc; + auto ItFileID = PreambleSrcLocCache.find(SD.Filename); + if (ItFileID == PreambleSrcLocCache.end()) { + FileID FID = SrcMgr.translateFile(FE); + FileLoc = SrcMgr.getLocForStartOfFile(FID); + PreambleSrcLocCache[SD.Filename] = FileLoc; + } else { + FileLoc = ItFileID->getValue(); } - SourceLocation FileLoc = SrcMgr.getLocForStartOfFile(FID); + if (FileLoc.isInvalid()) continue; SourceLocation L = FileLoc.getLocWithOffset(SD.LocOffset); @@ -2879,7 +2904,32 @@ const FileEntry *ASTUnit::getPCHFile() { } bool ASTUnit::isModuleFile() { - return isMainFileAST() && ASTFileLangOpts.isCompilingModule(); + return isMainFileAST() && getLangOpts().isCompilingModule(); +} + +InputKind ASTUnit::getInputKind() const { + auto &LangOpts = getLangOpts(); + + InputKind::Language Lang; + if (LangOpts.OpenCL) + Lang = InputKind::OpenCL; + else if (LangOpts.CUDA) + Lang = InputKind::CUDA; + else if (LangOpts.RenderScript) + Lang = InputKind::RenderScript; + else if (LangOpts.CPlusPlus) + Lang = LangOpts.ObjC1 ? InputKind::ObjCXX : InputKind::CXX; + else + Lang = LangOpts.ObjC1 ? InputKind::ObjC : InputKind::C; + + InputKind::Format Fmt = InputKind::Source; + if (LangOpts.getCompilingModule() == LangOptions::CMK_ModuleMap) + Fmt = InputKind::ModuleMap; + + // We don't know if input was preprocessed. Assume not. + bool PP = false; + + return InputKind(Lang, Fmt, PP); } void ASTUnit::PreambleData::countLines() const { diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp index e92672a785da..72a8c3818093 100644 --- a/lib/Frontend/CompilerInstance.cpp +++ b/lib/Frontend/CompilerInstance.cpp @@ -667,6 +667,11 @@ void CompilerInstance::clearOutputFiles(bool EraseFiles) { llvm::sys::fs::remove(OF.Filename); } OutputFiles.clear(); + if (DeleteBuiltModules) { + for (auto &Module : BuiltModules) + llvm::sys::fs::remove(Module.second); + BuiltModules.clear(); + } NonSeekStream.reset(); } @@ -1029,13 +1034,14 @@ static InputKind::Language getLanguageFromOptions(const LangOptions &LangOpts) { /// \brief Compile a module file for the given module, using the options /// provided by the importing compiler instance. Returns true if the module /// was built without errors. -static bool compileModuleImpl(CompilerInstance &ImportingInstance, - SourceLocation ImportLoc, - Module *Module, - StringRef ModuleFileName) { - ModuleMap &ModMap - = ImportingInstance.getPreprocessor().getHeaderSearchInfo().getModuleMap(); - +static bool +compileModuleImpl(CompilerInstance &ImportingInstance, SourceLocation ImportLoc, + StringRef ModuleName, FrontendInputFile Input, + StringRef OriginalModuleMapFile, StringRef ModuleFileName, + llvm::function_ref<void(CompilerInstance &)> PreBuildStep = + [](CompilerInstance &) {}, + llvm::function_ref<void(CompilerInstance &)> PostBuildStep = + [](CompilerInstance &) {}) { // Construct a compiler invocation for creating this module. auto Invocation = std::make_shared<CompilerInvocation>(ImportingInstance.getInvocation()); @@ -1060,7 +1066,7 @@ static bool compileModuleImpl(CompilerInstance &ImportingInstance, PPOpts.Macros.end()); // Note the name of the module we're building. - Invocation->getLangOpts()->CurrentModule = Module->getTopLevelModuleName(); + Invocation->getLangOpts()->CurrentModule = ModuleName; // Make sure that the failed-module structure has been allocated in // the importing instance, and propagate the pointer to the newly-created @@ -1080,13 +1086,10 @@ static bool compileModuleImpl(CompilerInstance &ImportingInstance, FrontendOpts.DisableFree = false; FrontendOpts.GenerateGlobalModuleIndex = false; FrontendOpts.BuildingImplicitModule = true; - FrontendOpts.OriginalModuleMap = - ModMap.getModuleMapFileForUniquing(Module)->getName(); + FrontendOpts.OriginalModuleMap = OriginalModuleMapFile; // Force implicitly-built modules to hash the content of the module file. HSOpts.ModulesHashContent = true; - FrontendOpts.Inputs.clear(); - InputKind IK(getLanguageFromOptions(*Invocation->getLangOpts()), - InputKind::ModuleMap); + FrontendOpts.Inputs = {Input}; // Don't free the remapped file buffers; they are owned by our caller. PPOpts.RetainRemappedFileBuffers = true; @@ -1117,7 +1120,7 @@ static bool compileModuleImpl(CompilerInstance &ImportingInstance, SourceManager &SourceMgr = Instance.getSourceManager(); SourceMgr.setModuleBuildStack( ImportingInstance.getSourceManager().getModuleBuildStack()); - SourceMgr.pushModuleBuildStack(Module->getTopLevelModuleName(), + SourceMgr.pushModuleBuildStack(ModuleName, FullSourceLoc(ImportLoc, ImportingInstance.getSourceManager())); // If we're collecting module dependencies, we need to share a collector @@ -1126,32 +1129,11 @@ static bool compileModuleImpl(CompilerInstance &ImportingInstance, Instance.setModuleDepCollector(ImportingInstance.getModuleDepCollector()); Inv.getDependencyOutputOpts() = DependencyOutputOptions(); - // Get or create the module map that we'll use to build this module. - std::string InferredModuleMapContent; - if (const FileEntry *ModuleMapFile = - ModMap.getContainingModuleMapFile(Module)) { - // Use the module map where this module resides. - FrontendOpts.Inputs.emplace_back(ModuleMapFile->getName(), IK, - +Module->IsSystem); - } else { - SmallString<128> FakeModuleMapFile(Module->Directory->getName()); - llvm::sys::path::append(FakeModuleMapFile, "__inferred_module.map"); - FrontendOpts.Inputs.emplace_back(FakeModuleMapFile, IK, +Module->IsSystem); - - llvm::raw_string_ostream OS(InferredModuleMapContent); - Module->print(OS); - OS.flush(); - - std::unique_ptr<llvm::MemoryBuffer> ModuleMapBuffer = - llvm::MemoryBuffer::getMemBuffer(InferredModuleMapContent); - ModuleMapFile = Instance.getFileManager().getVirtualFile( - FakeModuleMapFile, InferredModuleMapContent.size(), 0); - SourceMgr.overrideFileContents(ModuleMapFile, std::move(ModuleMapBuffer)); - } - ImportingInstance.getDiagnostics().Report(ImportLoc, diag::remark_module_build) - << Module->Name << ModuleFileName; + << ModuleName << ModuleFileName; + + PreBuildStep(Instance); // Execute the action to actually build the module in-place. Use a separate // thread so that we get a stack large enough. @@ -1164,9 +1146,11 @@ static bool compileModuleImpl(CompilerInstance &ImportingInstance, }, ThreadStackSize); + PostBuildStep(Instance); + ImportingInstance.getDiagnostics().Report(ImportLoc, diag::remark_module_build_done) - << Module->Name; + << ModuleName; // Delete the temporary module map file. // FIXME: Even though we're executing under crash protection, it would still @@ -1174,13 +1158,66 @@ static bool compileModuleImpl(CompilerInstance &ImportingInstance, // doesn't make sense for all clients, so clean this up manually. Instance.clearOutputFiles(/*EraseFiles=*/true); + return !Instance.getDiagnostics().hasErrorOccurred(); +} + +/// \brief Compile a module file for the given module, using the options +/// provided by the importing compiler instance. Returns true if the module +/// was built without errors. +static bool compileModuleImpl(CompilerInstance &ImportingInstance, + SourceLocation ImportLoc, + Module *Module, + StringRef ModuleFileName) { + InputKind IK(getLanguageFromOptions(ImportingInstance.getLangOpts()), + InputKind::ModuleMap); + + // Get or create the module map that we'll use to build this module. + ModuleMap &ModMap + = ImportingInstance.getPreprocessor().getHeaderSearchInfo().getModuleMap(); + bool Result; + if (const FileEntry *ModuleMapFile = + ModMap.getContainingModuleMapFile(Module)) { + // Use the module map where this module resides. + Result = compileModuleImpl( + ImportingInstance, ImportLoc, Module->getTopLevelModuleName(), + FrontendInputFile(ModuleMapFile->getName(), IK, +Module->IsSystem), + ModMap.getModuleMapFileForUniquing(Module)->getName(), + ModuleFileName); + } else { + // FIXME: We only need to fake up an input file here as a way of + // transporting the module's directory to the module map parser. We should + // be able to do that more directly, and parse from a memory buffer without + // inventing this file. + SmallString<128> FakeModuleMapFile(Module->Directory->getName()); + llvm::sys::path::append(FakeModuleMapFile, "__inferred_module.map"); + + std::string InferredModuleMapContent; + llvm::raw_string_ostream OS(InferredModuleMapContent); + Module->print(OS); + OS.flush(); + + Result = compileModuleImpl( + ImportingInstance, ImportLoc, Module->getTopLevelModuleName(), + FrontendInputFile(FakeModuleMapFile, IK, +Module->IsSystem), + ModMap.getModuleMapFileForUniquing(Module)->getName(), + ModuleFileName, + [&](CompilerInstance &Instance) { + std::unique_ptr<llvm::MemoryBuffer> ModuleMapBuffer = + llvm::MemoryBuffer::getMemBuffer(InferredModuleMapContent); + ModuleMapFile = Instance.getFileManager().getVirtualFile( + FakeModuleMapFile, InferredModuleMapContent.size(), 0); + Instance.getSourceManager().overrideFileContents( + ModuleMapFile, std::move(ModuleMapBuffer)); + }); + } + // We've rebuilt a module. If we're allowed to generate or update the global // module index, record that fact in the importing compiler instance. if (ImportingInstance.getFrontendOpts().GenerateGlobalModuleIndex) { ImportingInstance.setBuildGlobalModuleIndex(true); } - return !Instance.getDiagnostics().hasErrorOccurred(); + return Result; } static bool compileAndLoadModule(CompilerInstance &ImportingInstance, @@ -1586,24 +1623,36 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, PP->getHeaderSearchInfo().getHeaderSearchOpts(); std::string ModuleFileName; - bool LoadFromPrebuiltModulePath = false; - // We try to load the module from the prebuilt module paths. If not - // successful, we then try to find it in the module cache. - if (!HSOpts.PrebuiltModulePaths.empty()) { - // Load the module from the prebuilt module path. + enum ModuleSource { + ModuleNotFound, ModuleCache, PrebuiltModulePath, ModuleBuildPragma + } Source = ModuleNotFound; + + // Check to see if the module has been built as part of this compilation + // via a module build pragma. + auto BuiltModuleIt = BuiltModules.find(ModuleName); + if (BuiltModuleIt != BuiltModules.end()) { + ModuleFileName = BuiltModuleIt->second; + Source = ModuleBuildPragma; + } + + // Try to load the module from the prebuilt module path. + if (Source == ModuleNotFound && !HSOpts.PrebuiltModulePaths.empty()) { ModuleFileName = PP->getHeaderSearchInfo().getModuleFileName( ModuleName, "", /*UsePrebuiltPath*/ true); if (!ModuleFileName.empty()) - LoadFromPrebuiltModulePath = true; + Source = PrebuiltModulePath; } - if (!LoadFromPrebuiltModulePath && Module) { - // Load the module from the module cache. + + // Try to load the module from the module cache. + if (Source == ModuleNotFound && Module) { ModuleFileName = PP->getHeaderSearchInfo().getModuleFileName(Module); - } else if (!LoadFromPrebuiltModulePath) { + Source = ModuleCache; + } + + if (Source == ModuleNotFound) { // We can't find a module, error out here. getDiagnostics().Report(ModuleNameLoc, diag::err_module_not_found) - << ModuleName - << SourceRange(ImportLoc, ModuleNameLoc); + << ModuleName << SourceRange(ImportLoc, ModuleNameLoc); ModuleBuildFailed = true; return ModuleLoadResult(); } @@ -1631,20 +1680,20 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, *FrontendTimerGroup); llvm::TimeRegion TimeLoading(FrontendTimerGroup ? &Timer : nullptr); - // Try to load the module file. If we are trying to load from the prebuilt - // module path, we don't have the module map files and don't know how to - // rebuild modules. - unsigned ARRFlags = LoadFromPrebuiltModulePath ? - ASTReader::ARR_ConfigurationMismatch : - ASTReader::ARR_OutOfDate | ASTReader::ARR_Missing; + // Try to load the module file. If we are not trying to load from the + // module cache, we don't know how to rebuild modules. + unsigned ARRFlags = Source == ModuleCache ? + ASTReader::ARR_OutOfDate | ASTReader::ARR_Missing : + ASTReader::ARR_ConfigurationMismatch; switch (ModuleManager->ReadAST(ModuleFileName, - LoadFromPrebuiltModulePath ? - serialization::MK_PrebuiltModule : - serialization::MK_ImplicitModule, - ImportLoc, - ARRFlags)) { + Source == PrebuiltModulePath + ? serialization::MK_PrebuiltModule + : Source == ModuleBuildPragma + ? serialization::MK_ExplicitModule + : serialization::MK_ImplicitModule, + ImportLoc, ARRFlags)) { case ASTReader::Success: { - if (LoadFromPrebuiltModulePath && !Module) { + if (Source != ModuleCache && !Module) { Module = PP->getHeaderSearchInfo().lookupModule(ModuleName); if (!Module || !Module->getASTFile() || FileMgr->getFile(ModuleFileName) != Module->getASTFile()) { @@ -1662,10 +1711,10 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, case ASTReader::OutOfDate: case ASTReader::Missing: { - if (LoadFromPrebuiltModulePath) { - // We can't rebuild the module without a module map. Since ReadAST - // already produces diagnostics for these two cases, we simply - // error out here. + if (Source != ModuleCache) { + // We don't know the desired configuration for this module and don't + // necessarily even have a module map. Since ReadAST already produces + // diagnostics for these two cases, we simply error out here. ModuleBuildFailed = true; KnownModules[Path[0].first] = nullptr; return ModuleLoadResult(); @@ -1722,7 +1771,9 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, } case ASTReader::ConfigurationMismatch: - if (LoadFromPrebuiltModulePath) + if (Source == PrebuiltModulePath) + // FIXME: We shouldn't be setting HadFatalFailure below if we only + // produce a warning here! getDiagnostics().Report(SourceLocation(), diag::warn_module_config_mismatch) << ModuleFileName; @@ -1751,7 +1802,7 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, // If we never found the module, fail. if (!Module) return ModuleLoadResult(); - + // Verify that the rest of the module path actually corresponds to // a submodule. if (Path.size() > 1) { @@ -1824,20 +1875,10 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, } // Check whether this module is available. - clang::Module::Requirement Requirement; - clang::Module::UnresolvedHeaderDirective MissingHeader; - if (!Module->isAvailable(getLangOpts(), getTarget(), Requirement, - MissingHeader)) { - if (MissingHeader.FileNameLoc.isValid()) { - getDiagnostics().Report(MissingHeader.FileNameLoc, - diag::err_module_header_missing) - << MissingHeader.IsUmbrella << MissingHeader.FileName; - } else { - getDiagnostics().Report(ImportLoc, diag::err_module_unavailable) - << Module->getFullModuleName() - << Requirement.second << Requirement.first - << SourceRange(Path.front().second, Path.back().second); - } + if (Preprocessor::checkModuleIsAvailable(getLangOpts(), getTarget(), + getDiagnostics(), Module)) { + getDiagnostics().Report(ImportLoc, diag::note_module_import_here) + << SourceRange(Path.front().second, Path.back().second); LastModuleImportLoc = ImportLoc; LastModuleImportResult = ModuleLoadResult(); return ModuleLoadResult(); @@ -1858,6 +1899,53 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, return LastModuleImportResult; } +void CompilerInstance::loadModuleFromSource(SourceLocation ImportLoc, + StringRef ModuleName, + StringRef Source) { + // FIXME: Using a randomized filename here means that our intermediate .pcm + // output is nondeterministic (as .pcm files refer to each other by name). + // Can this affect the output in any way? + SmallString<128> ModuleFileName; + if (std::error_code EC = llvm::sys::fs::createTemporaryFile( + ModuleName, "pcm", ModuleFileName)) { + getDiagnostics().Report(ImportLoc, diag::err_fe_unable_to_open_output) + << ModuleFileName << EC.message(); + return; + } + std::string ModuleMapFileName = (ModuleName + ".map").str(); + + FrontendInputFile Input( + ModuleMapFileName, + InputKind(getLanguageFromOptions(*Invocation->getLangOpts()), + InputKind::ModuleMap, /*Preprocessed*/true)); + + std::string NullTerminatedSource(Source.str()); + + auto PreBuildStep = [&](CompilerInstance &Other) { + // Create a virtual file containing our desired source. + // FIXME: We shouldn't need to do this. + const FileEntry *ModuleMapFile = Other.getFileManager().getVirtualFile( + ModuleMapFileName, NullTerminatedSource.size(), 0); + Other.getSourceManager().overrideFileContents( + ModuleMapFile, + llvm::MemoryBuffer::getMemBuffer(NullTerminatedSource.c_str())); + + Other.BuiltModules = std::move(BuiltModules); + Other.DeleteBuiltModules = false; + }; + + auto PostBuildStep = [this](CompilerInstance &Other) { + BuiltModules = std::move(Other.BuiltModules); + }; + + // Build the module, inheriting any modules that we've built locally. + if (compileModuleImpl(*this, ImportLoc, ModuleName, Input, StringRef(), + ModuleFileName, PreBuildStep, PostBuildStep)) { + BuiltModules[ModuleName] = ModuleFileName.str(); + llvm::sys::RemoveFileOnSignal(ModuleFileName); + } +} + void CompilerInstance::makeModuleVisible(Module *Mod, Module::NameVisibilityKind Visibility, SourceLocation ImportLoc) { diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index adb15f1730bf..bb635b7ad714 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -739,7 +739,9 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.InstrumentForProfiling = Args.hasArg(OPT_pg); Opts.CallFEntry = Args.hasArg(OPT_mfentry); Opts.EmitOpenCLArgMetadata = Args.hasArg(OPT_cl_kernel_arg_info); - Opts.CompressDebugSections = Args.hasArg(OPT_compress_debug_sections); + // TODO: map this from -gz in the driver and give it a named value + if (Args.hasArg(OPT_compress_debug_sections)) + Opts.setCompressDebugSections(llvm::DebugCompressionType::GNU); Opts.RelaxELFRelocations = Args.hasArg(OPT_mrelax_relocations); Opts.DebugCompilationDir = Args.getLastArgValue(OPT_fdebug_compilation_dir); for (auto A : Args.filtered(OPT_mlink_bitcode_file, OPT_mlink_cuda_bitcode)) { @@ -2499,6 +2501,7 @@ static void ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts, Opts.ShowMacros = Args.hasArg(OPT_dM) || Args.hasArg(OPT_dD); Opts.ShowIncludeDirectives = Args.hasArg(OPT_dI); Opts.RewriteIncludes = Args.hasArg(OPT_frewrite_includes); + Opts.RewriteImports = Args.hasArg(OPT_frewrite_imports); Opts.UseLineDirectives = Args.hasArg(OPT_fuse_line_directives); } diff --git a/lib/Frontend/FrontendAction.cpp b/lib/Frontend/FrontendAction.cpp index e2fbe965349f..7c0b854648bd 100644 --- a/lib/Frontend/FrontendAction.cpp +++ b/lib/Frontend/FrontendAction.cpp @@ -387,8 +387,7 @@ static std::error_code collectModuleHeaderIncludes( return std::error_code(); } -static bool loadModuleMapForModuleBuild(CompilerInstance &CI, - StringRef Filename, bool IsSystem, +static bool loadModuleMapForModuleBuild(CompilerInstance &CI, bool IsSystem, bool IsPreprocessed, std::string &PresumedModuleMapFile, unsigned &Offset) { @@ -444,21 +443,9 @@ static Module *prepareToBuildModule(CompilerInstance &CI, } // Check whether we can build this module at all. - clang::Module::Requirement Requirement; - clang::Module::UnresolvedHeaderDirective MissingHeader; - if (!M->isAvailable(CI.getLangOpts(), CI.getTarget(), Requirement, - MissingHeader)) { - if (MissingHeader.FileNameLoc.isValid()) { - CI.getDiagnostics().Report(MissingHeader.FileNameLoc, - diag::err_module_header_missing) - << MissingHeader.IsUmbrella << MissingHeader.FileName; - } else { - CI.getDiagnostics().Report(diag::err_module_unavailable) - << M->getFullModuleName() << Requirement.second << Requirement.first; - } - + if (Preprocessor::checkModuleIsAvailable(CI.getLangOpts(), CI.getTarget(), + CI.getDiagnostics(), M)) return nullptr; - } // Inform the preprocessor that includes from within the input buffer should // be resolved relative to the build directory of the module map file. @@ -523,7 +510,8 @@ getInputBufferForModule(CompilerInstance &CI, Module *M) { } bool FrontendAction::BeginSourceFile(CompilerInstance &CI, - const FrontendInputFile &Input) { + const FrontendInputFile &RealInput) { + FrontendInputFile Input(RealInput); assert(!Instance && "Already processing a source file!"); assert(!Input.isEmpty() && "Unexpected empty filename!"); setCurrentInput(Input); @@ -531,15 +519,72 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, StringRef InputFile = Input.getFile(); bool HasBegunSourceFile = false; + bool ReplayASTFile = Input.getKind().getFormat() == InputKind::Precompiled && + usesPreprocessorOnly(); if (!BeginInvocation(CI)) goto failure; + // If we're replaying the build of an AST file, import it and set up + // the initial state from its build. + if (ReplayASTFile) { + IntrusiveRefCntPtr<DiagnosticsEngine> Diags(&CI.getDiagnostics()); + + // The AST unit populates its own diagnostics engine rather than ours. + IntrusiveRefCntPtr<DiagnosticsEngine> ASTDiags( + new DiagnosticsEngine(Diags->getDiagnosticIDs(), + &Diags->getDiagnosticOptions())); + ASTDiags->setClient(Diags->getClient(), /*OwnsClient*/false); + + std::unique_ptr<ASTUnit> AST = ASTUnit::LoadFromASTFile( + InputFile, CI.getPCHContainerReader(), ASTDiags, CI.getFileSystemOpts(), + CI.getCodeGenOpts().DebugTypeExtRefs); + if (!AST) + goto failure; + + // Options relating to how we treat the input (but not what we do with it) + // are inherited from the AST unit. + CI.getHeaderSearchOpts() = AST->getHeaderSearchOpts(); + CI.getPreprocessorOpts() = AST->getPreprocessorOpts(); + CI.getLangOpts() = AST->getLangOpts(); + + // Preload all the module files loaded transitively by the AST unit. + if (auto ASTReader = AST->getASTReader()) { + auto &MM = ASTReader->getModuleManager(); + for (ModuleFile &MF : MM) + if (&MF != &MM.getPrimaryModule()) + CI.getFrontendOpts().ModuleFiles.push_back(MF.FileName); + } + // FIXME: Preload module maps loaded by the AST unit. + + // Set the shared objects, these are reset when we finish processing the + // file, otherwise the CompilerInstance will happily destroy them. + CI.setFileManager(&AST->getFileManager()); + CI.createSourceManager(CI.getFileManager()); + CI.getSourceManager().initializeForReplay(AST->getSourceManager()); + CI.createPreprocessor(getTranslationUnitKind()); + + // Set up the input file for replay purposes. + auto Kind = AST->getInputKind(); + if (Kind.getFormat() == InputKind::ModuleMap) { + Module *ASTModule = + AST->getPreprocessor().getHeaderSearchInfo().lookupModule( + AST->getLangOpts().CurrentModule, /*AllowSearch*/ false); + Input = FrontendInputFile(ASTModule->PresumedModuleMapFile, Kind); + } else { + auto &SM = CI.getSourceManager(); + FileID ID = SM.getMainFileID(); + if (auto *File = SM.getFileEntryForID(ID)) + Input = FrontendInputFile(File->getName(), Kind); + else + Input = FrontendInputFile(SM.getBuffer(ID), Kind); + } + setCurrentInput(Input, std::move(AST)); + } + // AST files follow a very different path, since they share objects via the // AST unit. if (Input.getKind().getFormat() == InputKind::Precompiled) { - // FIXME: We should not be asserting on bad command-line arguments. - assert(!usesPreprocessorOnly() && - "Attempt to pass AST file to preprocessor only action!"); + assert(!usesPreprocessorOnly() && "this case was handled above"); assert(hasASTFileSupport() && "This action does not have AST file support!"); @@ -569,7 +614,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, setCurrentInput(Input, std::move(AST)); // Initialize the action. - if (!BeginSourceFileAction(CI, InputFile)) + if (!BeginSourceFileAction(CI)) goto failure; // Create the AST consumer. @@ -616,7 +661,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, HasBegunSourceFile = true; // Initialize the action. - if (!BeginSourceFileAction(CI, InputFile)) + if (!BeginSourceFileAction(CI)) goto failure; // Initialize the main file entry. @@ -680,7 +725,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, std::string PresumedModuleMapFile; unsigned OffsetToContents; - if (loadModuleMapForModuleBuild(CI, Input.getFile(), Input.isSystem(), + if (loadModuleMapForModuleBuild(CI, Input.isSystem(), Input.isPreprocessed(), PresumedModuleMapFile, OffsetToContents)) goto failure; @@ -709,7 +754,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, } // Initialize the action. - if (!BeginSourceFileAction(CI, InputFile)) + if (!BeginSourceFileAction(CI)) goto failure; // Create the AST context and consumer unless this is a preprocessor only @@ -829,14 +874,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, // If we failed, reset state since the client will not end up calling the // matching EndSourceFile(). - failure: - if (isCurrentFileAST()) { - CI.setASTContext(nullptr); - CI.setPreprocessor(nullptr); - CI.setSourceManager(nullptr); - CI.setFileManager(nullptr); - } - +failure: if (HasBegunSourceFile) CI.getDiagnosticClient().EndSourceFile(); CI.clearOutputFiles(/*EraseFiles=*/true); @@ -914,6 +952,7 @@ void FrontendAction::EndSourceFile() { CI.resetAndLeakPreprocessor(); CI.resetAndLeakSourceManager(); CI.resetAndLeakFileManager(); + BuryPointer(CurrentASTUnit.release()); } else { CI.setPreprocessor(nullptr); CI.setSourceManager(nullptr); @@ -973,11 +1012,10 @@ WrapperFrontendAction::CreateASTConsumer(CompilerInstance &CI, bool WrapperFrontendAction::BeginInvocation(CompilerInstance &CI) { return WrappedAction->BeginInvocation(CI); } -bool WrapperFrontendAction::BeginSourceFileAction(CompilerInstance &CI, - StringRef Filename) { +bool WrapperFrontendAction::BeginSourceFileAction(CompilerInstance &CI) { WrappedAction->setCurrentInput(getCurrentInput()); WrappedAction->setCompilerInstance(&CI); - auto Ret = WrappedAction->BeginSourceFileAction(CI, Filename); + auto Ret = WrappedAction->BeginSourceFileAction(CI); // BeginSourceFileAction may change CurrentInput, e.g. during module builds. setCurrentInput(WrappedAction->getCurrentInput()); return Ret; diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp index 89ac385ca45d..c5567a09636b 100644 --- a/lib/Frontend/FrontendActions.cpp +++ b/lib/Frontend/FrontendActions.cpp @@ -134,8 +134,7 @@ bool GeneratePCHAction::shouldEraseOutputFiles() { return ASTFrontendAction::shouldEraseOutputFiles(); } -bool GeneratePCHAction::BeginSourceFileAction(CompilerInstance &CI, - StringRef Filename) { +bool GeneratePCHAction::BeginSourceFileAction(CompilerInstance &CI) { CI.getLangOpts().CompilingPCH = true; return true; } @@ -164,11 +163,6 @@ GenerateModuleAction::CreateASTConsumer(CompilerInstance &CI, return llvm::make_unique<MultiplexConsumer>(std::move(Consumers)); } -bool GenerateModuleFromModuleMapAction::BeginSourceFileAction( - CompilerInstance &CI, StringRef Filename) { - return GenerateModuleAction::BeginSourceFileAction(CI, Filename); -} - std::unique_ptr<raw_pwrite_stream> GenerateModuleFromModuleMapAction::CreateOutputFile(CompilerInstance &CI, StringRef InFile) { @@ -194,8 +188,8 @@ GenerateModuleFromModuleMapAction::CreateOutputFile(CompilerInstance &CI, /*CreateMissingDirectories=*/true); } -bool GenerateModuleInterfaceAction::BeginSourceFileAction(CompilerInstance &CI, - StringRef Filename) { +bool GenerateModuleInterfaceAction::BeginSourceFileAction( + CompilerInstance &CI) { if (!CI.getLangOpts().ModulesTS) { CI.getDiagnostics().Report(diag::err_module_interface_requires_modules_ts); return false; @@ -203,7 +197,7 @@ bool GenerateModuleInterfaceAction::BeginSourceFileAction(CompilerInstance &CI, CI.getLangOpts().setCompilingModule(LangOptions::CMK_ModuleInterface); - return GenerateModuleAction::BeginSourceFileAction(CI, Filename); + return GenerateModuleAction::BeginSourceFileAction(CI); } std::unique_ptr<raw_pwrite_stream> diff --git a/lib/Frontend/Rewrite/CMakeLists.txt b/lib/Frontend/Rewrite/CMakeLists.txt index 924bf5d5ee28..61a22b5b13b4 100644 --- a/lib/Frontend/Rewrite/CMakeLists.txt +++ b/lib/Frontend/Rewrite/CMakeLists.txt @@ -19,4 +19,5 @@ add_clang_library(clangRewriteFrontend clangFrontend clangLex clangRewrite + clangSerialization ) diff --git a/lib/Frontend/Rewrite/FrontendActions.cpp b/lib/Frontend/Rewrite/FrontendActions.cpp index b2dfd2941130..45feffbcb5b5 100644 --- a/lib/Frontend/Rewrite/FrontendActions.cpp +++ b/lib/Frontend/Rewrite/FrontendActions.cpp @@ -18,6 +18,11 @@ #include "clang/Rewrite/Frontend/ASTConsumers.h" #include "clang/Rewrite/Frontend/FixItRewriter.h" #include "clang/Rewrite/Frontend/Rewriters.h" +#include "clang/Serialization/ASTReader.h" +#include "clang/Serialization/Module.h" +#include "clang/Serialization/ModuleManager.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/Support/CrashRecoveryContext.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" @@ -86,8 +91,7 @@ public: }; } // end anonymous namespace -bool FixItAction::BeginSourceFileAction(CompilerInstance &CI, - StringRef Filename) { +bool FixItAction::BeginSourceFileAction(CompilerInstance &CI) { const FrontendOptions &FEOpts = getCompilerInstance().getFrontendOpts(); if (!FEOpts.FixItSuffix.empty()) { FixItOpts.reset(new FixItActionSuffixInserter(FEOpts.FixItSuffix, @@ -190,27 +194,112 @@ void RewriteTestAction::ExecuteAction() { DoRewriteTest(CI.getPreprocessor(), OS.get()); } -void RewriteIncludesAction::ExecuteAction() { - CompilerInstance &CI = getCompilerInstance(); - std::unique_ptr<raw_ostream> OS = - CI.createDefaultOutputFile(true, getCurrentFile()); - if (!OS) return; +class RewriteIncludesAction::RewriteImportsListener : public ASTReaderListener { + CompilerInstance &CI; + std::weak_ptr<raw_ostream> Out; + + llvm::DenseSet<const FileEntry*> Rewritten; + +public: + RewriteImportsListener(CompilerInstance &CI, std::shared_ptr<raw_ostream> Out) + : CI(CI), Out(Out) {} + + void visitModuleFile(StringRef Filename, + serialization::ModuleKind Kind) override { + auto *File = CI.getFileManager().getFile(Filename); + assert(File && "missing file for loaded module?"); + + // Only rewrite each module file once. + if (!Rewritten.insert(File).second) + return; + + serialization::ModuleFile *MF = + CI.getModuleManager()->getModuleManager().lookup(File); + assert(File && "missing module file for loaded module?"); + + // Not interested in PCH / preambles. + if (!MF->isModule()) + return; + + auto OS = Out.lock(); + assert(OS && "loaded module file after finishing rewrite action?"); + + (*OS) << "#pragma clang module build " << MF->ModuleName << "\n"; + + // Rewrite the contents of the module in a separate compiler instance. + CompilerInstance Instance(CI.getPCHContainerOperations(), + &CI.getPreprocessor().getPCMCache()); + Instance.setInvocation( + std::make_shared<CompilerInvocation>(CI.getInvocation())); + Instance.createDiagnostics( + new ForwardingDiagnosticConsumer(CI.getDiagnosticClient()), + /*ShouldOwnClient=*/true); + Instance.getFrontendOpts().Inputs.clear(); + Instance.getFrontendOpts().Inputs.emplace_back( + Filename, InputKind(InputKind::Unknown, InputKind::Precompiled)); + // Don't recursively rewrite imports. We handle them all at the top level. + Instance.getPreprocessorOutputOpts().RewriteImports = false; + + llvm::CrashRecoveryContext().RunSafelyOnThread([&]() { + RewriteIncludesAction Action; + Action.OutputStream = OS; + Instance.ExecuteAction(Action); + }); + + (*OS) << "#pragma clang module endbuild /*" << MF->ModuleName << "*/\n"; + } +}; + +bool RewriteIncludesAction::BeginSourceFileAction(CompilerInstance &CI) { + if (!OutputStream) { + OutputStream = CI.createDefaultOutputFile(true, getCurrentFile()); + if (!OutputStream) + return false; + } + + auto &OS = *OutputStream; // If we're preprocessing a module map, start by dumping the contents of the // module itself before switching to the input buffer. auto &Input = getCurrentInput(); if (Input.getKind().getFormat() == InputKind::ModuleMap) { if (Input.isFile()) { - (*OS) << "# 1 \""; - OS->write_escaped(Input.getFile()); - (*OS) << "\"\n"; + OS << "# 1 \""; + OS.write_escaped(Input.getFile()); + OS << "\"\n"; } - // FIXME: Include additional information here so that we don't need the - // original source files to exist on disk. - getCurrentModule()->print(*OS); - (*OS) << "#pragma clang module contents\n"; + getCurrentModule()->print(OS); + OS << "#pragma clang module contents\n"; + } + + // If we're rewriting imports, set up a listener to track when we import + // module files. + if (CI.getPreprocessorOutputOpts().RewriteImports) { + CI.createModuleManager(); + CI.getModuleManager()->addListener( + llvm::make_unique<RewriteImportsListener>(CI, OutputStream)); + } + + return true; +} + +void RewriteIncludesAction::ExecuteAction() { + CompilerInstance &CI = getCompilerInstance(); + + // If we're rewriting imports, emit the module build output first rather + // than switching back and forth (potentially in the middle of a line). + if (CI.getPreprocessorOutputOpts().RewriteImports) { + std::string Buffer; + llvm::raw_string_ostream OS(Buffer); + + RewriteIncludesInInput(CI.getPreprocessor(), &OS, + CI.getPreprocessorOutputOpts()); + + (*OutputStream) << OS.str(); + } else { + RewriteIncludesInInput(CI.getPreprocessor(), OutputStream.get(), + CI.getPreprocessorOutputOpts()); } - RewriteIncludesInInput(CI.getPreprocessor(), OS.get(), - CI.getPreprocessorOutputOpts()); + OutputStream.reset(); } diff --git a/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/lib/FrontendTool/ExecuteCompilerInvocation.cpp index 1f7493c9e398..a7c140188b35 100644 --- a/lib/FrontendTool/ExecuteCompilerInvocation.cpp +++ b/lib/FrontendTool/ExecuteCompilerInvocation.cpp @@ -85,7 +85,8 @@ CreateFrontendBaseAction(CompilerInstance &CI) { case PrintDeclContext: return llvm::make_unique<DeclContextPrintAction>(); case PrintPreamble: return llvm::make_unique<PrintPreambleAction>(); case PrintPreprocessedInput: { - if (CI.getPreprocessorOutputOpts().RewriteIncludes) + if (CI.getPreprocessorOutputOpts().RewriteIncludes || + CI.getPreprocessorOutputOpts().RewriteImports) return llvm::make_unique<RewriteIncludesAction>(); return llvm::make_unique<PrintPreprocessedAction>(); } diff --git a/lib/Headers/avxintrin.h b/lib/Headers/avxintrin.h index 15d28259dcc0..78bb70740bbf 100644 --- a/lib/Headers/avxintrin.h +++ b/lib/Headers/avxintrin.h @@ -3603,7 +3603,7 @@ _mm256_stream_si256(__m256i *__a, __m256i __b) /// /// \param __a /// A pointer to a 32-byte aligned memory location that will receive the -/// integer values. +/// double-precision floating-point values. /// \param __b /// A 256-bit vector of [4 x double] containing the values to be moved. static __inline void __DEFAULT_FN_ATTRS diff --git a/lib/Headers/bmiintrin.h b/lib/Headers/bmiintrin.h index e590cf8bc1ae..361e5f720ea1 100644 --- a/lib/Headers/bmiintrin.h +++ b/lib/Headers/bmiintrin.h @@ -148,7 +148,7 @@ __blsi_u32(unsigned int __X) } /// \brief Creates a mask whose bits are set to 1, using bit 0 up to and -/// including the least siginificant bit that is set to 1 in the source +/// including the least significant bit that is set to 1 in the source /// operand and returns the result. /// /// \headerfile <x86intrin.h> @@ -164,7 +164,7 @@ __blsmsk_u32(unsigned int __X) return __X ^ (__X - 1); } -/// \brief Clears the least siginificant bit that is set to 1 in the source +/// \brief Clears the least significant bit that is set to 1 in the source /// operand and returns the result. /// /// \headerfile <x86intrin.h> @@ -309,7 +309,7 @@ __blsi_u64(unsigned long long __X) } /// \brief Creates a mask whose bits are set to 1, using bit 0 up to and -/// including the least siginificant bit that is set to 1 in the source +/// including the least significant bit that is set to 1 in the source /// operand and returns the result. /// /// \headerfile <x86intrin.h> @@ -325,7 +325,7 @@ __blsmsk_u64(unsigned long long __X) return __X ^ (__X - 1); } -/// \brief Clears the least siginificant bit that is set to 1 in the source +/// \brief Clears the least significant bit that is set to 1 in the source /// operand and returns the result. /// /// \headerfile <x86intrin.h> diff --git a/lib/Headers/emmintrin.h b/lib/Headers/emmintrin.h index fa5cefadc52c..709815cbb4c2 100644 --- a/lib/Headers/emmintrin.h +++ b/lib/Headers/emmintrin.h @@ -302,7 +302,7 @@ _mm_min_pd(__m128d __a, __m128d __b) return __builtin_ia32_minpd((__v2df)__a, (__v2df)__b); } -/// \brief Compares lower 64-bits double-precision values of both operands, and +/// \brief Compares lower 64-bit double-precision values of both operands, and /// returns the greater of the pair of values in the lower 64-bits of the /// result. The upper 64 bits of the result are copied from the upper double- /// precision value of the first operand. @@ -1652,7 +1652,7 @@ _mm_loadu_pd(double const *__dp) /// /// This intrinsic corresponds to the <c> VMOVQ / MOVQ </c> instruction. /// -/// \param __dp +/// \param __a /// A pointer to a 64-bit memory location. The address of the memory /// location does not have to be aligned. /// \returns A 128-bit vector of [2 x i64] containing the loaded value. @@ -1674,7 +1674,7 @@ _mm_loadu_si64(void const *__a) /// This intrinsic corresponds to the <c> VMOVSD / MOVSD </c> instruction. /// /// \param __dp -/// An pointer to a memory location containing a double-precision value. +/// A pointer to a memory location containing a double-precision value. /// The address of the memory location does not have to be aligned. /// \returns A 128-bit vector of [2 x double] containing the loaded value. static __inline__ __m128d __DEFAULT_FN_ATTRS @@ -1911,12 +1911,38 @@ _mm_store_sd(double *__dp, __m128d __a) ((struct __mm_store_sd_struct*)__dp)->__u = __a[0]; } +/// \brief Moves packed double-precision values from a 128-bit vector of +/// [2 x double] to a memory location. +/// +/// \headerfile <x86intrin.h> +/// +/// This intrinsic corresponds to the <c>VMOVAPD / MOVAPS</c> instruction. +/// +/// \param __dp +/// A pointer to an aligned memory location that can store two +/// double-precision values. +/// \param __a +/// A packed 128-bit vector of [2 x double] containing the values to be +/// moved. static __inline__ void __DEFAULT_FN_ATTRS _mm_store_pd(double *__dp, __m128d __a) { *(__m128d*)__dp = __a; } +/// \brief Moves the lower 64 bits of a 128-bit vector of [2 x double] twice to +/// the upper and lower 64 bits of a memory location. +/// +/// \headerfile <x86intrin.h> +/// +/// This intrinsic corresponds to the <c>VMOVDDUP + VMOVAPD / MOVLHPS + MOVAPS </c> instruction. +/// +/// \param __dp +/// A pointer to a memory location that can store two double-precision +/// values. +/// \param __a +/// A 128-bit vector of [2 x double] whose lower 64 bits are copied to each +/// of the values in \a dp. static __inline__ void __DEFAULT_FN_ATTRS _mm_store1_pd(double *__dp, __m128d __a) { diff --git a/lib/Headers/xmmintrin.h b/lib/Headers/xmmintrin.h index 5a1c572ce614..bbc2117b4ea1 100644 --- a/lib/Headers/xmmintrin.h +++ b/lib/Headers/xmmintrin.h @@ -2099,7 +2099,7 @@ _mm_stream_pi(__m64 *__p, __m64 __a) /// /// \param __p /// A pointer to a 128-bit aligned memory location that will receive the -/// integer values. +/// single-precision floating-point values. /// \param __a /// A 128-bit vector of [4 x float] containing the values to be moved. static __inline__ void __DEFAULT_FN_ATTRS diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp index 2d3ad690987e..89c2ebd00a68 100644 --- a/lib/Lex/PPDirectives.cpp +++ b/lib/Lex/PPDirectives.cpp @@ -30,6 +30,7 @@ #include "clang/Lex/PPCallbacks.h" #include "clang/Lex/Pragma.h" #include "clang/Lex/Preprocessor.h" +#include "clang/Lex/PreprocessorOptions.h" #include "clang/Lex/PTHLexer.h" #include "clang/Lex/Token.h" #include "llvm/ADT/ArrayRef.h" @@ -1654,6 +1655,26 @@ static bool trySimplifyPath(SmallVectorImpl<StringRef> &Components, return SuggestReplacement; } +bool Preprocessor::checkModuleIsAvailable(const LangOptions &LangOpts, + const TargetInfo &TargetInfo, + DiagnosticsEngine &Diags, Module *M) { + Module::Requirement Requirement; + Module::UnresolvedHeaderDirective MissingHeader; + if (M->isAvailable(LangOpts, TargetInfo, Requirement, MissingHeader)) + return false; + + if (MissingHeader.FileNameLoc.isValid()) { + Diags.Report(MissingHeader.FileNameLoc, diag::err_module_header_missing) + << MissingHeader.IsUmbrella << MissingHeader.FileName; + } else { + // FIXME: Track the location at which the requirement was specified, and + // use it here. + Diags.Report(M->DefinitionLoc, diag::err_module_unavailable) + << M->getFullModuleName() << Requirement.second << Requirement.first; + } + return true; +} + /// HandleIncludeDirective - The "\#include" tokens have just been read, read /// the file to be included from the lexer, then include it! This is a common /// routine with functionality shared between \#include, \#include_next and @@ -1825,33 +1846,24 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, // we've imported or already built. bool ShouldEnter = true; + if (PPOpts->SingleFileParseMode) + ShouldEnter = false; + // Determine whether we should try to import the module for this #include, if // there is one. Don't do so if precompiled module support is disabled or we // are processing this module textually (because we're building the module). - if (File && SuggestedModule && getLangOpts().Modules && + if (ShouldEnter && File && SuggestedModule && getLangOpts().Modules && SuggestedModule.getModule()->getTopLevelModuleName() != getLangOpts().CurrentModule) { // If this include corresponds to a module but that module is // unavailable, diagnose the situation and bail out. // FIXME: Remove this; loadModule does the same check (but produces // slightly worse diagnostics). - if (!SuggestedModule.getModule()->isAvailable()) { - Module::Requirement Requirement; - Module::UnresolvedHeaderDirective MissingHeader; - Module *M = SuggestedModule.getModule(); - // Identify the cause. - (void)M->isAvailable(getLangOpts(), getTargetInfo(), Requirement, - MissingHeader); - if (MissingHeader.FileNameLoc.isValid()) { - Diag(MissingHeader.FileNameLoc, diag::err_module_header_missing) - << MissingHeader.IsUmbrella << MissingHeader.FileName; - } else { - Diag(M->DefinitionLoc, diag::err_module_unavailable) - << M->getFullModuleName() << Requirement.second << Requirement.first; - } + if (checkModuleIsAvailable(getLangOpts(), getTargetInfo(), getDiagnostics(), + SuggestedModule.getModule())) { Diag(FilenameTok.getLocation(), diag::note_implicit_top_level_module_import_here) - << M->getTopLevelModuleName(); + << SuggestedModule.getModule()->getTopLevelModuleName(); return; } diff --git a/lib/Lex/Pragma.cpp b/lib/Lex/Pragma.cpp index e1d981527bec..c16478dd2be4 100644 --- a/lib/Lex/Pragma.cpp +++ b/lib/Lex/Pragma.cpp @@ -754,6 +754,88 @@ void Preprocessor::HandlePragmaIncludeAlias(Token &Tok) { getHeaderSearchInfo().AddIncludeAlias(OriginalSource, ReplaceFileName); } +void Preprocessor::HandlePragmaModuleBuild(Token &Tok) { + SourceLocation Loc = Tok.getLocation(); + + LexUnexpandedToken(Tok); + if (Tok.isAnnotation() || !Tok.getIdentifierInfo()) { + Diag(Tok.getLocation(), diag::err_pp_expected_module_name) << true; + return; + } + IdentifierInfo *ModuleName = Tok.getIdentifierInfo(); + + LexUnexpandedToken(Tok); + if (Tok.isNot(tok::eod)) { + Diag(Tok, diag::ext_pp_extra_tokens_at_eol) << "pragma"; + DiscardUntilEndOfDirective(); + } + + if (CurPTHLexer) { + // FIXME: Support this somehow? + Diag(Loc, diag::err_pp_module_build_pth); + return; + } + + CurLexer->LexingRawMode = true; + + auto TryConsumeIdentifier = [&](StringRef Ident) -> bool { + if (Tok.getKind() != tok::raw_identifier || + Tok.getRawIdentifier() != Ident) + return false; + CurLexer->Lex(Tok); + return true; + }; + + // Scan forward looking for the end of the module. + const char *Start = CurLexer->getBufferLocation(); + const char *End = nullptr; + unsigned NestingLevel = 1; + while (true) { + End = CurLexer->getBufferLocation(); + CurLexer->Lex(Tok); + + if (Tok.is(tok::eof)) { + Diag(Loc, diag::err_pp_module_build_missing_end); + break; + } + + if (Tok.isNot(tok::hash) || !Tok.isAtStartOfLine()) { + // Token was part of module; keep going. + continue; + } + + // We hit something directive-shaped; check to see if this is the end + // of the module build. + CurLexer->ParsingPreprocessorDirective = true; + CurLexer->Lex(Tok); + if (TryConsumeIdentifier("pragma") && TryConsumeIdentifier("clang") && + TryConsumeIdentifier("module")) { + if (TryConsumeIdentifier("build")) + // #pragma clang module build -> entering a nested module build. + ++NestingLevel; + else if (TryConsumeIdentifier("endbuild")) { + // #pragma clang module endbuild -> leaving a module build. + if (--NestingLevel == 0) + break; + } + // We should either be looking at the EOD or more of the current directive + // preceding the EOD. Either way we can ignore this token and keep going. + assert(Tok.getKind() != tok::eof && "missing EOD before EOF"); + } + } + + CurLexer->LexingRawMode = false; + + // Load the extracted text as a preprocessed module. + assert(CurLexer->getBuffer().begin() <= Start && + Start <= CurLexer->getBuffer().end() && + CurLexer->getBuffer().begin() <= End && + End <= CurLexer->getBuffer().end() && + "module source range not contained within same file buffer"); + TheModuleLoader.loadModuleFromSource(Loc, ModuleName->getName(), + StringRef(Start, End - Start)); +} + /// AddPragmaHandler - Add the specified pragma handler to the preprocessor. /// If 'Namespace' is non-null, then it is a token required to exist on the /// pragma line before the pragma string starts, e.g. "STDC" or "GCC". @@ -1408,18 +1490,8 @@ struct PragmaModuleBeginHandler : public PragmaHandler { } // If the module isn't available, it doesn't make sense to enter it. - if (!M->isAvailable()) { - Module::Requirement Requirement; - Module::UnresolvedHeaderDirective MissingHeader; - (void)M->isAvailable(PP.getLangOpts(), PP.getTargetInfo(), - Requirement, MissingHeader); - if (MissingHeader.FileNameLoc.isValid()) { - PP.Diag(MissingHeader.FileNameLoc, diag::err_module_header_missing) - << MissingHeader.IsUmbrella << MissingHeader.FileName; - } else { - PP.Diag(M->DefinitionLoc, diag::err_module_unavailable) - << M->getFullModuleName() << Requirement.second << Requirement.first; - } + if (Preprocessor::checkModuleIsAvailable( + PP.getLangOpts(), PP.getTargetInfo(), PP.getDiagnostics(), M)) { PP.Diag(BeginLoc, diag::note_pp_module_begin_here) << M->getTopLevelModuleName(); return; @@ -1452,6 +1524,39 @@ struct PragmaModuleEndHandler : public PragmaHandler { } }; +/// Handle the clang \#pragma module build extension. +struct PragmaModuleBuildHandler : public PragmaHandler { + PragmaModuleBuildHandler() : PragmaHandler("build") {} + + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &Tok) override { + PP.HandlePragmaModuleBuild(Tok); + } +}; + +/// Handle the clang \#pragma module load extension. +struct PragmaModuleLoadHandler : public PragmaHandler { + PragmaModuleLoadHandler() : PragmaHandler("load") {} + + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &Tok) override { + SourceLocation Loc = Tok.getLocation(); + + // Read the module name. + llvm::SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 8> + ModuleName; + if (LexModuleName(PP, Tok, ModuleName)) + return; + + if (Tok.isNot(tok::eod)) + PP.Diag(Tok, diag::ext_pp_extra_tokens_at_eol) << "pragma"; + + // Load the module, don't make it visible. + PP.getModuleLoader().loadModule(Loc, ModuleName, Module::Hidden, + /*IsIncludeDirective=*/false); + } +}; + /// PragmaPushMacroHandler - "\#pragma push_macro" saves the value of the /// macro on the top of the stack. struct PragmaPushMacroHandler : public PragmaHandler { @@ -1681,6 +1786,8 @@ void Preprocessor::RegisterBuiltinPragmas() { ModuleHandler->AddPragma(new PragmaModuleImportHandler()); ModuleHandler->AddPragma(new PragmaModuleBeginHandler()); ModuleHandler->AddPragma(new PragmaModuleEndHandler()); + ModuleHandler->AddPragma(new PragmaModuleBuildHandler()); + ModuleHandler->AddPragma(new PragmaModuleLoadHandler()); AddPragmaHandler("STDC", new PragmaSTDC_FENV_ACCESSHandler()); AddPragmaHandler("STDC", new PragmaSTDC_CX_LIMITED_RANGEHandler()); diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp index 3596337c245e..f9a399cd7fd7 100644 --- a/lib/Lex/Preprocessor.cpp +++ b/lib/Lex/Preprocessor.cpp @@ -580,7 +580,11 @@ IdentifierInfo *Preprocessor::LookUpIdentifierInfo(Token &Identifier) const { // Update the token info (identifier info and appropriate token kind). Identifier.setIdentifierInfo(II); - Identifier.setKind(II->getTokenID()); + if (getLangOpts().MSVCCompat && II->isCPlusPlusOperatorKeyword() && + getSourceManager().isInSystemHeader(Identifier.getLocation())) + Identifier.setKind(clang::tok::identifier); + else + Identifier.setKind(II->getTokenID()); return II; } @@ -709,7 +713,9 @@ bool Preprocessor::HandleIdentifier(Token &Identifier) { // C++ 2.11p2: If this is an alternative representation of a C++ operator, // then we act as if it is the actual operator and not the textual // representation of it. - if (II.isCPlusPlusOperatorKeyword()) + if (II.isCPlusPlusOperatorKeyword() && + !(getLangOpts().MSVCCompat && + getSourceManager().isInSystemHeader(Identifier.getLocation()))) Identifier.setIdentifierInfo(nullptr); // If this is an extension token, diagnose its use. diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 4c117f531ef1..1a4607a84cff 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -840,7 +840,9 @@ Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd){ return nullptr; } - ExprResult AssertExpr(ParseConstantExpression()); + EnterExpressionEvaluationContext ConstantEvaluated( + Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated); + ExprResult AssertExpr(ParseConstantExpressionInExprEvalContext()); if (AssertExpr.isInvalid()) { SkipMalformedDecl(); return nullptr; diff --git a/lib/Parse/ParsePragma.cpp b/lib/Parse/ParsePragma.cpp index 18aebe658073..262743756a6b 100644 --- a/lib/Parse/ParsePragma.cpp +++ b/lib/Parse/ParsePragma.cpp @@ -49,6 +49,15 @@ struct PragmaPackHandler : public PragmaHandler { Token &FirstToken) override; }; +struct PragmaClangSectionHandler : public PragmaHandler { + explicit PragmaClangSectionHandler(Sema &S) + : PragmaHandler("section"), Actions(S) {} + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &FirstToken) override; +private: + Sema &Actions; +}; + struct PragmaMSStructHandler : public PragmaHandler { explicit PragmaMSStructHandler() : PragmaHandler("ms_struct") {} void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, @@ -224,6 +233,9 @@ void Parser::initializePragmaHandlers() { FPContractHandler.reset(new PragmaFPContractHandler()); PP.AddPragmaHandler("STDC", FPContractHandler.get()); + PCSectionHandler.reset(new PragmaClangSectionHandler(Actions)); + PP.AddPragmaHandler("clang", PCSectionHandler.get()); + if (getLangOpts().OpenCL) { OpenCLExtensionHandler.reset(new PragmaOpenCLExtensionHandler()); PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get()); @@ -323,6 +335,9 @@ void Parser::resetPragmaHandlers() { MSCommentHandler.reset(); } + PP.RemovePragmaHandler("clang", PCSectionHandler.get()); + PCSectionHandler.reset(); + if (getLangOpts().MicrosoftExt) { PP.RemovePragmaHandler(MSDetectMismatchHandler.get()); MSDetectMismatchHandler.reset(); @@ -1614,6 +1629,51 @@ void PragmaMSStructHandler::HandlePragma(Preprocessor &PP, PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true); } +// #pragma clang section bss="abc" data="" rodata="def" text="" +void PragmaClangSectionHandler::HandlePragma(Preprocessor &PP, + PragmaIntroducerKind Introducer, Token &FirstToken) { + + Token Tok; + auto SecKind = Sema::PragmaClangSectionKind::PCSK_Invalid; + + PP.Lex(Tok); // eat 'section' + while (Tok.isNot(tok::eod)) { + if (Tok.isNot(tok::identifier)) { + PP.Diag(Tok.getLocation(), diag::err_pragma_expected_clang_section_name) << "clang section"; + return; + } + + const IdentifierInfo *SecType = Tok.getIdentifierInfo(); + if (SecType->isStr("bss")) + SecKind = Sema::PragmaClangSectionKind::PCSK_BSS; + else if (SecType->isStr("data")) + SecKind = Sema::PragmaClangSectionKind::PCSK_Data; + else if (SecType->isStr("rodata")) + SecKind = Sema::PragmaClangSectionKind::PCSK_Rodata; + else if (SecType->isStr("text")) + SecKind = Sema::PragmaClangSectionKind::PCSK_Text; + else { + PP.Diag(Tok.getLocation(), diag::err_pragma_expected_clang_section_name) << "clang section"; + return; + } + + PP.Lex(Tok); // eat ['bss'|'data'|'rodata'|'text'] + if (Tok.isNot(tok::equal)) { + PP.Diag(Tok.getLocation(), diag::err_pragma_clang_section_expected_equal) << SecKind; + return; + } + + std::string SecName; + if (!PP.LexStringLiteral(Tok, SecName, "pragma clang section", false)) + return; + + Actions.ActOnPragmaClangSection(Tok.getLocation(), + (SecName.size()? Sema::PragmaClangSectionAction::PCSA_Set : + Sema::PragmaClangSectionAction::PCSA_Clear), + SecKind, SecName); + } +} + // #pragma 'align' '=' {'native','natural','mac68k','power','reset'} // #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'} static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok, diff --git a/lib/Sema/SemaAttr.cpp b/lib/Sema/SemaAttr.cpp index 76ca65373dda..8c13ead64457 100644 --- a/lib/Sema/SemaAttr.cpp +++ b/lib/Sema/SemaAttr.cpp @@ -126,6 +126,36 @@ void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind, PackStack.Act(PragmaLoc, Action, StringRef(), Alignment); } +void Sema::ActOnPragmaClangSection(SourceLocation PragmaLoc, PragmaClangSectionAction Action, + PragmaClangSectionKind SecKind, StringRef SecName) { + PragmaClangSection *CSec; + switch (SecKind) { + case PragmaClangSectionKind::PCSK_BSS: + CSec = &PragmaClangBSSSection; + break; + case PragmaClangSectionKind::PCSK_Data: + CSec = &PragmaClangDataSection; + break; + case PragmaClangSectionKind::PCSK_Rodata: + CSec = &PragmaClangRodataSection; + break; + case PragmaClangSectionKind::PCSK_Text: + CSec = &PragmaClangTextSection; + break; + default: + llvm_unreachable("invalid clang section kind"); + } + + if (Action == PragmaClangSectionAction::PCSA_Clear) { + CSec->Valid = false; + return; + } + + CSec->Valid = true; + CSec->SectionName = SecName; + CSec->PragmaLocation = PragmaLoc; +} + void Sema::ActOnPragmaPack(SourceLocation PragmaLoc, PragmaMsStackAction Action, StringRef SlotLabel, Expr *alignment) { Expr *Alignment = static_cast<Expr *>(alignment); diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index 224d9e9a0ee2..b9349dc06bff 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -1860,6 +1860,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts()); } + LLVM_FALLTHROUGH; // Fall through (for statement expressions). case Sema::PCC_ForInit: diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index ef6dfaa2f28c..cba220daf774 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -8651,6 +8651,14 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, NewFD->setInvalidDecl(); } + // Apply an implicit SectionAttr if '#pragma clang section text' is active + if (PragmaClangTextSection.Valid && D.isFunctionDefinition() && + !NewFD->hasAttr<SectionAttr>()) { + NewFD->addAttr(PragmaClangTextSectionAttr::CreateImplicit(Context, + PragmaClangTextSection.SectionName, + PragmaClangTextSection.PragmaLocation)); + } + // Apply an implicit SectionAttr if #pragma code_seg is active. if (CodeSegStack.CurrentValue && D.isFunctionDefinition() && !NewFD->hasAttr<SectionAttr>()) { @@ -11175,6 +11183,23 @@ void Sema::FinalizeDeclaration(Decl *ThisDecl) { if (!VD) return; + // Apply an implicit SectionAttr if '#pragma clang section bss|data|rodata' is active + if (VD->hasGlobalStorage() && VD->isThisDeclarationADefinition() && + !inTemplateInstantiation() && !VD->hasAttr<SectionAttr>()) { + if (PragmaClangBSSSection.Valid) + VD->addAttr(PragmaClangBSSSectionAttr::CreateImplicit(Context, + PragmaClangBSSSection.SectionName, + PragmaClangBSSSection.PragmaLocation)); + if (PragmaClangDataSection.Valid) + VD->addAttr(PragmaClangDataSectionAttr::CreateImplicit(Context, + PragmaClangDataSection.SectionName, + PragmaClangDataSection.PragmaLocation)); + if (PragmaClangRodataSection.Valid) + VD->addAttr(PragmaClangRodataSectionAttr::CreateImplicit(Context, + PragmaClangRodataSection.SectionName, + PragmaClangRodataSection.PragmaLocation)); + } + if (auto *DD = dyn_cast<DecompositionDecl>(ThisDecl)) { for (auto *BD : DD->bindings()) { FinalizeDeclaration(BD); diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index acacdc263c08..844299bb87cf 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -547,17 +547,23 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, Diag(OldParam->getLocation(), diag::note_previous_definition) << OldParam->getDefaultArgRange(); } else if (OldParamHasDfl) { - // Merge the old default argument into the new parameter. - // It's important to use getInit() here; getDefaultArg() - // strips off any top-level ExprWithCleanups. - NewParam->setHasInheritedDefaultArg(); - if (OldParam->hasUnparsedDefaultArg()) - NewParam->setUnparsedDefaultArg(); - else if (OldParam->hasUninstantiatedDefaultArg()) - NewParam->setUninstantiatedDefaultArg( - OldParam->getUninstantiatedDefaultArg()); - else - NewParam->setDefaultArg(OldParam->getInit()); + // Merge the old default argument into the new parameter unless the new + // function is a friend declaration in a template class. In the latter + // case the default arguments will be inherited when the friend + // declaration will be instantiated. + if (New->getFriendObjectKind() == Decl::FOK_None || + !New->getLexicalDeclContext()->isDependentContext()) { + // It's important to use getInit() here; getDefaultArg() + // strips off any top-level ExprWithCleanups. + NewParam->setHasInheritedDefaultArg(); + if (OldParam->hasUnparsedDefaultArg()) + NewParam->setUnparsedDefaultArg(); + else if (OldParam->hasUninstantiatedDefaultArg()) + NewParam->setUninstantiatedDefaultArg( + OldParam->getUninstantiatedDefaultArg()); + else + NewParam->setDefaultArg(OldParam->getInit()); + } } else if (NewParamHasDfl) { if (New->getDescribedFunctionTemplate()) { // Paragraph 4, quoted above, only applies to non-template functions. @@ -638,7 +644,12 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, Diag(Old->getLocation(), diag::note_previous_declaration); Invalid = true; } else if (!Old->getMostRecentDecl()->isInlined() && New->isInlined() && - Old->isDefined(Def)) { + Old->isDefined(Def) && + // If a friend function is inlined but does not have 'inline' + // specifier, it is a definition. Do not report attribute conflict + // in this case, redefinition will be diagnosed later. + (New->isInlineSpecified() || + New->getFriendObjectKind() == Decl::FOK_None)) { // C++11 [dcl.fcn.spec]p4: // If the definition of a function appears in a translation unit before its // first declaration as inline, the program is ill-formed. @@ -13232,6 +13243,14 @@ Decl *Sema::BuildStaticAssertDeclaration(SourceLocation StaticAssertLoc, } } + ExprResult FullAssertExpr = ActOnFinishFullExpr(AssertExpr, StaticAssertLoc, + /*DiscardedValue*/false, + /*IsConstexpr*/true); + if (FullAssertExpr.isInvalid()) + Failed = true; + else + AssertExpr = FullAssertExpr.get(); + Decl *Decl = StaticAssertDecl::Create(Context, CurContext, StaticAssertLoc, AssertExpr, AssertMessage, RParenLoc, Failed); diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 4e7fb19b282b..0f8f5c253ac6 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -11828,6 +11828,28 @@ ExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc, RHSExpr->getType()->isOverloadableType()) return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr); } + + // If we're instantiating "a.x < b" or "A::x < b" and 'x' names a function + // template, diagnose the missing 'template' keyword instead of diagnosing + // an invalid use of a bound member function. + // + // Note that "A::x < b" might be valid if 'b' has an overloadable type due + // to C++1z [over.over]/1.4, but we already checked for that case above. + if (Opc == BO_LT && inTemplateInstantiation() && + (pty->getKind() == BuiltinType::BoundMember || + pty->getKind() == BuiltinType::Overload)) { + auto *OE = dyn_cast<OverloadExpr>(LHSExpr); + if (OE && !OE->hasTemplateKeyword() && !OE->hasExplicitTemplateArgs() && + std::any_of(OE->decls_begin(), OE->decls_end(), [](NamedDecl *ND) { + return isa<FunctionTemplateDecl>(ND); + })) { + Diag(OE->getQualifier() ? OE->getQualifierLoc().getBeginLoc() + : OE->getNameLoc(), + diag::err_template_kw_missing) + << OE->getName().getAsString() << ""; + return ExprError(); + } + } ExprResult LHS = CheckPlaceholderExpr(LHSExpr); if (LHS.isInvalid()) return ExprError(); @@ -11953,16 +11975,13 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, << resultType << Input.get()->getSourceRange(); else if (resultType->hasIntegerRepresentation()) break; - else if (resultType->isExtVectorType()) { - if (Context.getLangOpts().OpenCL) { - // OpenCL v1.1 s6.3.f: The bitwise operator not (~) does not operate - // on vector float types. - QualType T = resultType->getAs<ExtVectorType>()->getElementType(); - if (!T->isIntegerType()) - return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) - << resultType << Input.get()->getSourceRange()); - } - break; + else if (resultType->isExtVectorType() && Context.getLangOpts().OpenCL) { + // OpenCL v1.1 s6.3.f: The bitwise operator not (~) does not operate + // on vector float types. + QualType T = resultType->getAs<ExtVectorType>()->getElementType(); + if (!T->isIntegerType()) + return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) + << resultType << Input.get()->getSourceRange()); } else { return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) << resultType << Input.get()->getSourceRange()); diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index a05f7a7e406b..00a4b39f1423 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -2658,6 +2658,8 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name, Context, GlobalCtx, SourceLocation(), SourceLocation(), Name, FnType, /*TInfo=*/nullptr, SC_None, false, true); Alloc->setImplicit(); + // Global allocation functions should always be visible. + Alloc->setHidden(false); // Implicit sized deallocation functions always have default visibility. Alloc->addAttr( @@ -5104,7 +5106,9 @@ QualType Sema::CheckPointerToMemberOperands(ExprResult &LHS, ExprResult &RHS, return QualType(); // Cast LHS to type of use. - QualType UseType = isIndirect ? Context.getPointerType(Class) : Class; + QualType UseType = Context.getQualifiedType(Class, LHSType.getQualifiers()); + if (isIndirect) + UseType = Context.getPointerType(UseType); ExprValueKind VK = isIndirect ? VK_RValue : LHS.get()->getValueKind(); LHS = ImpCastExprToType(LHS.get(), UseType, CK_DerivedToBase, VK, &BasePath); @@ -5281,16 +5285,16 @@ static bool FindConditionalOverload(Sema &Self, ExprResult &LHS, ExprResult &RHS switch (CandidateSet.BestViableFunction(Self, QuestionLoc, Best)) { case OR_Success: { // We found a match. Perform the conversions on the arguments and move on. - ExprResult LHSRes = - Self.PerformImplicitConversion(LHS.get(), Best->BuiltinTypes.ParamTypes[0], - Best->Conversions[0], Sema::AA_Converting); + ExprResult LHSRes = Self.PerformImplicitConversion( + LHS.get(), Best->BuiltinParamTypes[0], Best->Conversions[0], + Sema::AA_Converting); if (LHSRes.isInvalid()) break; LHS = LHSRes; - ExprResult RHSRes = - Self.PerformImplicitConversion(RHS.get(), Best->BuiltinTypes.ParamTypes[1], - Best->Conversions[1], Sema::AA_Converting); + ExprResult RHSRes = Self.PerformImplicitConversion( + RHS.get(), Best->BuiltinParamTypes[1], Best->Conversions[1], + Sema::AA_Converting); if (RHSRes.isInvalid()) break; RHS = RHSRes; diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 1d32e5796812..1fb25f4e0e7c 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -3747,20 +3747,19 @@ static void LookupPotentialTypoResult(Sema &SemaRef, bool FindHidden); /// \brief Check whether the declarations found for a typo correction are -/// visible, and if none of them are, convert the correction to an 'import -/// a module' correction. +/// visible. Set the correction's RequiresImport flag to true if none of the +/// declarations are visible, false otherwise. static void checkCorrectionVisibility(Sema &SemaRef, TypoCorrection &TC) { - if (TC.begin() == TC.end()) - return; - TypoCorrection::decl_iterator DI = TC.begin(), DE = TC.end(); for (/**/; DI != DE; ++DI) if (!LookupResult::isVisible(SemaRef, *DI)) break; - // Nothing to do if all decls are visible. - if (DI == DE) + // No filtering needed if all decls are visible. + if (DI == DE) { + TC.setRequiresImport(false); return; + } llvm::SmallVector<NamedDecl*, 4> NewDecls(TC.begin(), DI); bool AnyVisibleDecls = !NewDecls.empty(); diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 7bdd8872456a..5cc13f391d11 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -7136,8 +7136,7 @@ void Sema::AddMemberOperatorCandidates(OverloadedOperatorKind Op, /// operator. NumContextualBoolArguments is the number of arguments /// (at the beginning of the argument list) that will be contextually /// converted to bool. -void Sema::AddBuiltinCandidate(QualType ResultTy, QualType *ParamTys, - ArrayRef<Expr *> Args, +void Sema::AddBuiltinCandidate(QualType *ParamTys, ArrayRef<Expr *> Args, OverloadCandidateSet& CandidateSet, bool IsAssignmentOperator, unsigned NumContextualBoolArguments) { @@ -7151,9 +7150,7 @@ void Sema::AddBuiltinCandidate(QualType ResultTy, QualType *ParamTys, Candidate.Function = nullptr; Candidate.IsSurrogate = false; Candidate.IgnoreObjectArgument = false; - Candidate.BuiltinTypes.ResultTy = ResultTy; - for (unsigned ArgIdx = 0, N = Args.size(); ArgIdx != N; ++ArgIdx) - Candidate.BuiltinTypes.ParamTypes[ArgIdx] = ParamTys[ArgIdx]; + std::copy(ParamTys, ParamTys + Args.size(), Candidate.BuiltinParamTypes); // Determine the implicit conversion sequences for each of the // arguments. @@ -7492,7 +7489,7 @@ static void AddBuiltinAssignmentOperatorCandidates(Sema &S, // T& operator=(T&, T) ParamTypes[0] = S.Context.getLValueReferenceType(T); ParamTypes[1] = T; - S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet, + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet, /*IsAssignmentOperator=*/true); if (!S.Context.getCanonicalType(T).isVolatileQualified()) { @@ -7500,7 +7497,7 @@ static void AddBuiltinAssignmentOperatorCandidates(Sema &S, ParamTypes[0] = S.Context.getLValueReferenceType(S.Context.getVolatileType(T)); ParamTypes[1] = T; - S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet, + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet, /*IsAssignmentOperator=*/true); } } @@ -7620,64 +7617,6 @@ class BuiltinOperatorOverloadBuilder { return S.Context.*ArithmeticTypes[index]; } - /// \brief Gets the canonical type resulting from the usual arithemetic - /// converions for the given arithmetic types. - CanQualType getUsualArithmeticConversions(unsigned L, unsigned R) { - // Accelerator table for performing the usual arithmetic conversions. - // The rules are basically: - // - if either is floating-point, use the wider floating-point - // - if same signedness, use the higher rank - // - if same size, use unsigned of the higher rank - // - use the larger type - // These rules, together with the axiom that higher ranks are - // never smaller, are sufficient to precompute all of these results - // *except* when dealing with signed types of higher rank. - // (we could precompute SLL x UI for all known platforms, but it's - // better not to make any assumptions). - // We assume that int128 has a higher rank than long long on all platforms. - enum PromotedType : int8_t { - Dep=-1, - Flt, Dbl, LDbl, SI, SL, SLL, S128, UI, UL, ULL, U128 - }; - static const PromotedType ConversionsTable[LastPromotedArithmeticType] - [LastPromotedArithmeticType] = { -/* Flt*/ { Flt, Dbl, LDbl, Flt, Flt, Flt, Flt, Flt, Flt, Flt, Flt }, -/* Dbl*/ { Dbl, Dbl, LDbl, Dbl, Dbl, Dbl, Dbl, Dbl, Dbl, Dbl, Dbl }, -/*LDbl*/ { LDbl, LDbl, LDbl, LDbl, LDbl, LDbl, LDbl, LDbl, LDbl, LDbl, LDbl }, -/* SI*/ { Flt, Dbl, LDbl, SI, SL, SLL, S128, UI, UL, ULL, U128 }, -/* SL*/ { Flt, Dbl, LDbl, SL, SL, SLL, S128, Dep, UL, ULL, U128 }, -/* SLL*/ { Flt, Dbl, LDbl, SLL, SLL, SLL, S128, Dep, Dep, ULL, U128 }, -/*S128*/ { Flt, Dbl, LDbl, S128, S128, S128, S128, S128, S128, S128, U128 }, -/* UI*/ { Flt, Dbl, LDbl, UI, Dep, Dep, S128, UI, UL, ULL, U128 }, -/* UL*/ { Flt, Dbl, LDbl, UL, UL, Dep, S128, UL, UL, ULL, U128 }, -/* ULL*/ { Flt, Dbl, LDbl, ULL, ULL, ULL, S128, ULL, ULL, ULL, U128 }, -/*U128*/ { Flt, Dbl, LDbl, U128, U128, U128, U128, U128, U128, U128, U128 }, - }; - - assert(L < LastPromotedArithmeticType); - assert(R < LastPromotedArithmeticType); - int Idx = ConversionsTable[L][R]; - - // Fast path: the table gives us a concrete answer. - if (Idx != Dep) return getArithmeticType(Idx); - - // Slow path: we need to compare widths. - // An invariant is that the signed type has higher rank. - CanQualType LT = getArithmeticType(L), - RT = getArithmeticType(R); - unsigned LW = S.Context.getIntWidth(LT), - RW = S.Context.getIntWidth(RT); - - // If they're different widths, use the signed type. - if (LW > RW) return LT; - else if (LW < RW) return RT; - - // Otherwise, use the unsigned type of the signed type's rank. - if (L == SL || R == SL) return S.Context.UnsignedLongTy; - assert(L == SLL || R == SLL); - return S.Context.UnsignedLongLongTy; - } - /// \brief Helper method to factor out the common pattern of adding overloads /// for '++' and '--' builtin operators. void addPlusPlusMinusMinusStyleOverloads(QualType CandidateTy, @@ -7689,10 +7628,7 @@ class BuiltinOperatorOverloadBuilder { }; // Non-volatile version. - if (Args.size() == 1) - S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet); - else - S.AddBuiltinCandidate(CandidateTy, ParamTypes, Args, CandidateSet); + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet); // Use a heuristic to reduce number of builtin candidates in the set: // add volatile version only if there are conversions to a volatile type. @@ -7700,10 +7636,7 @@ class BuiltinOperatorOverloadBuilder { ParamTypes[0] = S.Context.getLValueReferenceType( S.Context.getVolatileType(CandidateTy)); - if (Args.size() == 1) - S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet); - else - S.AddBuiltinCandidate(CandidateTy, ParamTypes, Args, CandidateSet); + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet); } // Add restrict version only if there are conversions to a restrict type @@ -7713,10 +7646,7 @@ class BuiltinOperatorOverloadBuilder { ParamTypes[0] = S.Context.getLValueReferenceType( S.Context.getCVRQualifiedType(CandidateTy, Qualifiers::Restrict)); - if (Args.size() == 1) - S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet); - else - S.AddBuiltinCandidate(CandidateTy, ParamTypes, Args, CandidateSet); + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet); if (HasVolatile) { ParamTypes[0] @@ -7724,10 +7654,7 @@ class BuiltinOperatorOverloadBuilder { S.Context.getCVRQualifiedType(CandidateTy, (Qualifiers::Volatile | Qualifiers::Restrict))); - if (Args.size() == 1) - S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet); - else - S.AddBuiltinCandidate(CandidateTy, ParamTypes, Args, CandidateSet); + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet); } } @@ -7841,8 +7768,7 @@ public: if (Proto->getTypeQuals() || Proto->getRefQualifier()) continue; - S.AddBuiltinCandidate(S.Context.getLValueReferenceType(PointeeTy), - &ParamTy, Args, CandidateSet); + S.AddBuiltinCandidate(&ParamTy, Args, CandidateSet); } } @@ -7859,7 +7785,7 @@ public: for (unsigned Arith = FirstPromotedArithmeticType; Arith < LastPromotedArithmeticType; ++Arith) { QualType ArithTy = getArithmeticType(Arith); - S.AddBuiltinCandidate(ArithTy, &ArithTy, Args, CandidateSet); + S.AddBuiltinCandidate(&ArithTy, Args, CandidateSet); } // Extension: We also add these operators for vector types. @@ -7868,7 +7794,7 @@ public: VecEnd = CandidateTypes[0].vector_end(); Vec != VecEnd; ++Vec) { QualType VecTy = *Vec; - S.AddBuiltinCandidate(VecTy, &VecTy, Args, CandidateSet); + S.AddBuiltinCandidate(&VecTy, Args, CandidateSet); } } @@ -7883,7 +7809,7 @@ public: PtrEnd = CandidateTypes[0].pointer_end(); Ptr != PtrEnd; ++Ptr) { QualType ParamTy = *Ptr; - S.AddBuiltinCandidate(ParamTy, &ParamTy, Args, CandidateSet); + S.AddBuiltinCandidate(&ParamTy, Args, CandidateSet); } } @@ -7899,7 +7825,7 @@ public: for (unsigned Int = FirstPromotedIntegralType; Int < LastPromotedIntegralType; ++Int) { QualType IntTy = getArithmeticType(Int); - S.AddBuiltinCandidate(IntTy, &IntTy, Args, CandidateSet); + S.AddBuiltinCandidate(&IntTy, Args, CandidateSet); } // Extension: We also add this operator for vector types. @@ -7908,7 +7834,7 @@ public: VecEnd = CandidateTypes[0].vector_end(); Vec != VecEnd; ++Vec) { QualType VecTy = *Vec; - S.AddBuiltinCandidate(VecTy, &VecTy, Args, CandidateSet); + S.AddBuiltinCandidate(&VecTy, Args, CandidateSet); } } @@ -7933,15 +7859,14 @@ public: continue; QualType ParamTypes[2] = { *MemPtr, *MemPtr }; - S.AddBuiltinCandidate(S.Context.BoolTy, ParamTypes, Args, CandidateSet); + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet); } if (CandidateTypes[ArgIdx].hasNullPtrType()) { CanQualType NullPtrTy = S.Context.getCanonicalType(S.Context.NullPtrTy); if (AddedTypes.insert(NullPtrTy).second) { QualType ParamTypes[2] = { NullPtrTy, NullPtrTy }; - S.AddBuiltinCandidate(S.Context.BoolTy, ParamTypes, Args, - CandidateSet); + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet); } } } @@ -8017,7 +7942,7 @@ public: continue; QualType ParamTypes[2] = { *Ptr, *Ptr }; - S.AddBuiltinCandidate(S.Context.BoolTy, ParamTypes, Args, CandidateSet); + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet); } for (BuiltinCandidateTypeSet::iterator Enum = CandidateTypes[ArgIdx].enumeration_begin(), @@ -8033,7 +7958,7 @@ public: continue; QualType ParamTypes[2] = { *Enum, *Enum }; - S.AddBuiltinCandidate(S.Context.BoolTy, ParamTypes, Args, CandidateSet); + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet); } } } @@ -8076,7 +8001,7 @@ public: if (Arg == 0 || Op == OO_Plus) { // operator+(T*, ptrdiff_t) or operator-(T*, ptrdiff_t) // T* operator+(ptrdiff_t, T*); - S.AddBuiltinCandidate(*Ptr, AsymmetricParamTypes, Args, CandidateSet); + S.AddBuiltinCandidate(AsymmetricParamTypes, Args, CandidateSet); } if (Op == OO_Minus) { // ptrdiff_t operator-(T, T); @@ -8084,8 +8009,7 @@ public: continue; QualType ParamTypes[2] = { *Ptr, *Ptr }; - S.AddBuiltinCandidate(S.Context.getPointerDiffType(), ParamTypes, - Args, CandidateSet); + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet); } } } @@ -8120,7 +8044,7 @@ public: // where LR is the result of the usual arithmetic conversions // between types L and R. // Our candidates ignore the first parameter. - void addGenericBinaryArithmeticOverloads(bool isComparison) { + void addGenericBinaryArithmeticOverloads() { if (!HasArithmeticOrEnumeralCandidateType) return; @@ -8130,10 +8054,7 @@ public: Right < LastPromotedArithmeticType; ++Right) { QualType LandR[2] = { getArithmeticType(Left), getArithmeticType(Right) }; - QualType Result = - isComparison ? S.Context.BoolTy - : getUsualArithmeticConversions(Left, Right); - S.AddBuiltinCandidate(Result, LandR, Args, CandidateSet); + S.AddBuiltinCandidate(LandR, Args, CandidateSet); } } @@ -8148,15 +8069,7 @@ public: Vec2End = CandidateTypes[1].vector_end(); Vec2 != Vec2End; ++Vec2) { QualType LandR[2] = { *Vec1, *Vec2 }; - QualType Result = S.Context.BoolTy; - if (!isComparison) { - if ((*Vec1)->isExtVectorType() || !(*Vec2)->isExtVectorType()) - Result = *Vec1; - else - Result = *Vec2; - } - - S.AddBuiltinCandidate(Result, LandR, Args, CandidateSet); + S.AddBuiltinCandidate(LandR, Args, CandidateSet); } } } @@ -8185,10 +8098,7 @@ public: Right < LastPromotedIntegralType; ++Right) { QualType LandR[2] = { getArithmeticType(Left), getArithmeticType(Right) }; - QualType Result = (Op == OO_LessLess || Op == OO_GreaterGreater) - ? LandR[0] - : getUsualArithmeticConversions(Left, Right); - S.AddBuiltinCandidate(Result, LandR, Args, CandidateSet); + S.AddBuiltinCandidate(LandR, Args, CandidateSet); } } } @@ -8262,7 +8172,7 @@ public: S.Context.getLValueReferenceType(*Ptr), isEqualOp ? *Ptr : S.Context.getPointerDiffType(), }; - S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet, + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet, /*IsAssigmentOperator=*/ isEqualOp); bool NeedVolatile = !(*Ptr).isVolatileQualified() && @@ -8271,7 +8181,7 @@ public: // volatile version ParamTypes[0] = S.Context.getLValueReferenceType(S.Context.getVolatileType(*Ptr)); - S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet, + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet, /*IsAssigmentOperator=*/isEqualOp); } @@ -8280,7 +8190,7 @@ public: // restrict version ParamTypes[0] = S.Context.getLValueReferenceType(S.Context.getRestrictType(*Ptr)); - S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet, + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet, /*IsAssigmentOperator=*/isEqualOp); if (NeedVolatile) { @@ -8290,7 +8200,7 @@ public: S.Context.getCVRQualifiedType(*Ptr, (Qualifiers::Volatile | Qualifiers::Restrict))); - S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet, + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet, /*IsAssigmentOperator=*/isEqualOp); } } @@ -8311,7 +8221,7 @@ public: }; // non-volatile version - S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet, + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet, /*IsAssigmentOperator=*/true); bool NeedVolatile = !(*Ptr).isVolatileQualified() && @@ -8320,7 +8230,7 @@ public: // volatile version ParamTypes[0] = S.Context.getLValueReferenceType(S.Context.getVolatileType(*Ptr)); - S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet, + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet, /*IsAssigmentOperator=*/true); } @@ -8329,7 +8239,7 @@ public: // restrict version ParamTypes[0] = S.Context.getLValueReferenceType(S.Context.getRestrictType(*Ptr)); - S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet, + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet, /*IsAssigmentOperator=*/true); if (NeedVolatile) { @@ -8339,7 +8249,7 @@ public: S.Context.getCVRQualifiedType(*Ptr, (Qualifiers::Volatile | Qualifiers::Restrict))); - S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet, + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet, /*IsAssigmentOperator=*/true); } } @@ -8372,7 +8282,7 @@ public: // Add this built-in operator as a candidate (VQ is empty). ParamTypes[0] = S.Context.getLValueReferenceType(getArithmeticType(Left)); - S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet, + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet, /*IsAssigmentOperator=*/isEqualOp); // Add this built-in operator as a candidate (VQ is 'volatile'). @@ -8380,7 +8290,7 @@ public: ParamTypes[0] = S.Context.getVolatileType(getArithmeticType(Left)); ParamTypes[0] = S.Context.getLValueReferenceType(ParamTypes[0]); - S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet, + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet, /*IsAssigmentOperator=*/isEqualOp); } } @@ -8399,14 +8309,14 @@ public: ParamTypes[1] = *Vec2; // Add this built-in operator as a candidate (VQ is empty). ParamTypes[0] = S.Context.getLValueReferenceType(*Vec1); - S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet, + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet, /*IsAssigmentOperator=*/isEqualOp); // Add this built-in operator as a candidate (VQ is 'volatile'). if (VisibleTypeConversionsQuals.hasVolatile()) { ParamTypes[0] = S.Context.getVolatileType(*Vec1); ParamTypes[0] = S.Context.getLValueReferenceType(ParamTypes[0]); - S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet, + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet, /*IsAssigmentOperator=*/isEqualOp); } } @@ -8438,13 +8348,13 @@ public: // Add this built-in operator as a candidate (VQ is empty). ParamTypes[0] = S.Context.getLValueReferenceType(getArithmeticType(Left)); - S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet); + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet); if (VisibleTypeConversionsQuals.hasVolatile()) { // Add this built-in operator as a candidate (VQ is 'volatile'). ParamTypes[0] = getArithmeticType(Left); ParamTypes[0] = S.Context.getVolatileType(ParamTypes[0]); ParamTypes[0] = S.Context.getLValueReferenceType(ParamTypes[0]); - S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet); + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet); } } } @@ -8459,13 +8369,13 @@ public: // bool operator||(bool, bool); void addExclaimOverload() { QualType ParamTy = S.Context.BoolTy; - S.AddBuiltinCandidate(ParamTy, &ParamTy, Args, CandidateSet, + S.AddBuiltinCandidate(&ParamTy, Args, CandidateSet, /*IsAssignmentOperator=*/false, /*NumContextualBoolArguments=*/1); } void addAmpAmpOrPipePipeOverload() { QualType ParamTypes[2] = { S.Context.BoolTy, S.Context.BoolTy }; - S.AddBuiltinCandidate(S.Context.BoolTy, ParamTypes, Args, CandidateSet, + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet, /*IsAssignmentOperator=*/false, /*NumContextualBoolArguments=*/2); } @@ -8490,10 +8400,8 @@ public: if (!PointeeType->isObjectType()) continue; - QualType ResultTy = S.Context.getLValueReferenceType(PointeeType); - // T& operator[](T*, ptrdiff_t) - S.AddBuiltinCandidate(ResultTy, ParamTypes, Args, CandidateSet); + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet); } for (BuiltinCandidateTypeSet::iterator @@ -8505,10 +8413,8 @@ public: if (!PointeeType->isObjectType()) continue; - QualType ResultTy = S.Context.getLValueReferenceType(PointeeType); - // T& operator[](ptrdiff_t, T*) - S.AddBuiltinCandidate(ResultTy, ParamTypes, Args, CandidateSet); + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet); } } @@ -8558,8 +8464,7 @@ public: T.isRestrictQualified()) continue; T = Q1.apply(S.Context, T); - QualType ResultTy = S.Context.getLValueReferenceType(T); - S.AddBuiltinCandidate(ResultTy, ParamTypes, Args, CandidateSet); + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet); } } } @@ -8587,7 +8492,7 @@ public: continue; QualType ParamTypes[2] = { *Ptr, *Ptr }; - S.AddBuiltinCandidate(*Ptr, ParamTypes, Args, CandidateSet); + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet); } for (BuiltinCandidateTypeSet::iterator @@ -8598,7 +8503,7 @@ public: continue; QualType ParamTypes[2] = { *MemPtr, *MemPtr }; - S.AddBuiltinCandidate(*MemPtr, ParamTypes, Args, CandidateSet); + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet); } if (S.getLangOpts().CPlusPlus11) { @@ -8613,7 +8518,7 @@ public: continue; QualType ParamTypes[2] = { *Enum, *Enum }; - S.AddBuiltinCandidate(*Enum, ParamTypes, Args, CandidateSet); + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet); } } } @@ -8707,7 +8612,7 @@ void Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op, OpBuilder.addUnaryPlusOrMinusArithmeticOverloads(); } else { OpBuilder.addBinaryPlusOrMinusPointerOverloads(Op); - OpBuilder.addGenericBinaryArithmeticOverloads(/*isComparison=*/false); + OpBuilder.addGenericBinaryArithmeticOverloads(); } break; @@ -8715,11 +8620,11 @@ void Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op, if (Args.size() == 1) OpBuilder.addUnaryStarPointerOverloads(); else - OpBuilder.addGenericBinaryArithmeticOverloads(/*isComparison=*/false); + OpBuilder.addGenericBinaryArithmeticOverloads(); break; case OO_Slash: - OpBuilder.addGenericBinaryArithmeticOverloads(/*isComparison=*/false); + OpBuilder.addGenericBinaryArithmeticOverloads(); break; case OO_PlusPlus: @@ -8738,7 +8643,7 @@ void Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op, case OO_LessEqual: case OO_GreaterEqual: OpBuilder.addRelationalPointerOrEnumeralOverloads(); - OpBuilder.addGenericBinaryArithmeticOverloads(/*isComparison=*/true); + OpBuilder.addGenericBinaryArithmeticOverloads(); break; case OO_Percent: @@ -8805,7 +8710,7 @@ void Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op, case OO_Conditional: OpBuilder.addConditionalOperatorOverloads(); - OpBuilder.addGenericBinaryArithmeticOverloads(/*isComparison=*/false); + OpBuilder.addGenericBinaryArithmeticOverloads(); break; } } @@ -10237,13 +10142,13 @@ static void NoteBuiltinOperatorCandidate(Sema &S, StringRef Opc, std::string TypeStr("operator"); TypeStr += Opc; TypeStr += "("; - TypeStr += Cand->BuiltinTypes.ParamTypes[0].getAsString(); + TypeStr += Cand->BuiltinParamTypes[0].getAsString(); if (Cand->Conversions.size() == 1) { TypeStr += ")"; S.Diag(OpLoc, diag::note_ovl_builtin_unary_candidate) << TypeStr; } else { TypeStr += ", "; - TypeStr += Cand->BuiltinTypes.ParamTypes[1].getAsString(); + TypeStr += Cand->BuiltinParamTypes[1].getAsString(); TypeStr += ")"; S.Diag(OpLoc, diag::note_ovl_builtin_binary_candidate) << TypeStr; } @@ -10480,7 +10385,7 @@ static void CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand, } else { // Builtin operator. assert(ConvCount <= 3); - ParamTypes = Cand->BuiltinTypes.ParamTypes; + ParamTypes = Cand->BuiltinParamTypes; } // Fill in the rest of the conversions. @@ -12086,9 +11991,8 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, // We matched a built-in operator. Convert the arguments, then // break out so that we will build the appropriate built-in // operator node. - ExprResult InputRes = - PerformImplicitConversion(Input, Best->BuiltinTypes.ParamTypes[0], - Best->Conversions[0], AA_Passing); + ExprResult InputRes = PerformImplicitConversion( + Input, Best->BuiltinParamTypes[0], Best->Conversions[0], AA_Passing); if (InputRes.isInvalid()) return ExprError(); Input = InputRes.get(); @@ -12332,15 +12236,15 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, // break out so that we will build the appropriate built-in // operator node. ExprResult ArgsRes0 = - PerformImplicitConversion(Args[0], Best->BuiltinTypes.ParamTypes[0], - Best->Conversions[0], AA_Passing); + PerformImplicitConversion(Args[0], Best->BuiltinParamTypes[0], + Best->Conversions[0], AA_Passing); if (ArgsRes0.isInvalid()) return ExprError(); Args[0] = ArgsRes0.get(); ExprResult ArgsRes1 = - PerformImplicitConversion(Args[1], Best->BuiltinTypes.ParamTypes[1], - Best->Conversions[1], AA_Passing); + PerformImplicitConversion(Args[1], Best->BuiltinParamTypes[1], + Best->Conversions[1], AA_Passing); if (ArgsRes1.isInvalid()) return ExprError(); Args[1] = ArgsRes1.get(); @@ -12543,15 +12447,15 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, // break out so that we will build the appropriate built-in // operator node. ExprResult ArgsRes0 = - PerformImplicitConversion(Args[0], Best->BuiltinTypes.ParamTypes[0], - Best->Conversions[0], AA_Passing); + PerformImplicitConversion(Args[0], Best->BuiltinParamTypes[0], + Best->Conversions[0], AA_Passing); if (ArgsRes0.isInvalid()) return ExprError(); Args[0] = ArgsRes0.get(); ExprResult ArgsRes1 = - PerformImplicitConversion(Args[1], Best->BuiltinTypes.ParamTypes[1], - Best->Conversions[1], AA_Passing); + PerformImplicitConversion(Args[1], Best->BuiltinParamTypes[1], + Best->Conversions[1], AA_Passing); if (ArgsRes1.isInvalid()) return ExprError(); Args[1] = ArgsRes1.get(); diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index dcb2c11c73c7..151b89ab8d2a 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -3956,8 +3956,9 @@ void Sema::ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope, DeclContext *DC = CapturedDecl::castToDeclContext(CD); IdentifierInfo *ParamName = &Context.Idents.get("__context"); QualType ParamType = Context.getPointerType(Context.getTagDeclType(RD)); - ImplicitParamDecl *Param - = ImplicitParamDecl::Create(Context, DC, Loc, ParamName, ParamType); + auto *Param = + ImplicitParamDecl::Create(Context, DC, Loc, ParamName, ParamType, + ImplicitParamDecl::CapturedContext); DC->addDecl(Param); CD->setContextParam(0, Param); @@ -3992,15 +3993,17 @@ void Sema::ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope, "null type has been found already for '__context' parameter"); IdentifierInfo *ParamName = &Context.Idents.get("__context"); QualType ParamType = Context.getPointerType(Context.getTagDeclType(RD)); - ImplicitParamDecl *Param - = ImplicitParamDecl::Create(Context, DC, Loc, ParamName, ParamType); + auto *Param = + ImplicitParamDecl::Create(Context, DC, Loc, ParamName, ParamType, + ImplicitParamDecl::CapturedContext); DC->addDecl(Param); CD->setContextParam(ParamNum, Param); ContextIsFound = true; } else { IdentifierInfo *ParamName = &Context.Idents.get(I->first); - ImplicitParamDecl *Param - = ImplicitParamDecl::Create(Context, DC, Loc, ParamName, I->second); + auto *Param = + ImplicitParamDecl::Create(Context, DC, Loc, ParamName, I->second, + ImplicitParamDecl::CapturedContext); DC->addDecl(Param); CD->setParam(ParamNum, Param); } @@ -4010,8 +4013,9 @@ void Sema::ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope, // Add __context implicitly if it is not specified. IdentifierInfo *ParamName = &Context.Idents.get("__context"); QualType ParamType = Context.getPointerType(Context.getTagDeclType(RD)); - ImplicitParamDecl *Param = - ImplicitParamDecl::Create(Context, DC, Loc, ParamName, ParamType); + auto *Param = + ImplicitParamDecl::Create(Context, DC, Loc, ParamName, ParamType, + ImplicitParamDecl::CapturedContext); DC->addDecl(Param); CD->setContextParam(ParamNum, Param); } diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 8cd7efbb1dba..1eea151a4ec8 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -4020,6 +4020,7 @@ bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param, } } // fallthrough + LLVM_FALLTHROUGH; } default: { // We have a template type parameter but the template argument @@ -7594,6 +7595,7 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc, return false; } // Fall through + LLVM_FALLTHROUGH; case TSK_ExplicitInstantiationDeclaration: case TSK_ExplicitInstantiationDefinition: @@ -7620,6 +7622,7 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc, return true; } + llvm_unreachable("The switch over PrevTSK must be exhaustive."); case TSK_ExplicitInstantiationDeclaration: switch (PrevTSK) { @@ -8955,7 +8958,8 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, // A member function [...] of a class template can be explicitly // instantiated from the member definition associated with its class // template. - UnresolvedSet<8> Matches; + UnresolvedSet<8> TemplateMatches; + FunctionDecl *NonTemplateMatch = nullptr; AttributeList *Attr = D.getDeclSpec().getAttributes().getList(); TemplateSpecCandidateSet FailedCandidates(D.getIdentifierLoc()); for (LookupResult::iterator P = Previous.begin(), PEnd = Previous.end(); @@ -8966,11 +8970,13 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, QualType Adjusted = adjustCCAndNoReturn(R, Method->getType(), /*AdjustExceptionSpec*/true); if (Context.hasSameUnqualifiedType(Method->getType(), Adjusted)) { - Matches.clear(); - - Matches.addDecl(Method, P.getAccess()); - if (Method->getTemplateSpecializationKind() == TSK_Undeclared) - break; + if (Method->getPrimaryTemplate()) { + TemplateMatches.addDecl(Method, P.getAccess()); + } else { + // FIXME: Can this assert ever happen? Needs a test. + assert(!NonTemplateMatch && "Multiple NonTemplateMatches"); + NonTemplateMatch = Method; + } } } } @@ -9009,22 +9015,25 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, continue; } - Matches.addDecl(Specialization, P.getAccess()); + TemplateMatches.addDecl(Specialization, P.getAccess()); } - // Find the most specialized function template specialization. - UnresolvedSetIterator Result = getMostSpecialized( - Matches.begin(), Matches.end(), FailedCandidates, - D.getIdentifierLoc(), - PDiag(diag::err_explicit_instantiation_not_known) << Name, - PDiag(diag::err_explicit_instantiation_ambiguous) << Name, - PDiag(diag::note_explicit_instantiation_candidate)); - - if (Result == Matches.end()) - return true; + FunctionDecl *Specialization = NonTemplateMatch; + if (!Specialization) { + // Find the most specialized function template specialization. + UnresolvedSetIterator Result = getMostSpecialized( + TemplateMatches.begin(), TemplateMatches.end(), FailedCandidates, + D.getIdentifierLoc(), + PDiag(diag::err_explicit_instantiation_not_known) << Name, + PDiag(diag::err_explicit_instantiation_ambiguous) << Name, + PDiag(diag::note_explicit_instantiation_candidate)); + + if (Result == TemplateMatches.end()) + return true; - // Ignore access control bits, we don't need them for redeclaration checking. - FunctionDecl *Specialization = cast<FunctionDecl>(*Result); + // Ignore access control bits, we don't need them for redeclaration checking. + Specialization = cast<FunctionDecl>(*Result); + } // C++11 [except.spec]p4 // In an explicit instantiation an exception-specification may be specified, @@ -9379,6 +9388,7 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword, } // Fall through to create a dependent typename type, from which we can recover // better. + LLVM_FALLTHROUGH; case LookupResult::NotFoundInCurrentInstantiation: // Okay, it's a member of an unknown instantiation. diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index 75b69ae04f56..983b1ea795dd 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -56,8 +56,12 @@ namespace clang { TDF_TopLevelParameterTypeList = 0x10, /// \brief Within template argument deduction from overload resolution per /// C++ [over.over] allow matching function types that are compatible in - /// terms of noreturn and default calling convention adjustments. - TDF_InOverloadResolution = 0x20 + /// terms of noreturn and default calling convention adjustments, or + /// similarly matching a declared template specialization against a + /// possible template, per C++ [temp.deduct.decl]. In either case, permit + /// deduction where the parameter is a function type that can be converted + /// to the argument type. + TDF_AllowCompatibleFunctionType = 0x20, }; } @@ -1306,9 +1310,10 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S, // If the parameter type is not dependent, there is nothing to deduce. if (!Param->isDependentType()) { if (!(TDF & TDF_SkipNonDependent)) { - bool NonDeduced = (TDF & TDF_InOverloadResolution)? - !S.isSameOrCompatibleFunctionType(CanParam, CanArg) : - Param != Arg; + bool NonDeduced = + (TDF & TDF_AllowCompatibleFunctionType) + ? !S.isSameOrCompatibleFunctionType(CanParam, CanArg) + : Param != Arg; if (NonDeduced) { return Sema::TDK_NonDeducedMismatch; } @@ -1318,10 +1323,10 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S, } else if (!Param->isDependentType()) { CanQualType ParamUnqualType = CanParam.getUnqualifiedType(), ArgUnqualType = CanArg.getUnqualifiedType(); - bool Success = (TDF & TDF_InOverloadResolution)? - S.isSameOrCompatibleFunctionType(ParamUnqualType, - ArgUnqualType) : - ParamUnqualType == ArgUnqualType; + bool Success = + (TDF & TDF_AllowCompatibleFunctionType) + ? S.isSameOrCompatibleFunctionType(ParamUnqualType, ArgUnqualType) + : ParamUnqualType == ArgUnqualType; if (Success) return Sema::TDK_Success; } @@ -1524,17 +1529,56 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S, return Sema::TDK_NonDeducedMismatch; // Check return types. - if (Sema::TemplateDeductionResult Result = - DeduceTemplateArgumentsByTypeMatch( - S, TemplateParams, FunctionProtoParam->getReturnType(), - FunctionProtoArg->getReturnType(), Info, Deduced, 0)) + if (auto Result = DeduceTemplateArgumentsByTypeMatch( + S, TemplateParams, FunctionProtoParam->getReturnType(), + FunctionProtoArg->getReturnType(), Info, Deduced, 0)) return Result; - return DeduceTemplateArguments( - S, TemplateParams, FunctionProtoParam->param_type_begin(), - FunctionProtoParam->getNumParams(), - FunctionProtoArg->param_type_begin(), - FunctionProtoArg->getNumParams(), Info, Deduced, SubTDF); + // Check parameter types. + if (auto Result = DeduceTemplateArguments( + S, TemplateParams, FunctionProtoParam->param_type_begin(), + FunctionProtoParam->getNumParams(), + FunctionProtoArg->param_type_begin(), + FunctionProtoArg->getNumParams(), Info, Deduced, SubTDF)) + return Result; + + if (TDF & TDF_AllowCompatibleFunctionType) + return Sema::TDK_Success; + + // FIXME: Per core-2016/10/1019 (no corresponding core issue yet), permit + // deducing through the noexcept-specifier if it's part of the canonical + // type. libstdc++ relies on this. + Expr *NoexceptExpr = FunctionProtoParam->getNoexceptExpr(); + if (NonTypeTemplateParmDecl *NTTP = + NoexceptExpr ? getDeducedParameterFromExpr(Info, NoexceptExpr) + : nullptr) { + assert(NTTP->getDepth() == Info.getDeducedDepth() && + "saw non-type template parameter with wrong depth"); + + llvm::APSInt Noexcept(1); + switch (FunctionProtoArg->canThrow(S.Context)) { + case CT_Cannot: + Noexcept = 1; + LLVM_FALLTHROUGH; + + case CT_Can: + // We give E in noexcept(E) the "deduced from array bound" treatment. + // FIXME: Should we? + return DeduceNonTypeTemplateArgument( + S, TemplateParams, NTTP, Noexcept, S.Context.BoolTy, + /*ArrayBound*/true, Info, Deduced); + + case CT_Dependent: + if (Expr *ArgNoexceptExpr = FunctionProtoArg->getNoexceptExpr()) + return DeduceNonTypeTemplateArgument( + S, TemplateParams, NTTP, ArgNoexceptExpr, Info, Deduced); + // Can't deduce anything from throw(T...). + break; + } + } + // FIXME: Detect non-deduced exception specification mismatches? + + return Sema::TDK_Success; } case Type::InjectedClassName: { @@ -1544,7 +1588,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S, ->getInjectedSpecializationType(); assert(isa<TemplateSpecializationType>(Param) && "injected class name is not a template specialization type"); - // fall through + LLVM_FALLTHROUGH; } // template-name<T> (where template-name refers to a class template) @@ -2820,6 +2864,17 @@ Sema::SubstituteExplicitTemplateArguments( if (FunctionType) { auto EPI = Proto->getExtProtoInfo(); EPI.ExtParameterInfos = ExtParamInfos.getPointerOrNull(ParamTypes.size()); + + // In C++1z onwards, exception specifications are part of the function type, + // so substitution into the type must also substitute into the exception + // specification. + SmallVector<QualType, 4> ExceptionStorage; + if (getLangOpts().CPlusPlus1z && + SubstExceptionSpec( + Function->getLocation(), EPI.ExceptionSpec, ExceptionStorage, + MultiLevelTemplateArgumentList(*ExplicitArgumentList))) + return TDK_SubstitutionFailure; + *FunctionType = BuildFunctionType(ResultType, ParamTypes, Function->getLocation(), Function->getDeclName(), @@ -3714,13 +3769,6 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( = FunctionTemplate->getTemplateParameters(); QualType FunctionType = Function->getType(); - // When taking the address of a function, we require convertibility of - // the resulting function type. Otherwise, we allow arbitrary mismatches - // of calling convention, noreturn, and noexcept. - if (!IsAddressOfFunction) - ArgFunctionType = adjustCCAndNoReturn(ArgFunctionType, FunctionType, - /*AdjustExceptionSpec*/true); - // Substitute any explicit template arguments. LocalInstantiationScope InstScope(*this); SmallVector<DeducedTemplateArgument, 4> Deduced; @@ -3737,6 +3785,13 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( NumExplicitlySpecified = Deduced.size(); } + // When taking the address of a function, we require convertibility of + // the resulting function type. Otherwise, we allow arbitrary mismatches + // of calling convention and noreturn. + if (!IsAddressOfFunction) + ArgFunctionType = adjustCCAndNoReturn(ArgFunctionType, FunctionType, + /*AdjustExceptionSpec*/false); + // Unevaluated SFINAE context. EnterExpressionEvaluationContext Unevaluated( *this, Sema::ExpressionEvaluationContext::Unevaluated); @@ -3756,9 +3811,8 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( } if (!ArgFunctionType.isNull()) { - unsigned TDF = TDF_TopLevelParameterTypeList; - if (IsAddressOfFunction) - TDF |= TDF_InOverloadResolution; + unsigned TDF = + TDF_TopLevelParameterTypeList | TDF_AllowCompatibleFunctionType; // Deduce template arguments from the function type. if (TemplateDeductionResult Result = DeduceTemplateArgumentsByTypeMatch(*this, TemplateParams, @@ -3789,7 +3843,7 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( !ResolveExceptionSpec(Info.getLocation(), SpecializationFPT)) return TDK_MiscellaneousDeductionFailure; - // Adjust the exception specification of the argument again to match the + // Adjust the exception specification of the argument to match the // substituted and resolved type we just formed. (Calling convention and // noreturn can't be dependent, so we don't actually need this for them // right now.) @@ -5127,6 +5181,8 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T, for (unsigned I = 0, N = Proto->getNumParams(); I != N; ++I) MarkUsedTemplateParameters(Ctx, Proto->getParamType(I), OnlyDeduced, Depth, Used); + if (auto *E = Proto->getNoexceptExpr()) + MarkUsedTemplateParameters(Ctx, E, OnlyDeduced, Depth, Used); break; } diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index a654ca800b05..fe92dd8ac653 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -1692,20 +1692,26 @@ TypeSourceInfo *Sema::SubstFunctionDeclType(TypeSourceInfo *T, return TLB.getTypeSourceInfo(Context, Result); } +bool Sema::SubstExceptionSpec(SourceLocation Loc, + FunctionProtoType::ExceptionSpecInfo &ESI, + SmallVectorImpl<QualType> &ExceptionStorage, + const MultiLevelTemplateArgumentList &Args) { + assert(ESI.Type != EST_Uninstantiated); + + bool Changed = false; + TemplateInstantiator Instantiator(*this, Args, Loc, DeclarationName()); + return Instantiator.TransformExceptionSpec(Loc, ESI, ExceptionStorage, + Changed); +} + void Sema::SubstExceptionSpec(FunctionDecl *New, const FunctionProtoType *Proto, const MultiLevelTemplateArgumentList &Args) { FunctionProtoType::ExceptionSpecInfo ESI = Proto->getExtProtoInfo().ExceptionSpec; - assert(ESI.Type != EST_Uninstantiated); - - TemplateInstantiator Instantiator(*this, Args, New->getLocation(), - New->getDeclName()); SmallVector<QualType, 4> ExceptionStorage; - bool Changed = false; - if (Instantiator.TransformExceptionSpec( - New->getTypeSourceInfo()->getTypeLoc().getLocEnd(), ESI, - ExceptionStorage, Changed)) + if (SubstExceptionSpec(New->getTypeSourceInfo()->getTypeLoc().getLocEnd(), + ESI, ExceptionStorage, Args)) // On error, recover by dropping the exception specification. ESI.Type = EST_None; @@ -2350,6 +2356,25 @@ namespace { }; } +bool Sema::usesPartialOrExplicitSpecialization( + SourceLocation Loc, ClassTemplateSpecializationDecl *ClassTemplateSpec) { + if (ClassTemplateSpec->getTemplateSpecializationKind() == + TSK_ExplicitSpecialization) + return true; + + SmallVector<ClassTemplatePartialSpecializationDecl *, 4> PartialSpecs; + ClassTemplateSpec->getSpecializedTemplate() + ->getPartialSpecializations(PartialSpecs); + for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I) { + TemplateDeductionInfo Info(Loc); + if (!DeduceTemplateArguments(PartialSpecs[I], + ClassTemplateSpec->getTemplateArgs(), Info)) + return true; + } + + return false; +} + /// Get the instantiation pattern to use to instantiate the definition of a /// given ClassTemplateSpecializationDecl (either the pattern of the primary /// template or of a partial specialization). diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index e7523ce2836d..148ce24293a0 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -4807,7 +4807,7 @@ static NamedDecl *findInstantiationOf(ASTContext &Ctx, DeclContext *Sema::FindInstantiatedContext(SourceLocation Loc, DeclContext* DC, const MultiLevelTemplateArgumentList &TemplateArgs) { if (NamedDecl *D = dyn_cast<NamedDecl>(DC)) { - Decl* ID = FindInstantiatedDecl(Loc, D, TemplateArgs); + Decl* ID = FindInstantiatedDecl(Loc, D, TemplateArgs, true); return cast_or_null<DeclContext>(ID); } else return DC; } @@ -4839,7 +4839,8 @@ DeclContext *Sema::FindInstantiatedContext(SourceLocation Loc, DeclContext* DC, /// (<tt>X<int>::<Kind>::KnownValue</tt>). \p FindInstantiatedDecl performs /// this mapping from within the instantiation of <tt>X<int></tt>. NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, - const MultiLevelTemplateArgumentList &TemplateArgs) { + const MultiLevelTemplateArgumentList &TemplateArgs, + bool FindingInstantiatedContext) { DeclContext *ParentDC = D->getDeclContext(); // FIXME: Parmeters of pointer to functions (y below) that are themselves // parameters (p below) can have their ParentDC set to the translation-unit @@ -5000,7 +5001,22 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, QualType T = CheckTemplateIdType(TemplateName(TD), Loc, Args); if (T.isNull()) return nullptr; - DC = T->getAsCXXRecordDecl(); + auto *SubstRecord = T->getAsCXXRecordDecl(); + assert(SubstRecord && "class template id not a class type?"); + // Check that this template-id names the primary template and not a + // partial or explicit specialization. (In the latter cases, it's + // meaningless to attempt to find an instantiation of D within the + // specialization.) + // FIXME: The standard doesn't say what should happen here. + if (FindingInstantiatedContext && + usesPartialOrExplicitSpecialization( + Loc, cast<ClassTemplateSpecializationDecl>(SubstRecord))) { + Diag(Loc, diag::err_specialization_not_primary_template) + << T << (SubstRecord->getTemplateSpecializationKind() == + TSK_ExplicitSpecialization); + return nullptr; + } + DC = SubstRecord; continue; } } diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index c189112e3455..8c8402e75e37 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -3367,7 +3367,7 @@ classifyPointerDeclarator(Sema &S, QualType type, Declarator &declarator, if (auto objcClass = type->getAs<ObjCInterfaceType>()) { if (objcClass->getInterface()->getIdentifier() == S.getNSErrorIdent()) { if (numNormalPointers == 2 && numTypeSpecifierPointers < 2) - return PointerDeclaratorKind::NSErrorPointerPointer;; + return PointerDeclaratorKind::NSErrorPointerPointer; } break; diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index e16a9b3ee3b5..94a8f609f57c 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -4918,6 +4918,7 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { } CurrentModule->setASTFile(F.File); + CurrentModule->PresumedModuleMapFile = F.ModuleMapPath; } CurrentModule->Kind = ModuleKind; @@ -5211,6 +5212,8 @@ bool ASTReader::ParseHeaderSearchOptions(const RecordData &Record, HSOpts.ModuleCachePath = ReadString(Record, Idx); HSOpts.ModuleUserBuildPath = ReadString(Record, Idx); HSOpts.DisableModuleHash = Record[Idx++]; + HSOpts.ImplicitModuleMaps = Record[Idx++]; + HSOpts.ModuleMapFileHomeIsCwd = Record[Idx++]; HSOpts.UseBuiltinIncludes = Record[Idx++]; HSOpts.UseStandardSystemIncludes = Record[Idx++]; HSOpts.UseStandardCXXIncludes = Record[Idx++]; @@ -9750,13 +9753,13 @@ void ASTReader::diagnoseOdrViolations() { if (Diagnosed == true) continue; - Diag(FirstRecord->getLocation(), - diag::err_module_odr_violation_different_definitions) - << FirstRecord << FirstModule.empty() << FirstModule; - - Diag(SecondRecord->getLocation(), - diag::note_module_odr_violation_different_definitions) - << SecondModule; + Diag(FirstDecl->getLocation(), + diag::err_module_odr_violation_mismatch_decl_unknown) + << FirstRecord << FirstModule.empty() << FirstModule << FirstDiffType + << FirstDecl->getSourceRange(); + Diag(SecondDecl->getLocation(), + diag::note_module_odr_violation_mismatch_decl_unknown) + << SecondModule << FirstDiffType << SecondDecl->getSourceRange(); Diagnosed = true; } diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index f3ee9078298e..9c467055fe55 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -216,6 +216,30 @@ namespace clang { TypedefNameForLinkage(nullptr), HasPendingBody(false), IsDeclMarkedUsed(false) {} + template <typename T> static + void AddLazySpecializations(T *D, + SmallVectorImpl<serialization::DeclID>& IDs) { + if (IDs.empty()) + return; + + // FIXME: We should avoid this pattern of getting the ASTContext. + ASTContext &C = D->getASTContext(); + + auto *&LazySpecializations = D->getCommonPtr()->LazySpecializations; + + if (auto &Old = LazySpecializations) { + IDs.insert(IDs.end(), Old + 1, Old + 1 + Old[0]); + std::sort(IDs.begin(), IDs.end()); + IDs.erase(std::unique(IDs.begin(), IDs.end()), IDs.end()); + } + + auto *Result = new (C) serialization::DeclID[1 + IDs.size()]; + *Result = IDs.size(); + std::copy(IDs.begin(), IDs.end(), Result + 1); + + LazySpecializations = Result; + } + template <typename DeclT> static Decl *getMostRecentDeclImpl(Redeclarable<DeclT> *D); static Decl *getMostRecentDeclImpl(...); @@ -244,7 +268,7 @@ namespace clang { void ReadFunctionDefinition(FunctionDecl *FD); void Visit(Decl *D); - void UpdateDecl(Decl *D); + void UpdateDecl(Decl *D, llvm::SmallVectorImpl<serialization::DeclID>&); static void setNextObjCCategory(ObjCCategoryDecl *Cat, ObjCCategoryDecl *Next) { @@ -1229,6 +1253,7 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitVarDeclImpl(VarDecl *VD) { VD->NonParmVarDeclBits.IsConstexpr = Record.readInt(); VD->NonParmVarDeclBits.IsInitCapture = Record.readInt(); VD->NonParmVarDeclBits.PreviousDeclInSameBlockScope = Record.readInt(); + VD->NonParmVarDeclBits.ImplicitParamKind = Record.readInt(); } Linkage VarLinkage = Linkage(Record.readInt()); VD->setCachedLinkage(VarLinkage); @@ -1951,21 +1976,6 @@ ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) { return Redecl; } -static DeclID *newDeclIDList(ASTContext &Context, DeclID *Old, - SmallVectorImpl<DeclID> &IDs) { - assert(!IDs.empty() && "no IDs to add to list"); - if (Old) { - IDs.insert(IDs.end(), Old + 1, Old + 1 + Old[0]); - std::sort(IDs.begin(), IDs.end()); - IDs.erase(std::unique(IDs.begin(), IDs.end()), IDs.end()); - } - - auto *Result = new (Context) DeclID[1 + IDs.size()]; - *Result = IDs.size(); - std::copy(IDs.begin(), IDs.end(), Result + 1); - return Result; -} - void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) { RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D); @@ -1974,12 +1984,7 @@ void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) { // the specializations. SmallVector<serialization::DeclID, 32> SpecIDs; ReadDeclIDList(SpecIDs); - - if (!SpecIDs.empty()) { - auto *CommonPtr = D->getCommonPtr(); - CommonPtr->LazySpecializations = newDeclIDList( - Reader.getContext(), CommonPtr->LazySpecializations, SpecIDs); - } + ASTDeclReader::AddLazySpecializations(D, SpecIDs); } if (D->getTemplatedDecl()->TemplateOrInstantiation) { @@ -2006,12 +2011,7 @@ void ASTDeclReader::VisitVarTemplateDecl(VarTemplateDecl *D) { // the specializations. SmallVector<serialization::DeclID, 32> SpecIDs; ReadDeclIDList(SpecIDs); - - if (!SpecIDs.empty()) { - auto *CommonPtr = D->getCommonPtr(); - CommonPtr->LazySpecializations = newDeclIDList( - Reader.getContext(), CommonPtr->LazySpecializations, SpecIDs); - } + ASTDeclReader::AddLazySpecializations(D, SpecIDs); } } @@ -2117,12 +2117,7 @@ void ASTDeclReader::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { // This FunctionTemplateDecl owns a CommonPtr; read it. SmallVector<serialization::DeclID, 32> SpecIDs; ReadDeclIDList(SpecIDs); - - if (!SpecIDs.empty()) { - auto *CommonPtr = D->getCommonPtr(); - CommonPtr->LazySpecializations = newDeclIDList( - Reader.getContext(), CommonPtr->LazySpecializations, SpecIDs); - } + ASTDeclReader::AddLazySpecializations(D, SpecIDs); } } @@ -3666,6 +3661,9 @@ void ASTReader::loadDeclUpdateRecords(PendingUpdateRecord &Record) { Decl *D = Record.D; ProcessingUpdatesRAIIObj ProcessingUpdates(*this); DeclUpdateOffsetsMap::iterator UpdI = DeclUpdateOffsets.find(ID); + + llvm::SmallVector<serialization::DeclID, 8> PendingLazySpecializationIDs; + if (UpdI != DeclUpdateOffsets.end()) { auto UpdateOffsets = std::move(UpdI->second); DeclUpdateOffsets.erase(UpdI); @@ -3690,7 +3688,7 @@ void ASTReader::loadDeclUpdateRecords(PendingUpdateRecord &Record) { ASTDeclReader Reader(*this, Record, RecordLocation(F, Offset), ID, SourceLocation()); - Reader.UpdateDecl(D); + Reader.UpdateDecl(D, PendingLazySpecializationIDs); // We might have made this declaration interesting. If so, remember that // we need to hand it off to the consumer. @@ -3702,6 +3700,17 @@ void ASTReader::loadDeclUpdateRecords(PendingUpdateRecord &Record) { } } } + // Add the lazy specializations to the template. + assert((PendingLazySpecializationIDs.empty() || isa<ClassTemplateDecl>(D) || + isa<FunctionTemplateDecl>(D) || isa<VarTemplateDecl>(D)) && + "Must not have pending specializations"); + if (auto *CTD = dyn_cast<ClassTemplateDecl>(D)) + ASTDeclReader::AddLazySpecializations(CTD, PendingLazySpecializationIDs); + else if (auto *FTD = dyn_cast<FunctionTemplateDecl>(D)) + ASTDeclReader::AddLazySpecializations(FTD, PendingLazySpecializationIDs); + else if (auto *VTD = dyn_cast<VarTemplateDecl>(D)) + ASTDeclReader::AddLazySpecializations(VTD, PendingLazySpecializationIDs); + PendingLazySpecializationIDs.clear(); // Load the pending visible updates for this decl context, if it has any. auto I = PendingVisibleUpdates.find(ID); @@ -3898,7 +3907,8 @@ static void forAllLaterRedecls(DeclT *D, Fn F) { } } -void ASTDeclReader::UpdateDecl(Decl *D) { +void ASTDeclReader::UpdateDecl(Decl *D, + llvm::SmallVectorImpl<serialization::DeclID> &PendingLazySpecializationIDs) { while (Record.getIdx() < Record.size()) { switch ((DeclUpdateKind)Record.readInt()) { case UPD_CXX_ADDED_IMPLICIT_MEMBER: { @@ -3914,8 +3924,8 @@ void ASTDeclReader::UpdateDecl(Decl *D) { } case UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION: - // It will be added to the template's specializations set when loaded. - (void)Record.readDecl(); + // It will be added to the template's lazy specialization set. + PendingLazySpecializationIDs.push_back(ReadDeclID()); break; case UPD_CXX_ADDED_ANONYMOUS_NAMESPACE: { diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index 044a26433a93..dcacabec1225 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -1601,6 +1601,8 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context, AddString(HSOpts.ModuleCachePath, Record); AddString(HSOpts.ModuleUserBuildPath, Record); Record.push_back(HSOpts.DisableModuleHash); + Record.push_back(HSOpts.ImplicitModuleMaps); + Record.push_back(HSOpts.ModuleMapFileHomeIsCwd); Record.push_back(HSOpts.UseBuiltinIncludes); Record.push_back(HSOpts.UseStandardSystemIncludes); Record.push_back(HSOpts.UseStandardCXXIncludes); diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp index 8fa64aa1b9d3..2d648cb103cb 100644 --- a/lib/Serialization/ASTWriterDecl.cpp +++ b/lib/Serialization/ASTWriterDecl.cpp @@ -915,6 +915,10 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) { Record.push_back(D->isConstexpr()); Record.push_back(D->isInitCapture()); Record.push_back(D->isPreviousDeclInSameBlockScope()); + if (const auto *IPD = dyn_cast<ImplicitParamDecl>(D)) + Record.push_back(static_cast<unsigned>(IPD->getParameterKind())); + else + Record.push_back(0); } Record.push_back(D->getLinkageInternal()); @@ -1989,6 +1993,7 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(0)); // isConstexpr Abv->Add(BitCodeAbbrevOp(0)); // isInitCapture Abv->Add(BitCodeAbbrevOp(0)); // isPrevDeclInSameScope + Abv->Add(BitCodeAbbrevOp(0)); // ImplicitParamKind Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Linkage Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // IsInitICE (local) Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // VarKind (local enum) diff --git a/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp b/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp index 41999d252763..fa9a317683ba 100644 --- a/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp @@ -326,7 +326,7 @@ NullabilityChecker::NullabilityBugVisitor::VisitNode(const ExplodedNode *N, // Retrieve the associated statement. const Stmt *S = TrackedNullab->getNullabilitySource(); - if (!S) { + if (!S || S->getLocStart().isInvalid()) { S = PathDiagnosticLocation::getStmt(N); } diff --git a/lib/StaticAnalyzer/Core/BugReporter.cpp b/lib/StaticAnalyzer/Core/BugReporter.cpp index 2c3169c0f8dd..d8fca00681b4 100644 --- a/lib/StaticAnalyzer/Core/BugReporter.cpp +++ b/lib/StaticAnalyzer/Core/BugReporter.cpp @@ -1671,9 +1671,15 @@ static bool GenerateAlternateExtensivePathDiagnostic( // Add an edge to the start of the function. const StackFrameContext *CalleeLC = CE->getCalleeContext(); const Decl *D = CalleeLC->getDecl(); - addEdgeToPath(PD.getActivePath(), PrevLoc, - PathDiagnosticLocation::createBegin(D, SM), - CalleeLC); + // Add the edge only when the callee has body. We jump to the beginning + // of the *declaration*, however we expect it to be followed by the + // body. This isn't the case for autosynthesized property accessors in + // Objective-C. No need for a similar extra check for CallExit points + // because the exit edge comes from a statement (i.e. return), + // not from declaration. + if (D->hasBody()) + addEdgeToPath(PD.getActivePath(), PrevLoc, + PathDiagnosticLocation::createBegin(D, SM), CalleeLC); // Did we visit an entire call? bool VisitedEntireCall = PD.isWithinCall(); diff --git a/lib/StaticAnalyzer/Core/PathDiagnostic.cpp b/lib/StaticAnalyzer/Core/PathDiagnostic.cpp index 7c5ee3b25944..6aa6da560e60 100644 --- a/lib/StaticAnalyzer/Core/PathDiagnostic.cpp +++ b/lib/StaticAnalyzer/Core/PathDiagnostic.cpp @@ -694,7 +694,30 @@ PathDiagnosticLocation::create(const ProgramPoint& P, return PathDiagnosticLocation(S, SMng, P.getLocationContext()); } +static const LocationContext * +findTopAutosynthesizedParentContext(const LocationContext *LC) { + assert(LC->getAnalysisDeclContext()->isBodyAutosynthesized()); + const LocationContext *ParentLC = LC->getParent(); + assert(ParentLC && "We don't start analysis from autosynthesized code"); + while (ParentLC->getAnalysisDeclContext()->isBodyAutosynthesized()) { + LC = ParentLC; + ParentLC = LC->getParent(); + assert(ParentLC && "We don't start analysis from autosynthesized code"); + } + return LC; +} + const Stmt *PathDiagnosticLocation::getStmt(const ExplodedNode *N) { + // We cannot place diagnostics on autosynthesized code. + // Put them onto the call site through which we jumped into autosynthesized + // code for the first time. + const LocationContext *LC = N->getLocationContext(); + if (LC->getAnalysisDeclContext()->isBodyAutosynthesized()) { + // It must be a stack frame because we only autosynthesize functions. + return cast<StackFrameContext>(findTopAutosynthesizedParentContext(LC)) + ->getCallSite(); + } + // Otherwise, see if the node's program point directly points to a statement. ProgramPoint P = N->getLocation(); if (Optional<StmtPoint> SP = P.getAs<StmtPoint>()) return SP->getStmt(); @@ -912,6 +935,17 @@ void PathDiagnosticCallPiece::setCallee(const CallEnter &CE, callEnterWithin = PathDiagnosticLocation::createBegin(Callee, SM); callEnter = getLocationForCaller(CalleeCtx, CE.getLocationContext(), SM); + + // Autosynthesized property accessors are special because we'd never + // pop back up to non-autosynthesized code until we leave them. + // This is not generally true for autosynthesized callees, which may call + // non-autosynthesized callbacks. + // Unless set here, the IsCalleeAnAutosynthesizedPropertyAccessor flag + // defaults to false. + if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(Callee)) + IsCalleeAnAutosynthesizedPropertyAccessor = ( + MD->isPropertyAccessor() && + CalleeCtx->getAnalysisDeclContext()->isBodyAutosynthesized()); } static inline void describeClass(raw_ostream &Out, const CXXRecordDecl *D, @@ -986,7 +1020,11 @@ static bool describeCodeDecl(raw_ostream &Out, const Decl *D, std::shared_ptr<PathDiagnosticEventPiece> PathDiagnosticCallPiece::getCallEnterEvent() const { - if (!Callee) + // We do not produce call enters and call exits for autosynthesized property + // accessors. We do generally produce them for other functions coming from + // the body farm because they may call callbacks that bring us back into + // visible code. + if (!Callee || IsCalleeAnAutosynthesizedPropertyAccessor) return nullptr; SmallString<256> buf; @@ -1020,7 +1058,11 @@ PathDiagnosticCallPiece::getCallEnterWithinCallerEvent() const { std::shared_ptr<PathDiagnosticEventPiece> PathDiagnosticCallPiece::getCallExitEvent() const { - if (NoExit) + // We do not produce call enters and call exits for autosynthesized property + // accessors. We do generally produce them for other functions coming from + // the body farm because they may call callbacks that bring us back into + // visible code. + if (NoExit || IsCalleeAnAutosynthesizedPropertyAccessor) return nullptr; SmallString<256> buf; |