diff options
Diffstat (limited to 'contrib/llvm-project/clang/lib')
64 files changed, 2510 insertions, 1555 deletions
diff --git a/contrib/llvm-project/clang/lib/APINotes/APINotesManager.cpp b/contrib/llvm-project/clang/lib/APINotes/APINotesManager.cpp index a921c8b9fce3..d3aef09dac91 100644 --- a/contrib/llvm-project/clang/lib/APINotes/APINotesManager.cpp +++ b/contrib/llvm-project/clang/lib/APINotes/APINotesManager.cpp @@ -125,7 +125,7 @@ APINotesManager::loadAPINotes(StringRef Buffer) { bool APINotesManager::loadAPINotes(const DirectoryEntry *HeaderDir, FileEntryRef APINotesFile) { - assert(Readers.find(HeaderDir) == Readers.end()); + assert(!Readers.contains(HeaderDir)); if (auto Reader = loadAPINotes(APINotesFile)) { Readers[HeaderDir] = Reader.release(); return false; diff --git a/contrib/llvm-project/clang/lib/AST/ASTImporter.cpp b/contrib/llvm-project/clang/lib/AST/ASTImporter.cpp index f1f335118f37..b61180c4f349 100644 --- a/contrib/llvm-project/clang/lib/AST/ASTImporter.cpp +++ b/contrib/llvm-project/clang/lib/AST/ASTImporter.cpp @@ -2771,9 +2771,11 @@ ASTNodeImporter::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) { for (auto *FoundDecl : FoundDecls) { if (!FoundDecl->isInIdentifierNamespace(IDNS)) continue; - if (auto *FoundAlias = dyn_cast<TypeAliasTemplateDecl>(FoundDecl)) - return Importer.MapImported(D, FoundAlias); - ConflictingDecls.push_back(FoundDecl); + if (auto *FoundAlias = dyn_cast<TypeAliasTemplateDecl>(FoundDecl)) { + if (IsStructuralMatch(D, FoundAlias)) + return Importer.MapImported(D, FoundAlias); + ConflictingDecls.push_back(FoundDecl); + } } if (!ConflictingDecls.empty()) { @@ -3418,10 +3420,16 @@ static bool isAncestorDeclContextOf(const DeclContext *DC, const Stmt *S) { while (!ToProcess.empty()) { const Stmt *CurrentS = ToProcess.pop_back_val(); ToProcess.append(CurrentS->child_begin(), CurrentS->child_end()); - if (const auto *DeclRef = dyn_cast<DeclRefExpr>(CurrentS)) + if (const auto *DeclRef = dyn_cast<DeclRefExpr>(CurrentS)) { if (const Decl *D = DeclRef->getDecl()) if (isAncestorDeclContextOf(DC, D)) return true; + } else if (const auto *E = + dyn_cast_or_null<SubstNonTypeTemplateParmExpr>(CurrentS)) { + if (const Decl *D = E->getAssociatedDecl()) + if (isAncestorDeclContextOf(DC, D)) + return true; + } } return false; } @@ -7820,6 +7828,18 @@ ExpectedStmt ASTNodeImporter::VisitExplicitCastExpr(ExplicitCastExpr *E) { *ToLParenLocOrErr, OCE->getBridgeKind(), E->getCastKind(), *ToBridgeKeywordLocOrErr, ToTypeInfoAsWritten, ToSubExpr); } + case Stmt::BuiltinBitCastExprClass: { + auto *BBC = cast<BuiltinBitCastExpr>(E); + ExpectedSLoc ToKWLocOrErr = import(BBC->getBeginLoc()); + if (!ToKWLocOrErr) + return ToKWLocOrErr.takeError(); + ExpectedSLoc ToRParenLocOrErr = import(BBC->getEndLoc()); + if (!ToRParenLocOrErr) + return ToRParenLocOrErr.takeError(); + return new (Importer.getToContext()) BuiltinBitCastExpr( + ToType, E->getValueKind(), E->getCastKind(), ToSubExpr, + ToTypeInfoAsWritten, *ToKWLocOrErr, *ToRParenLocOrErr); + } default: llvm_unreachable("Cast expression of unsupported type!"); return make_error<ASTImportError>(ASTImportError::UnsupportedConstruct); @@ -9003,10 +9023,6 @@ class AttrImporter { public: AttrImporter(ASTImporter &I) : Importer(I), NImporter(I) {} - // Useful for accessing the imported attribute. - template <typename T> T *castAttrAs() { return cast<T>(ToAttr); } - template <typename T> const T *castAttrAs() const { return cast<T>(ToAttr); } - // Create an "importer" for an attribute parameter. // Result of the 'value()' of that object is to be passed to the function // 'importAttr', in the order that is expected by the attribute class. @@ -9101,6 +9117,12 @@ Expected<Attr *> ASTImporter::Import(const Attr *FromAttr) { break; } + case attr::AlignValue: { + auto *From = cast<AlignValueAttr>(FromAttr); + AI.importAttr(From, AI.importArg(From->getAlignment()).value()); + break; + } + case attr::Format: { const auto *From = cast<FormatAttr>(FromAttr); AI.importAttr(From, Import(From->getType()), From->getFormatIdx(), @@ -9214,15 +9236,6 @@ Expected<Attr *> ASTImporter::Import(const Attr *FromAttr) { From->args_size()); break; } - case attr::CountedBy: { - AI.cloneAttr(FromAttr); - const auto *CBA = cast<CountedByAttr>(FromAttr); - Expected<SourceRange> SR = Import(CBA->getCountedByFieldLoc()).get(); - if (!SR) - return SR.takeError(); - AI.castAttrAs<CountedByAttr>()->setCountedByFieldLoc(SR.get()); - break; - } default: { // The default branch works for attributes that have no arguments to import. @@ -9391,7 +9404,6 @@ Expected<Decl *> ASTImporter::Import(Decl *FromD) { setImportDeclError(FromD, *Error); return make_error<ASTImportError>(*Error); } - // Make sure that ImportImpl registered the imported decl. assert(ImportedDecls.count(FromD) != 0 && "Missing call to MapImported?"); if (auto Error = ImportAttrs(ToD, FromD)) diff --git a/contrib/llvm-project/clang/lib/AST/ASTStructuralEquivalence.cpp b/contrib/llvm-project/clang/lib/AST/ASTStructuralEquivalence.cpp index 6bb4bf14b873..1f492b051e03 100644 --- a/contrib/llvm-project/clang/lib/AST/ASTStructuralEquivalence.cpp +++ b/contrib/llvm-project/clang/lib/AST/ASTStructuralEquivalence.cpp @@ -1978,6 +1978,18 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, } static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, + TypeAliasTemplateDecl *D1, + TypeAliasTemplateDecl *D2) { + // Check template parameters. + if (!IsTemplateDeclCommonStructurallyEquivalent(Context, D1, D2)) + return false; + + // Check the templated declaration. + return IsStructurallyEquivalent(Context, D1->getTemplatedDecl(), + D2->getTemplatedDecl()); +} + +static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, ConceptDecl *D1, ConceptDecl *D2) { // Check template parameters. diff --git a/contrib/llvm-project/clang/lib/AST/Decl.cpp b/contrib/llvm-project/clang/lib/AST/Decl.cpp index 527ea6042daa..12e0a6faa4c3 100644 --- a/contrib/llvm-project/clang/lib/AST/Decl.cpp +++ b/contrib/llvm-project/clang/lib/AST/Decl.cpp @@ -1088,11 +1088,11 @@ bool NamedDecl::isPlaceholderVar(const LangOptions &LangOpts) const { return false; if (isa<FieldDecl>(this)) return true; - if (auto *IFD = dyn_cast<IndirectFieldDecl>(this)) { + if (const auto *IFD = dyn_cast<IndirectFieldDecl>(this)) { if (!getDeclContext()->isFunctionOrMethod() && !getDeclContext()->isRecord()) return false; - VarDecl *VD = IFD->getVarDecl(); + const VarDecl *VD = IFD->getVarDecl(); return !VD || VD->getStorageDuration() == SD_Automatic; } // and it declares a variable with automatic storage duration @@ -1105,7 +1105,7 @@ bool NamedDecl::isPlaceholderVar(const LangOptions &LangOpts) const { } if (const auto *BD = dyn_cast<BindingDecl>(this); BD && getDeclContext()->isFunctionOrMethod()) { - VarDecl *VD = BD->getHoldingVar(); + const VarDecl *VD = BD->getHoldingVar(); return !VD || VD->getStorageDuration() == StorageDuration::SD_Automatic; } return false; @@ -1843,7 +1843,8 @@ static bool isRedeclarable(Decl::Kind K) { llvm_unreachable("unknown decl kind"); } -bool NamedDecl::declarationReplaces(NamedDecl *OldD, bool IsKnownNewer) const { +bool NamedDecl::declarationReplaces(const NamedDecl *OldD, + bool IsKnownNewer) const { assert(getDeclName() == OldD->getDeclName() && "Declaration name mismatch"); // Never replace one imported declaration with another; we need both results @@ -1873,13 +1874,13 @@ bool NamedDecl::declarationReplaces(NamedDecl *OldD, bool IsKnownNewer) const { // Using declarations can be replaced if they import the same name from the // same context. - if (auto *UD = dyn_cast<UsingDecl>(this)) { + if (const auto *UD = dyn_cast<UsingDecl>(this)) { ASTContext &Context = getASTContext(); return Context.getCanonicalNestedNameSpecifier(UD->getQualifier()) == Context.getCanonicalNestedNameSpecifier( cast<UsingDecl>(OldD)->getQualifier()); } - if (auto *UUVD = dyn_cast<UnresolvedUsingValueDecl>(this)) { + if (const auto *UUVD = dyn_cast<UnresolvedUsingValueDecl>(this)) { ASTContext &Context = getASTContext(); return Context.getCanonicalNestedNameSpecifier(UUVD->getQualifier()) == Context.getCanonicalNestedNameSpecifier( @@ -1896,7 +1897,7 @@ bool NamedDecl::declarationReplaces(NamedDecl *OldD, bool IsKnownNewer) const { // Check whether this is actually newer than OldD. We want to keep the // newer declaration. This loop will usually only iterate once, because // OldD is usually the previous declaration. - for (auto *D : redecls()) { + for (const auto *D : redecls()) { if (D == OldD) break; @@ -2199,8 +2200,7 @@ static LanguageLinkage getDeclLanguageLinkage(const T &D) { // Language linkage is a C++ concept, but saying that everything else in C has // C language linkage fits the implementation nicely. - ASTContext &Context = D.getASTContext(); - if (!Context.getLangOpts().CPlusPlus) + if (!D.getASTContext().getLangOpts().CPlusPlus) return CLanguageLinkage; // C++ [dcl.link]p4: A C language linkage is ignored in determining the @@ -2943,7 +2943,7 @@ bool ParmVarDecl::isDestroyedInCallee() const { // FIXME: isParamDestroyedInCallee() should probably imply // isDestructedType() - auto *RT = getType()->getAs<RecordType>(); + const auto *RT = getType()->getAs<RecordType>(); if (RT && RT->getDecl()->isParamDestroyedInCallee() && getType().isDestructedType()) return true; @@ -3105,7 +3105,7 @@ FunctionDecl::getDefaultedFunctionInfo() const { } bool FunctionDecl::hasBody(const FunctionDecl *&Definition) const { - for (auto *I : redecls()) { + for (const auto *I : redecls()) { if (I->doesThisDeclarationHaveABody()) { Definition = I; return true; @@ -3116,7 +3116,7 @@ bool FunctionDecl::hasBody(const FunctionDecl *&Definition) const { } bool FunctionDecl::hasTrivialBody() const { - Stmt *S = getBody(); + const Stmt *S = getBody(); if (!S) { // Since we don't have a body for this function, we don't know if it's // trivial or not. @@ -3212,7 +3212,7 @@ void FunctionDecl::setPure(bool P) { template<std::size_t Len> static bool isNamed(const NamedDecl *ND, const char (&Str)[Len]) { - IdentifierInfo *II = ND->getIdentifier(); + const IdentifierInfo *II = ND->getIdentifier(); return II && II->isStr(Str); } @@ -3305,9 +3305,9 @@ bool FunctionDecl::isReservedGlobalPlacementOperator() const { if (proto->getNumParams() != 2 || proto->isVariadic()) return false; - ASTContext &Context = - cast<TranslationUnitDecl>(getDeclContext()->getRedeclContext()) - ->getASTContext(); + const ASTContext &Context = + cast<TranslationUnitDecl>(getDeclContext()->getRedeclContext()) + ->getASTContext(); // The result type and first argument type are constant across all // these operators. The second argument must be exactly void*. @@ -3342,7 +3342,7 @@ bool FunctionDecl::isReplaceableGlobalAllocationFunction( unsigned Params = 1; QualType Ty = FPT->getParamType(Params); - ASTContext &Ctx = getASTContext(); + const ASTContext &Ctx = getASTContext(); auto Consume = [&] { ++Params; @@ -3388,7 +3388,8 @@ bool FunctionDecl::isReplaceableGlobalAllocationFunction( QualType T = Ty; while (const auto *TD = T->getAs<TypedefType>()) T = TD->getDecl()->getUnderlyingType(); - IdentifierInfo *II = T->castAs<EnumType>()->getDecl()->getIdentifier(); + const IdentifierInfo *II = + T->castAs<EnumType>()->getDecl()->getIdentifier(); if (II && II->isStr("__hot_cold_t")) Consume(); } @@ -3586,7 +3587,7 @@ unsigned FunctionDecl::getBuiltinID(bool ConsiderWrapperFunctions) const { (!hasAttr<ArmBuiltinAliasAttr>() && !hasAttr<BuiltinAliasAttr>())) return 0; - ASTContext &Context = getASTContext(); + const ASTContext &Context = getASTContext(); if (!Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) return BuiltinID; @@ -3745,7 +3746,7 @@ bool FunctionDecl::doesDeclarationForceExternallyVisibleDefinition() const { assert(!doesThisDeclarationHaveABody() && "Must have a declaration without a body."); - ASTContext &Context = getASTContext(); + const ASTContext &Context = getASTContext(); if (Context.getLangOpts().MSVCCompat) { const FunctionDecl *Definition; diff --git a/contrib/llvm-project/clang/lib/AST/DeclBase.cpp b/contrib/llvm-project/clang/lib/AST/DeclBase.cpp index e4d7169752bc..5e03f0223d31 100644 --- a/contrib/llvm-project/clang/lib/AST/DeclBase.cpp +++ b/contrib/llvm-project/clang/lib/AST/DeclBase.cpp @@ -29,6 +29,7 @@ #include "clang/AST/Type.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/LLVM.h" +#include "clang/Basic/LangOptions.h" #include "clang/Basic/Module.h" #include "clang/Basic/ObjCRuntime.h" #include "clang/Basic/PartialDiagnostic.h" @@ -410,79 +411,6 @@ bool Decl::isFileContextDecl() const { return DC && DC->isFileContext(); } -bool Decl::isFlexibleArrayMemberLike( - ASTContext &Ctx, const Decl *D, QualType Ty, - LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel, - bool IgnoreTemplateOrMacroSubstitution) { - // For compatibility with existing code, we treat arrays of length 0 or - // 1 as flexible array members. - const auto *CAT = Ctx.getAsConstantArrayType(Ty); - if (CAT) { - using FAMKind = LangOptions::StrictFlexArraysLevelKind; - - llvm::APInt Size = CAT->getSize(); - if (StrictFlexArraysLevel == FAMKind::IncompleteOnly) - return false; - - // GCC extension, only allowed to represent a FAM. - if (Size.isZero()) - return true; - - if (StrictFlexArraysLevel == FAMKind::ZeroOrIncomplete && Size.uge(1)) - return false; - - if (StrictFlexArraysLevel == FAMKind::OneZeroOrIncomplete && Size.uge(2)) - return false; - } else if (!Ctx.getAsIncompleteArrayType(Ty)) { - return false; - } - - if (const auto *OID = dyn_cast_if_present<ObjCIvarDecl>(D)) - return OID->getNextIvar() == nullptr; - - const auto *FD = dyn_cast_if_present<FieldDecl>(D); - if (!FD) - return false; - - if (CAT) { - // GCC treats an array memeber of a union as an FAM if the size is one or - // zero. - llvm::APInt Size = CAT->getSize(); - if (FD->getParent()->isUnion() && (Size.isZero() || Size.isOne())) - return true; - } - - // Don't consider sizes resulting from macro expansions or template argument - // substitution to form C89 tail-padded arrays. - if (IgnoreTemplateOrMacroSubstitution) { - TypeSourceInfo *TInfo = FD->getTypeSourceInfo(); - while (TInfo) { - TypeLoc TL = TInfo->getTypeLoc(); - - // Look through typedefs. - if (TypedefTypeLoc TTL = TL.getAsAdjusted<TypedefTypeLoc>()) { - const TypedefNameDecl *TDL = TTL.getTypedefNameDecl(); - TInfo = TDL->getTypeSourceInfo(); - continue; - } - - if (auto CTL = TL.getAs<ConstantArrayTypeLoc>()) { - if (const Expr *SizeExpr = - dyn_cast_if_present<IntegerLiteral>(CTL.getSizeExpr()); - !SizeExpr || SizeExpr->getExprLoc().isMacroID()) - return false; - } - - break; - } - } - - // Test that the field is the last in the structure. - RecordDecl::field_iterator FI( - DeclContext::decl_iterator(const_cast<FieldDecl *>(FD))); - return ++FI == FD->getParent()->field_end(); -} - TranslationUnitDecl *Decl::getTranslationUnitDecl() { if (auto *TUD = dyn_cast<TranslationUnitDecl>(this)) return TUD; diff --git a/contrib/llvm-project/clang/lib/AST/Expr.cpp b/contrib/llvm-project/clang/lib/AST/Expr.cpp index b125fc676da8..a90f92d07f86 100644 --- a/contrib/llvm-project/clang/lib/AST/Expr.cpp +++ b/contrib/llvm-project/clang/lib/AST/Expr.cpp @@ -205,22 +205,85 @@ bool Expr::isKnownToHaveBooleanValue(bool Semantic) const { } bool Expr::isFlexibleArrayMemberLike( - ASTContext &Ctx, + ASTContext &Context, LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel, bool IgnoreTemplateOrMacroSubstitution) const { + + // For compatibility with existing code, we treat arrays of length 0 or + // 1 as flexible array members. + const auto *CAT = Context.getAsConstantArrayType(getType()); + if (CAT) { + llvm::APInt Size = CAT->getSize(); + + using FAMKind = LangOptions::StrictFlexArraysLevelKind; + + if (StrictFlexArraysLevel == FAMKind::IncompleteOnly) + return false; + + // GCC extension, only allowed to represent a FAM. + if (Size == 0) + return true; + + if (StrictFlexArraysLevel == FAMKind::ZeroOrIncomplete && Size.uge(1)) + return false; + + if (StrictFlexArraysLevel == FAMKind::OneZeroOrIncomplete && Size.uge(2)) + return false; + } else if (!Context.getAsIncompleteArrayType(getType())) + return false; + const Expr *E = IgnoreParens(); - const Decl *D = nullptr; - if (const auto *ME = dyn_cast<MemberExpr>(E)) - D = ME->getMemberDecl(); - else if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) - D = DRE->getDecl(); + const NamedDecl *ND = nullptr; + if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) + ND = DRE->getDecl(); + else if (const auto *ME = dyn_cast<MemberExpr>(E)) + ND = ME->getMemberDecl(); else if (const auto *IRE = dyn_cast<ObjCIvarRefExpr>(E)) - D = IRE->getDecl(); + return IRE->getDecl()->getNextIvar() == nullptr; + + if (!ND) + return false; - return Decl::isFlexibleArrayMemberLike(Ctx, D, E->getType(), - StrictFlexArraysLevel, - IgnoreTemplateOrMacroSubstitution); + // A flexible array member must be the last member in the class. + // FIXME: If the base type of the member expr is not FD->getParent(), + // this should not be treated as a flexible array member access. + if (const auto *FD = dyn_cast<FieldDecl>(ND)) { + // GCC treats an array memeber of a union as an FAM if the size is one or + // zero. + if (CAT) { + llvm::APInt Size = CAT->getSize(); + if (FD->getParent()->isUnion() && (Size.isZero() || Size.isOne())) + return true; + } + + // Don't consider sizes resulting from macro expansions or template argument + // substitution to form C89 tail-padded arrays. + if (IgnoreTemplateOrMacroSubstitution) { + TypeSourceInfo *TInfo = FD->getTypeSourceInfo(); + while (TInfo) { + TypeLoc TL = TInfo->getTypeLoc(); + // Look through typedefs. + if (TypedefTypeLoc TTL = TL.getAsAdjusted<TypedefTypeLoc>()) { + const TypedefNameDecl *TDL = TTL.getTypedefNameDecl(); + TInfo = TDL->getTypeSourceInfo(); + continue; + } + if (ConstantArrayTypeLoc CTL = TL.getAs<ConstantArrayTypeLoc>()) { + const Expr *SizeExpr = dyn_cast<IntegerLiteral>(CTL.getSizeExpr()); + if (!SizeExpr || SizeExpr->getExprLoc().isMacroID()) + return false; + } + break; + } + } + + RecordDecl::field_iterator FI( + DeclContext::decl_iterator(const_cast<FieldDecl *>(FD))); + return ++FI == FD->getParent()->field_end(); + } + + return false; } const ValueDecl * diff --git a/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp b/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp index b98037b73645..96fe6df88dbb 100644 --- a/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp +++ b/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp @@ -726,27 +726,70 @@ void Environment::setStorageLocation(const Expr &E, StorageLocation &Loc) { // so allow these as an exception. assert(E.isGLValue() || E.getType()->isSpecificBuiltinType(BuiltinType::BuiltinFn)); - setStorageLocationInternal(E, Loc); + const Expr &CanonE = ignoreCFGOmittedNodes(E); + assert(!ExprToLoc.contains(&CanonE)); + ExprToLoc[&CanonE] = &Loc; } StorageLocation *Environment::getStorageLocation(const Expr &E) const { // See comment in `setStorageLocation()`. assert(E.isGLValue() || E.getType()->isSpecificBuiltinType(BuiltinType::BuiltinFn)); - return getStorageLocationInternal(E); + auto It = ExprToLoc.find(&ignoreCFGOmittedNodes(E)); + return It == ExprToLoc.end() ? nullptr : &*It->second; +} + +// Returns whether a prvalue of record type is the one that originally +// constructs the object (i.e. it doesn't propagate it from one of its +// children). +static bool isOriginalRecordConstructor(const Expr &RecordPRValue) { + if (auto *Init = dyn_cast<InitListExpr>(&RecordPRValue)) + return !Init->isSemanticForm() || !Init->isTransparent(); + return isa<CXXConstructExpr>(RecordPRValue) || isa<CallExpr>(RecordPRValue) || + isa<LambdaExpr>(RecordPRValue) || + // The framework currently does not propagate the objects created in + // the two branches of a `ConditionalOperator` because there is no way + // to reconcile their storage locations, which are different. We + // therefore claim that the `ConditionalOperator` is the expression + // that originally constructs the object. + // Ultimately, this will be fixed by propagating locations down from + // the result object, rather than up from the original constructor as + // we do now (see also the FIXME in the documentation for + // `getResultObjectLocation()`). + isa<ConditionalOperator>(RecordPRValue); } RecordStorageLocation & -Environment::getResultObjectLocation(const Expr &RecordPRValue) { +Environment::getResultObjectLocation(const Expr &RecordPRValue) const { assert(RecordPRValue.getType()->isRecordType()); assert(RecordPRValue.isPRValue()); - if (StorageLocation *ExistingLoc = getStorageLocationInternal(RecordPRValue)) - return *cast<RecordStorageLocation>(ExistingLoc); - auto &Loc = cast<RecordStorageLocation>( - DACtx->getStableStorageLocation(RecordPRValue)); - setStorageLocationInternal(RecordPRValue, Loc); - return Loc; + // Returns a storage location that we can use if assertions fail. + auto FallbackForAssertFailure = + [this, &RecordPRValue]() -> RecordStorageLocation & { + return cast<RecordStorageLocation>( + DACtx->getStableStorageLocation(RecordPRValue)); + }; + + if (isOriginalRecordConstructor(RecordPRValue)) { + auto *Val = cast_or_null<RecordValue>(getValue(RecordPRValue)); + // The builtin transfer function should have created a `RecordValue` for all + // original record constructors. + assert(Val); + if (!Val) + return FallbackForAssertFailure(); + return Val->getLoc(); + } + + // Expression nodes that propagate a record prvalue should have exactly one + // child. + llvm::SmallVector<const Stmt *> children(RecordPRValue.child_begin(), + RecordPRValue.child_end()); + assert(children.size() == 1); + if (children.empty()) + return FallbackForAssertFailure(); + + return getResultObjectLocation(*cast<Expr>(children[0])); } PointerValue &Environment::getOrCreateNullPointerValue(QualType PointeeType) { @@ -760,6 +803,11 @@ void Environment::setValue(const StorageLocation &Loc, Value &Val) { } void Environment::setValue(const Expr &E, Value &Val) { + if (auto *RecordVal = dyn_cast<RecordValue>(&Val)) { + assert(isOriginalRecordConstructor(E) || + &RecordVal->getLoc() == &getResultObjectLocation(E)); + } + assert(E.isPRValue()); ExprToVal[&E] = &Val; } @@ -799,18 +847,6 @@ Value *Environment::createValue(QualType Type) { return Val; } -void Environment::setStorageLocationInternal(const Expr &E, - StorageLocation &Loc) { - const Expr &CanonE = ignoreCFGOmittedNodes(E); - assert(!ExprToLoc.contains(&CanonE)); - ExprToLoc[&CanonE] = &Loc; -} - -StorageLocation *Environment::getStorageLocationInternal(const Expr &E) const { - auto It = ExprToLoc.find(&ignoreCFGOmittedNodes(E)); - return It == ExprToLoc.end() ? nullptr : &*It->second; -} - Value *Environment::createValueUnlessSelfReferential( QualType Type, llvm::DenseSet<QualType> &Visited, int Depth, int &CreatedValuesCount) { @@ -998,7 +1034,7 @@ RecordStorageLocation *getImplicitObjectLocation(const CXXMemberCallExpr &MCE, if (ImplicitObject == nullptr) return nullptr; if (ImplicitObject->getType()->isPointerType()) { - if (auto *Val = cast_or_null<PointerValue>(Env.getValue(*ImplicitObject))) + if (auto *Val = Env.get<PointerValue>(*ImplicitObject)) return &cast<RecordStorageLocation>(Val->getPointeeLoc()); return nullptr; } @@ -1012,11 +1048,11 @@ RecordStorageLocation *getBaseObjectLocation(const MemberExpr &ME, if (Base == nullptr) return nullptr; if (ME.isArrow()) { - if (auto *Val = cast_or_null<PointerValue>(Env.getValue(*Base))) + if (auto *Val = Env.get<PointerValue>(*Base)) return &cast<RecordStorageLocation>(Val->getPointeeLoc()); return nullptr; } - return cast_or_null<RecordStorageLocation>(Env.getStorageLocation(*Base)); + return Env.get<RecordStorageLocation>(*Base); } std::vector<FieldDecl *> getFieldsForInitListExpr(const RecordDecl *RD) { @@ -1041,9 +1077,10 @@ RecordValue &refreshRecordValue(const Expr &Expr, Environment &Env) { assert(Expr.getType()->isRecordType()); if (Expr.isPRValue()) { - if (auto *ExistingVal = cast_or_null<RecordValue>(Env.getValue(Expr))) { + if (auto *ExistingVal = Env.get<RecordValue>(Expr)) { auto &NewVal = Env.create<RecordValue>(ExistingVal->getLoc()); Env.setValue(Expr, NewVal); + Env.setValue(NewVal.getLoc(), NewVal); return NewVal; } @@ -1052,8 +1089,7 @@ RecordValue &refreshRecordValue(const Expr &Expr, Environment &Env) { return NewVal; } - if (auto *Loc = - cast_or_null<RecordStorageLocation>(Env.getStorageLocation(Expr))) { + if (auto *Loc = Env.get<RecordStorageLocation>(Expr)) { auto &NewVal = Env.create<RecordValue>(*Loc); Env.setValue(*Loc, NewVal); return NewVal; diff --git a/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp b/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp index 69ac2c2b82cf..1d31b22b6d25 100644 --- a/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp +++ b/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp @@ -226,7 +226,7 @@ auto isComparisonOperatorCall(L lhs_arg_matcher, R rhs_arg_matcher) { /// Ensures that `Expr` is mapped to a `BoolValue` and returns its formula. const Formula &forceBoolValue(Environment &Env, const Expr &Expr) { - auto *Value = cast_or_null<BoolValue>(Env.getValue(Expr)); + auto *Value = Env.get<BoolValue>(Expr); if (Value != nullptr) return Value->formula(); @@ -267,7 +267,7 @@ BoolValue *getHasValue(Environment &Env, RecordStorageLocation *OptionalLoc) { if (OptionalLoc == nullptr) return nullptr; StorageLocation &HasValueLoc = locForHasValue(*OptionalLoc); - auto *HasValueVal = cast_or_null<BoolValue>(Env.getValue(HasValueLoc)); + auto *HasValueVal = Env.get<BoolValue>(HasValueLoc); if (HasValueVal == nullptr) { HasValueVal = &Env.makeAtomicBoolValue(); Env.setValue(HasValueLoc, *HasValueVal); @@ -406,7 +406,7 @@ void transferCallReturningOptional(const CallExpr *E, if (E->isPRValue()) { Loc = &State.Env.getResultObjectLocation(*E); } else { - Loc = cast_or_null<RecordStorageLocation>(State.Env.getStorageLocation(*E)); + Loc = State.Env.get<RecordStorageLocation>(*E); if (Loc == nullptr) { Loc = &cast<RecordStorageLocation>(State.Env.createStorageLocation(*E)); State.Env.setStorageLocation(*E, *Loc); @@ -449,8 +449,7 @@ BoolValue &valueOrConversionHasValue(const FunctionDecl &F, const Expr &E, // This is a constructor/assignment call for `optional<T>` with argument of // type `optional<U>` such that `T` is constructible from `U`. - auto *Loc = - cast_or_null<RecordStorageLocation>(State.Env.getStorageLocation(E)); + auto *Loc = State.Env.get<RecordStorageLocation>(E); if (auto *HasValueVal = getHasValue(State.Env, Loc)) return *HasValueVal; return State.Env.makeAtomicBoolValue(); @@ -471,8 +470,7 @@ void transferAssignment(const CXXOperatorCallExpr *E, BoolValue &HasValueVal, LatticeTransferState &State) { assert(E->getNumArgs() > 0); - if (auto *Loc = cast_or_null<RecordStorageLocation>( - State.Env.getStorageLocation(*E->getArg(0)))) { + if (auto *Loc = State.Env.get<RecordStorageLocation>(*E->getArg(0))) { createOptionalValue(*Loc, HasValueVal, State.Env); // Assign a storage location for the whole expression. @@ -534,18 +532,15 @@ void transferSwapCall(const CXXMemberCallExpr *E, const MatchFinder::MatchResult &, LatticeTransferState &State) { assert(E->getNumArgs() == 1); - auto *OtherLoc = cast_or_null<RecordStorageLocation>( - State.Env.getStorageLocation(*E->getArg(0))); + auto *OtherLoc = State.Env.get<RecordStorageLocation>(*E->getArg(0)); transferSwap(getImplicitObjectLocation(*E, State.Env), OtherLoc, State.Env); } void transferStdSwapCall(const CallExpr *E, const MatchFinder::MatchResult &, LatticeTransferState &State) { assert(E->getNumArgs() == 2); - auto *Arg0Loc = cast_or_null<RecordStorageLocation>( - State.Env.getStorageLocation(*E->getArg(0))); - auto *Arg1Loc = cast_or_null<RecordStorageLocation>( - State.Env.getStorageLocation(*E->getArg(1))); + auto *Arg0Loc = State.Env.get<RecordStorageLocation>(*E->getArg(0)); + auto *Arg1Loc = State.Env.get<RecordStorageLocation>(*E->getArg(1)); transferSwap(Arg0Loc, Arg1Loc, State.Env); } @@ -585,11 +580,9 @@ void transferOptionalAndOptionalCmp(const clang::CXXOperatorCallExpr *CmpExpr, Environment &Env = State.Env; auto &A = Env.arena(); auto *CmpValue = &forceBoolValue(Env, *CmpExpr); - auto *Arg0Loc = cast_or_null<RecordStorageLocation>( - Env.getStorageLocation(*CmpExpr->getArg(0))); + auto *Arg0Loc = Env.get<RecordStorageLocation>(*CmpExpr->getArg(0)); if (auto *LHasVal = getHasValue(Env, Arg0Loc)) { - auto *Arg1Loc = cast_or_null<RecordStorageLocation>( - Env.getStorageLocation(*CmpExpr->getArg(1))); + auto *Arg1Loc = Env.get<RecordStorageLocation>(*CmpExpr->getArg(1)); if (auto *RHasVal = getHasValue(Env, Arg1Loc)) { if (CmpExpr->getOperator() == clang::OO_ExclaimEqual) CmpValue = &A.makeNot(*CmpValue); @@ -603,7 +596,7 @@ void transferOptionalAndValueCmp(const clang::CXXOperatorCallExpr *CmpExpr, const clang::Expr *E, Environment &Env) { auto &A = Env.arena(); auto *CmpValue = &forceBoolValue(Env, *CmpExpr); - auto *Loc = cast_or_null<RecordStorageLocation>(Env.getStorageLocation(*E)); + auto *Loc = Env.get<RecordStorageLocation>(*E); if (auto *HasVal = getHasValue(Env, Loc)) { if (CmpExpr->getOperator() == clang::OO_ExclaimEqual) CmpValue = &A.makeNot(*CmpValue); @@ -616,7 +609,7 @@ void transferOptionalAndNulloptCmp(const clang::CXXOperatorCallExpr *CmpExpr, const clang::Expr *E, Environment &Env) { auto &A = Env.arena(); auto *CmpValue = &forceBoolValue(Env, *CmpExpr); - auto *Loc = cast_or_null<RecordStorageLocation>(Env.getStorageLocation(*E)); + auto *Loc = Env.get<RecordStorageLocation>(*E); if (auto *HasVal = getHasValue(Env, Loc)) { if (CmpExpr->getOperator() == clang::OO_ExclaimEqual) CmpValue = &A.makeNot(*CmpValue); diff --git a/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/RecordOps.cpp b/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/RecordOps.cpp index caaf443382b0..da4dd6dc0785 100644 --- a/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/RecordOps.cpp +++ b/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/RecordOps.cpp @@ -66,19 +66,8 @@ void clang::dataflow::copyRecord(RecordStorageLocation &Src, } } - RecordValue *SrcVal = cast_or_null<RecordValue>(Env.getValue(Src)); - RecordValue *DstVal = cast_or_null<RecordValue>(Env.getValue(Dst)); - - DstVal = &Env.create<RecordValue>(Dst); + RecordValue *DstVal = &Env.create<RecordValue>(Dst); Env.setValue(Dst, *DstVal); - - if (SrcVal == nullptr) - return; - - for (const auto &[Name, Value] : SrcVal->properties()) { - if (Value != nullptr) - DstVal->setProperty(Name, *Value); - } } bool clang::dataflow::recordsEqual(const RecordStorageLocation &Loc1, @@ -125,25 +114,5 @@ bool clang::dataflow::recordsEqual(const RecordStorageLocation &Loc1, } } - llvm::StringMap<Value *> Props1, Props2; - - if (RecordValue *Val1 = cast_or_null<RecordValue>(Env1.getValue(Loc1))) - for (const auto &[Name, Value] : Val1->properties()) - Props1[Name] = Value; - if (RecordValue *Val2 = cast_or_null<RecordValue>(Env2.getValue(Loc2))) - for (const auto &[Name, Value] : Val2->properties()) - Props2[Name] = Value; - - if (Props1.size() != Props2.size()) - return false; - - for (const auto &[Name, Value] : Props1) { - auto It = Props2.find(Name); - if (It == Props2.end()) - return false; - if (Value != It->second) - return false; - } - return true; } diff --git a/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/Transfer.cpp b/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/Transfer.cpp index bbf5f12359bc..55093c2e2cda 100644 --- a/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/Transfer.cpp +++ b/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/Transfer.cpp @@ -339,8 +339,7 @@ public: switch (S->getOpcode()) { case UO_Deref: { - const auto *SubExprVal = - cast_or_null<PointerValue>(Env.getValue(*SubExpr)); + const auto *SubExprVal = Env.get<PointerValue>(*SubExpr); if (SubExprVal == nullptr) break; @@ -467,8 +466,7 @@ public: const Expr *Arg = S->getArg(0); assert(Arg != nullptr); - auto *ArgLoc = - cast_or_null<RecordStorageLocation>(Env.getStorageLocation(*Arg)); + auto *ArgLoc = Env.get<RecordStorageLocation>(*Arg); if (ArgLoc == nullptr) return; @@ -489,7 +487,6 @@ public: if (S->getType()->isRecordType()) { auto &InitialVal = *cast<RecordValue>(Env.createValue(S->getType())); Env.setValue(*S, InitialVal); - copyRecord(InitialVal.getLoc(), Env.getResultObjectLocation(*S), Env); } transferInlineCall(S, ConstructorDecl); @@ -516,14 +513,12 @@ public: RecordStorageLocation *LocSrc = nullptr; if (Arg1->isPRValue()) { - if (auto *Val = cast_or_null<RecordValue>(Env.getValue(*Arg1))) + if (auto *Val = Env.get<RecordValue>(*Arg1)) LocSrc = &Val->getLoc(); } else { - LocSrc = - cast_or_null<RecordStorageLocation>(Env.getStorageLocation(*Arg1)); + LocSrc = Env.get<RecordStorageLocation>(*Arg1); } - auto *LocDst = - cast_or_null<RecordStorageLocation>(Env.getStorageLocation(*Arg0)); + auto *LocDst = Env.get<RecordStorageLocation>(*Arg0); if (LocSrc == nullptr || LocDst == nullptr) return; @@ -582,6 +577,14 @@ public: Env.setValue(*S, *ArgVal); } else if (const FunctionDecl *F = S->getDirectCallee()) { transferInlineCall(S, F); + + // If this call produces a prvalue of record type, make sure that we have + // a `RecordValue` for it. This is required so that + // `Environment::getResultObjectLocation()` is able to return a location + // for this `CallExpr`. + if (S->getType()->isRecordType() && S->isPRValue()) + if (Env.getValue(*S) == nullptr) + refreshRecordValue(*S, Env); } } @@ -669,7 +672,7 @@ public: auto Init = Inits[InitIdx++]; assert(Base.getType().getCanonicalType() == Init->getType().getCanonicalType()); - auto* BaseVal = cast_or_null<RecordValue>(Env.getValue(*Init)); + auto *BaseVal = Env.get<RecordValue>(*Init); if (!BaseVal) BaseVal = cast<RecordValue>(Env.createValue(Init->getType())); // Take ownership of the fields of the `RecordValue` for the base class diff --git a/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp b/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp index 8c9360235da7..faf83a8920d4 100644 --- a/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp +++ b/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp @@ -130,7 +130,7 @@ private: if (Env.getValue(Cond) == nullptr) transfer(StmtToEnv, Cond, Env); - auto *Val = cast_or_null<BoolValue>(Env.getValue(Cond)); + auto *Val = Env.get<BoolValue>(Cond); // Value merging depends on flow conditions from different environments // being mutually exclusive -- that is, they cannot both be true in their // entirety (even if they may share some clauses). So, we need *some* value diff --git a/contrib/llvm-project/clang/lib/Basic/Targets/AArch64.cpp b/contrib/llvm-project/clang/lib/Basic/Targets/AArch64.cpp index def16c032c86..3ee39133fcee 100644 --- a/contrib/llvm-project/clang/lib/Basic/Targets/AArch64.cpp +++ b/contrib/llvm-project/clang/lib/Basic/Targets/AArch64.cpp @@ -225,6 +225,7 @@ bool AArch64TargetInfo::validateBranchProtection(StringRef Spec, StringRef, BPI.SignKey = LangOptions::SignReturnAddressKeyKind::BKey; BPI.BranchTargetEnforcement = PBP.BranchTargetEnforcement; + BPI.BranchProtectionPAuthLR = PBP.BranchProtectionPAuthLR; return true; } diff --git a/contrib/llvm-project/clang/lib/Basic/Targets/ARM.cpp b/contrib/llvm-project/clang/lib/Basic/Targets/ARM.cpp index ce7e4d4639ce..6e1842fc64e5 100644 --- a/contrib/llvm-project/clang/lib/Basic/Targets/ARM.cpp +++ b/contrib/llvm-project/clang/lib/Basic/Targets/ARM.cpp @@ -419,6 +419,7 @@ bool ARMTargetInfo::validateBranchProtection(StringRef Spec, StringRef Arch, BPI.SignKey = LangOptions::SignReturnAddressKeyKind::AKey; BPI.BranchTargetEnforcement = PBP.BranchTargetEnforcement; + BPI.BranchProtectionPAuthLR = PBP.BranchProtectionPAuthLR; return true; } diff --git a/contrib/llvm-project/clang/lib/Basic/Targets/RISCV.cpp b/contrib/llvm-project/clang/lib/Basic/Targets/RISCV.cpp index 60a4e0ed69c3..685462961ee3 100644 --- a/contrib/llvm-project/clang/lib/Basic/Targets/RISCV.cpp +++ b/contrib/llvm-project/clang/lib/Basic/Targets/RISCV.cpp @@ -350,6 +350,7 @@ bool RISCVTargetInfo::hasFeature(StringRef Feature) const { .Case("riscv64", Is64Bit) .Case("32bit", !Is64Bit) .Case("64bit", Is64Bit) + .Case("experimental", HasExperimental) .Default(std::nullopt); if (Result) return *Result; @@ -382,6 +383,9 @@ bool RISCVTargetInfo::handleTargetFeatures(std::vector<std::string> &Features, FastUnalignedAccess = llvm::is_contained(Features, "+fast-unaligned-access"); + if (llvm::is_contained(Features, "+experimental")) + HasExperimental = true; + return true; } diff --git a/contrib/llvm-project/clang/lib/Basic/Targets/RISCV.h b/contrib/llvm-project/clang/lib/Basic/Targets/RISCV.h index a893cae914ce..f98c88cd45f8 100644 --- a/contrib/llvm-project/clang/lib/Basic/Targets/RISCV.h +++ b/contrib/llvm-project/clang/lib/Basic/Targets/RISCV.h @@ -31,6 +31,7 @@ protected: private: bool FastUnalignedAccess; + bool HasExperimental = false; public: RISCVTargetInfo(const llvm::Triple &Triple, const TargetOptions &) diff --git a/contrib/llvm-project/clang/lib/Basic/Version.cpp b/contrib/llvm-project/clang/lib/Basic/Version.cpp index e205da7adec1..4823f566bd77 100644 --- a/contrib/llvm-project/clang/lib/Basic/Version.cpp +++ b/contrib/llvm-project/clang/lib/Basic/Version.cpp @@ -57,6 +57,14 @@ std::string getLLVMRevision() { #endif } +std::string getClangVendor() { +#ifdef CLANG_VENDOR + return CLANG_VENDOR; +#else + return ""; +#endif +} + std::string getClangFullRepositoryVersion() { std::string buf; llvm::raw_string_ostream OS(buf); @@ -92,10 +100,7 @@ std::string getClangFullVersion() { std::string getClangToolFullVersion(StringRef ToolName) { std::string buf; llvm::raw_string_ostream OS(buf); -#ifdef CLANG_VENDOR - OS << CLANG_VENDOR; -#endif - OS << ToolName << " version " CLANG_VERSION_STRING; + OS << getClangVendor() << ToolName << " version " CLANG_VERSION_STRING; std::string repo = getClangFullRepositoryVersion(); if (!repo.empty()) { @@ -110,10 +115,7 @@ std::string getClangFullCPPVersion() { // the one we report on the command line. std::string buf; llvm::raw_string_ostream OS(buf); -#ifdef CLANG_VENDOR - OS << CLANG_VENDOR; -#endif - OS << "Clang " CLANG_VERSION_STRING; + OS << getClangVendor() << "Clang " CLANG_VERSION_STRING; std::string repo = getClangFullRepositoryVersion(); if (!repo.empty()) { diff --git a/contrib/llvm-project/clang/lib/Basic/Warnings.cpp b/contrib/llvm-project/clang/lib/Basic/Warnings.cpp index cb23d844ef8f..bab1af4f03b6 100644 --- a/contrib/llvm-project/clang/lib/Basic/Warnings.cpp +++ b/contrib/llvm-project/clang/lib/Basic/Warnings.cpp @@ -198,8 +198,7 @@ void clang::ProcessWarningOptions(DiagnosticsEngine &Diags, } } - for (unsigned i = 0, e = Opts.Remarks.size(); i != e; ++i) { - StringRef Opt = Opts.Remarks[i]; + for (StringRef Opt : Opts.Remarks) { const auto Flavor = diag::Flavor::Remark; // Check to see if this warning starts with "no-", if so, this is a diff --git a/contrib/llvm-project/clang/lib/CodeGen/BackendUtil.cpp b/contrib/llvm-project/clang/lib/CodeGen/BackendUtil.cpp index 7d16de33763a..a6142d99f3b6 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/BackendUtil.cpp +++ b/contrib/llvm-project/clang/lib/CodeGen/BackendUtil.cpp @@ -881,7 +881,7 @@ void EmitAssemblyHelper::RunOptimizationPipeline( << PluginFN << toString(PassPlugin.takeError()); } } - for (auto PassCallback : CodeGenOpts.PassBuilderCallbacks) + for (const auto &PassCallback : CodeGenOpts.PassBuilderCallbacks) PassCallback(PB); #define HANDLE_EXTENSION(Ext) \ get##Ext##PluginInfo().RegisterPassBuilderCallbacks(PB); @@ -1068,11 +1068,8 @@ void EmitAssemblyHelper::RunOptimizationPipeline( } } if (CodeGenOpts.FatLTO) { - // Set module flags, like EnableSplitLTOUnit and UnifiedLTO, since FatLTO + // Set the EnableSplitLTOUnit and UnifiedLTO module flags, since FatLTO // uses a different action than Backend_EmitBC or Backend_EmitLL. - if (!TheModule->getModuleFlag("ThinLTO")) - TheModule->addModuleFlag(llvm::Module::Error, "ThinLTO", - uint32_t(CodeGenOpts.PrepareForThinLTO)); if (!TheModule->getModuleFlag("EnableSplitLTOUnit")) TheModule->addModuleFlag(llvm::Module::Error, "EnableSplitLTOUnit", uint32_t(CodeGenOpts.EnableSplitLTOUnit)); diff --git a/contrib/llvm-project/clang/lib/CodeGen/CGBuiltin.cpp b/contrib/llvm-project/clang/lib/CodeGen/CGBuiltin.cpp index 3327866d2b96..5081062da286 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/CGBuiltin.cpp +++ b/contrib/llvm-project/clang/lib/CodeGen/CGBuiltin.cpp @@ -25,7 +25,6 @@ #include "clang/AST/Attr.h" #include "clang/AST/Decl.h" #include "clang/AST/OSLog.h" -#include "clang/AST/OperationKinds.h" #include "clang/Basic/TargetBuiltins.h" #include "clang/Basic/TargetInfo.h" #include "clang/Basic/TargetOptions.h" @@ -232,19 +231,19 @@ static Value *MakeBinaryAtomicValue( static Value *EmitNontemporalStore(CodeGenFunction &CGF, const CallExpr *E) { Value *Val = CGF.EmitScalarExpr(E->getArg(0)); - Value *Address = CGF.EmitScalarExpr(E->getArg(1)); + Address Addr = CGF.EmitPointerWithAlignment(E->getArg(1)); Val = CGF.EmitToMemory(Val, E->getArg(0)->getType()); - LValue LV = CGF.MakeNaturalAlignAddrLValue(Address, E->getArg(0)->getType()); + LValue LV = CGF.MakeAddrLValue(Addr, E->getArg(0)->getType()); LV.setNontemporal(true); CGF.EmitStoreOfScalar(Val, LV, false); return nullptr; } static Value *EmitNontemporalLoad(CodeGenFunction &CGF, const CallExpr *E) { - Value *Address = CGF.EmitScalarExpr(E->getArg(0)); + Address Addr = CGF.EmitPointerWithAlignment(E->getArg(0)); - LValue LV = CGF.MakeNaturalAlignAddrLValue(Address, E->getType()); + LValue LV = CGF.MakeAddrLValue(Addr, E->getType()); LV.setNontemporal(true); return CGF.EmitLoadOfScalar(LV, E->getExprLoc()); } @@ -819,165 +818,6 @@ CodeGenFunction::evaluateOrEmitBuiltinObjectSize(const Expr *E, unsigned Type, return ConstantInt::get(ResType, ObjectSize, /*isSigned=*/true); } -llvm::Value * -CodeGenFunction::emitFlexibleArrayMemberSize(const Expr *E, unsigned Type, - llvm::IntegerType *ResType) { - // The code generated here calculates the size of a struct with a flexible - // array member that uses the counted_by attribute. There are two instances - // we handle: - // - // struct s { - // unsigned long flags; - // int count; - // int array[] __attribute__((counted_by(count))); - // } - // - // 1) bdos of the flexible array itself: - // - // __builtin_dynamic_object_size(p->array, 1) == - // p->count * sizeof(*p->array) - // - // 2) bdos of a pointer into the flexible array: - // - // __builtin_dynamic_object_size(&p->array[42], 1) == - // (p->count - 42) * sizeof(*p->array) - // - // 2) bdos of the whole struct, including the flexible array: - // - // __builtin_dynamic_object_size(p, 1) == - // max(sizeof(struct s), - // offsetof(struct s, array) + p->count * sizeof(*p->array)) - // - ASTContext &Ctx = getContext(); - const Expr *Base = E->IgnoreParenImpCasts(); - const Expr *Idx = nullptr; - - if (const auto *UO = dyn_cast<UnaryOperator>(Base); - UO && UO->getOpcode() == UO_AddrOf) { - Expr *SubExpr = UO->getSubExpr()->IgnoreParenImpCasts(); - if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(SubExpr)) { - Base = ASE->getBase()->IgnoreParenImpCasts(); - Idx = ASE->getIdx()->IgnoreParenImpCasts(); - - if (const auto *IL = dyn_cast<IntegerLiteral>(Idx)) { - int64_t Val = IL->getValue().getSExtValue(); - if (Val < 0) - // __bdos returns 0 for negative indexes into an array in a struct. - return getDefaultBuiltinObjectSizeResult(Type, ResType); - - if (Val == 0) - // The index is 0, so we don't need to take it into account. - Idx = nullptr; - } - } else { - // Potential pointer to another element in the struct. - Base = SubExpr; - } - } - - // Get the flexible array member Decl. - const ValueDecl *FAMDecl = nullptr; - if (const auto *ME = dyn_cast<MemberExpr>(Base)) { - // Check if \p Base is referencing the FAM itself. - if (const ValueDecl *MD = ME->getMemberDecl()) { - const LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel = - getLangOpts().getStrictFlexArraysLevel(); - if (!Decl::isFlexibleArrayMemberLike( - Ctx, MD, MD->getType(), StrictFlexArraysLevel, - /*IgnoreTemplateOrMacroSubstitution=*/true)) - return nullptr; - - FAMDecl = MD; - } - } else if (const auto *DRE = dyn_cast<DeclRefExpr>(Base)) { - // Check if we're pointing to the whole struct. - QualType Ty = DRE->getDecl()->getType(); - if (Ty->isPointerType()) - Ty = Ty->getPointeeType(); - - if (const auto *RD = Ty->getAsRecordDecl()) - // Don't use the outer lexical record because the FAM might be in a - // different RecordDecl. - FAMDecl = FindFlexibleArrayMemberField(Ctx, RD); - } - - if (!FAMDecl || !FAMDecl->hasAttr<CountedByAttr>()) - // No flexible array member found or it doesn't have the "counted_by" - // attribute. - return nullptr; - - const ValueDecl *CountedByFD = FindCountedByField(Base); - if (!CountedByFD) - // Can't find the field referenced by the "counted_by" attribute. - return nullptr; - - // Build a load of the counted_by field. - bool IsSigned = CountedByFD->getType()->isSignedIntegerType(); - const Expr *CountedByExpr = BuildCountedByFieldExpr(Base, CountedByFD); - Value *CountedByInst = EmitAnyExprToTemp(CountedByExpr).getScalarVal(); - llvm::Type *CountedByTy = CountedByInst->getType(); - - // Build a load of the index and subtract it from the count. - Value *IdxInst = nullptr; - if (Idx) { - bool IdxSigned = Idx->getType()->isSignedIntegerType(); - IdxInst = EmitAnyExprToTemp(Idx).getScalarVal(); - IdxInst = IdxSigned ? Builder.CreateSExtOrTrunc(IdxInst, CountedByTy) - : Builder.CreateZExtOrTrunc(IdxInst, CountedByTy); - - // We go ahead with the calculation here. If the index turns out to be - // negative, we'll catch it at the end. - CountedByInst = - Builder.CreateSub(CountedByInst, IdxInst, "", !IsSigned, IsSigned); - } - - // Calculate how large the flexible array member is in bytes. - const ArrayType *ArrayTy = Ctx.getAsArrayType(FAMDecl->getType()); - CharUnits Size = Ctx.getTypeSizeInChars(ArrayTy->getElementType()); - llvm::Constant *ElemSize = - llvm::ConstantInt::get(CountedByTy, Size.getQuantity(), IsSigned); - Value *FAMSize = - Builder.CreateMul(CountedByInst, ElemSize, "", !IsSigned, IsSigned); - FAMSize = IsSigned ? Builder.CreateSExtOrTrunc(FAMSize, ResType) - : Builder.CreateZExtOrTrunc(FAMSize, ResType); - Value *Res = FAMSize; - - if (const auto *DRE = dyn_cast<DeclRefExpr>(Base)) { - // The whole struct is specificed in the __bdos. - const RecordDecl *OuterRD = - CountedByFD->getDeclContext()->getOuterLexicalRecordContext(); - const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(OuterRD); - - // Get the offset of the FAM. - CharUnits Offset = Ctx.toCharUnitsFromBits(Ctx.getFieldOffset(FAMDecl)); - llvm::Constant *FAMOffset = - ConstantInt::get(ResType, Offset.getQuantity(), IsSigned); - Value *OffsetAndFAMSize = - Builder.CreateAdd(FAMOffset, Res, "", !IsSigned, IsSigned); - - // Get the full size of the struct. - llvm::Constant *SizeofStruct = - ConstantInt::get(ResType, Layout.getSize().getQuantity(), IsSigned); - - // max(sizeof(struct s), - // offsetof(struct s, array) + p->count * sizeof(*p->array)) - Res = IsSigned - ? Builder.CreateBinaryIntrinsic(llvm::Intrinsic::smax, - OffsetAndFAMSize, SizeofStruct) - : Builder.CreateBinaryIntrinsic(llvm::Intrinsic::umax, - OffsetAndFAMSize, SizeofStruct); - } - - // A negative \p IdxInst or \p CountedByInst means that the index lands - // outside of the flexible array member. If that's the case, we want to - // return 0. - Value *Cmp = Builder.CreateIsNotNeg(CountedByInst); - if (IdxInst) - Cmp = Builder.CreateAnd(Builder.CreateIsNotNeg(IdxInst), Cmp); - - return Builder.CreateSelect(Cmp, Res, ConstantInt::get(ResType, 0, IsSigned)); -} - /// Returns a Value corresponding to the size of the given expression. /// This Value may be either of the following: /// - A llvm::Argument (if E is a param with the pass_object_size attribute on @@ -1010,13 +850,6 @@ CodeGenFunction::emitBuiltinObjectSize(const Expr *E, unsigned Type, } } - if (IsDynamic) { - // Emit special code for a flexible array member with the "counted_by" - // attribute. - if (Value *V = emitFlexibleArrayMemberSize(E, Type, ResType)) - return V; - } - // LLVM can't handle Type=3 appropriately, and __builtin_object_size shouldn't // evaluate E for side-effects. In either case, we shouldn't lower to // @llvm.objectsize. @@ -3214,7 +3047,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, Value *AlignmentValue = EmitScalarExpr(E->getArg(1)); ConstantInt *AlignmentCI = cast<ConstantInt>(AlignmentValue); if (AlignmentCI->getValue().ugt(llvm::Value::MaximumAlignment)) - AlignmentCI = ConstantInt::get(AlignmentCI->getType(), + AlignmentCI = ConstantInt::get(AlignmentCI->getIntegerType(), llvm::Value::MaximumAlignment); emitAlignmentAssumption(PtrValue, Ptr, @@ -10485,6 +10318,30 @@ Value *CodeGenFunction::EmitAArch64SVEBuiltinExpr(unsigned BuiltinID, return nullptr; } +static void swapCommutativeSMEOperands(unsigned BuiltinID, + SmallVectorImpl<Value *> &Ops) { + unsigned MultiVec; + switch (BuiltinID) { + default: + return; + case SME::BI__builtin_sme_svsumla_za32_s8_vg4x1: + MultiVec = 1; + break; + case SME::BI__builtin_sme_svsumla_za32_s8_vg4x2: + case SME::BI__builtin_sme_svsudot_za32_s8_vg1x2: + MultiVec = 2; + break; + case SME::BI__builtin_sme_svsudot_za32_s8_vg1x4: + case SME::BI__builtin_sme_svsumla_za32_s8_vg4x4: + MultiVec = 4; + break; + } + + if (MultiVec > 0) + for (unsigned I = 0; I < MultiVec; ++I) + std::swap(Ops[I + 1], Ops[I + 1 + MultiVec]); +} + Value *CodeGenFunction::EmitAArch64SMEBuiltinExpr(unsigned BuiltinID, const CallExpr *E) { auto *Builtin = findARMVectorIntrinsicInMap(AArch64SMEIntrinsicMap, BuiltinID, @@ -10507,6 +10364,9 @@ Value *CodeGenFunction::EmitAArch64SMEBuiltinExpr(unsigned BuiltinID, BuiltinID == SME::BI__builtin_sme_svstr_za) return EmitSMELdrStr(TypeFlags, Ops, Builtin->LLVMIntrinsic); + // Handle builtins which require their multi-vector operands to be swapped + swapCommutativeSMEOperands(BuiltinID, Ops); + // Should not happen! if (Builtin->LLVMIntrinsic == 0) return nullptr; @@ -17034,7 +16894,7 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID, Value *Op1 = EmitScalarExpr(E->getArg(1)); ConstantInt *AlignmentCI = cast<ConstantInt>(Op0); if (AlignmentCI->getValue().ugt(llvm::Value::MaximumAlignment)) - AlignmentCI = ConstantInt::get(AlignmentCI->getType(), + AlignmentCI = ConstantInt::get(AlignmentCI->getIntegerType(), llvm::Value::MaximumAlignment); emitAlignmentAssumption(Op1, E->getArg(1), @@ -17272,7 +17132,8 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID, Op0, llvm::FixedVectorType::get(ConvertType(E->getType()), 2)); if (getTarget().isLittleEndian()) - Index = ConstantInt::get(Index->getType(), 1 - Index->getZExtValue()); + Index = + ConstantInt::get(Index->getIntegerType(), 1 - Index->getZExtValue()); return Builder.CreateExtractElement(Unpacked, Index); } diff --git a/contrib/llvm-project/clang/lib/CodeGen/CGExpr.cpp b/contrib/llvm-project/clang/lib/CodeGen/CGExpr.cpp index ed9aaa28c257..3f277725d9e7 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/CGExpr.cpp +++ b/contrib/llvm-project/clang/lib/CodeGen/CGExpr.cpp @@ -30,7 +30,6 @@ #include "clang/Basic/CodeGenOptions.h" #include "clang/Basic/SourceManager.h" #include "llvm/ADT/Hashing.h" -#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Intrinsics.h" @@ -926,27 +925,16 @@ static llvm::Value *getArrayIndexingBound(CodeGenFunction &CGF, if (CE->getCastKind() == CK_ArrayToPointerDecay && !CE->getSubExpr()->isFlexibleArrayMemberLike(CGF.getContext(), StrictFlexArraysLevel)) { - CodeGenFunction::SanitizerScope SanScope(&CGF); - IndexedType = CE->getSubExpr()->getType(); const ArrayType *AT = IndexedType->castAsArrayTypeUnsafe(); if (const auto *CAT = dyn_cast<ConstantArrayType>(AT)) return CGF.Builder.getInt(CAT->getSize()); - - if (const auto *VAT = dyn_cast<VariableArrayType>(AT)) + else if (const auto *VAT = dyn_cast<VariableArrayType>(AT)) return CGF.getVLASize(VAT).NumElts; // Ignore pass_object_size here. It's not applicable on decayed pointers. } - - if (const ValueDecl *VD = CGF.FindCountedByField(Base)) { - IndexedType = Base->getType(); - const Expr *E = CGF.BuildCountedByFieldExpr(Base, VD); - return CGF.EmitAnyExprToTemp(E).getScalarVal(); - } } - CodeGenFunction::SanitizerScope SanScope(&CGF); - QualType EltTy{Base->getType()->getPointeeOrArrayElementType(), 0}; if (llvm::Value *POS = CGF.LoadPassedObjectSize(Base, EltTy)) { IndexedType = Base->getType(); @@ -956,122 +944,13 @@ static llvm::Value *getArrayIndexingBound(CodeGenFunction &CGF, return nullptr; } -const Expr * -CodeGenFunction::BuildCountedByFieldExpr(const Expr *Base, - const ValueDecl *CountedByVD) { - // Find the outer struct expr (i.e. p in p->a.b.c.d). - Expr *CountedByExpr = const_cast<Expr *>(Base)->IgnoreParenImpCasts(); - - // Work our way up the expression until we reach the DeclRefExpr. - while (!isa<DeclRefExpr>(CountedByExpr)) - if (const auto *ME = dyn_cast<MemberExpr>(CountedByExpr)) - CountedByExpr = ME->getBase()->IgnoreParenImpCasts(); - - // Add back an implicit cast to create the required pr-value. - CountedByExpr = ImplicitCastExpr::Create( - getContext(), CountedByExpr->getType(), CK_LValueToRValue, CountedByExpr, - nullptr, VK_PRValue, FPOptionsOverride()); - - if (const auto *IFD = dyn_cast<IndirectFieldDecl>(CountedByVD)) { - // The counted_by field is inside an anonymous struct / union. The - // IndirectFieldDecl has the correct order of FieldDecls to build this - // easily. (Yay!) - for (NamedDecl *ND : IFD->chain()) { - auto *VD = cast<ValueDecl>(ND); - CountedByExpr = - MemberExpr::CreateImplicit(getContext(), CountedByExpr, - CountedByExpr->getType()->isPointerType(), - VD, VD->getType(), VK_LValue, OK_Ordinary); - } - } else { - CountedByExpr = MemberExpr::CreateImplicit( - getContext(), const_cast<Expr *>(CountedByExpr), - CountedByExpr->getType()->isPointerType(), - const_cast<ValueDecl *>(CountedByVD), CountedByVD->getType(), VK_LValue, - OK_Ordinary); - } - - return CountedByExpr; -} - -const ValueDecl * -CodeGenFunction::FindFlexibleArrayMemberField(ASTContext &Ctx, - const RecordDecl *RD) { - const LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel = - getLangOpts().getStrictFlexArraysLevel(); - - for (const Decl *D : RD->decls()) { - if (const auto *VD = dyn_cast<ValueDecl>(D); - VD && Decl::isFlexibleArrayMemberLike( - Ctx, VD, VD->getType(), StrictFlexArraysLevel, - /*IgnoreTemplateOrMacroSubstitution=*/true)) - return VD; - - if (const auto *Record = dyn_cast<RecordDecl>(D)) - if (const ValueDecl *VD = FindFlexibleArrayMemberField(Ctx, Record)) - return VD; - } - - return nullptr; -} - -const ValueDecl *CodeGenFunction::FindCountedByField(const Expr *Base) { - ASTContext &Ctx = getContext(); - const RecordDecl *OuterRD = nullptr; - const FieldDecl *FD = nullptr; - - Base = Base->IgnoreParenImpCasts(); - - // Get the outer-most lexical RecordDecl. - if (const auto *DRE = dyn_cast<DeclRefExpr>(Base)) { - QualType Ty = DRE->getDecl()->getType(); - if (Ty->isPointerType()) - Ty = Ty->getPointeeType(); - - if (const auto *RD = Ty->getAsRecordDecl()) - OuterRD = RD->getOuterLexicalRecordContext(); - } else if (const auto *ME = dyn_cast<MemberExpr>(Base)) { - if (const ValueDecl *MD = ME->getMemberDecl()) { - OuterRD = MD->getDeclContext()->getOuterLexicalRecordContext(); - - const LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel = - getLangOpts().getStrictFlexArraysLevel(); - if (Decl::isFlexibleArrayMemberLike( - Ctx, MD, MD->getType(), StrictFlexArraysLevel, - /*IgnoreTemplateOrMacroSubstitution=*/true)) - // Base is referencing the FAM itself. - FD = dyn_cast<FieldDecl>(MD); - } - } - - if (!OuterRD) - return nullptr; - - if (!FD) { - const ValueDecl *VD = FindFlexibleArrayMemberField(Ctx, OuterRD); - FD = dyn_cast_if_present<FieldDecl>(VD); - if (!FD) - return nullptr; - } - - const auto *CBA = FD->getAttr<CountedByAttr>(); - if (!CBA) - return nullptr; - - DeclarationName DName(CBA->getCountedByField()); - DeclContext::lookup_result Lookup = OuterRD->lookup(DName); - - if (Lookup.empty()) - return nullptr; - - return dyn_cast<ValueDecl>(Lookup.front()); -} - void CodeGenFunction::EmitBoundsCheck(const Expr *E, const Expr *Base, llvm::Value *Index, QualType IndexType, bool Accessed) { assert(SanOpts.has(SanitizerKind::ArrayBounds) && "should not be called unless adding bounds checks"); + SanitizerScope SanScope(this); + const LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel = getLangOpts().getStrictFlexArraysLevel(); @@ -1081,8 +960,6 @@ void CodeGenFunction::EmitBoundsCheck(const Expr *E, const Expr *Base, if (!Bound) return; - SanitizerScope SanScope(this); - bool IndexSigned = IndexType->isSignedIntegerOrEnumerationType(); llvm::Value *IndexVal = Builder.CreateIntCast(Index, SizeTy, IndexSigned); llvm::Value *BoundVal = Builder.CreateIntCast(Bound, SizeTy, false); diff --git a/contrib/llvm-project/clang/lib/CodeGen/CGExprScalar.cpp b/contrib/llvm-project/clang/lib/CodeGen/CGExprScalar.cpp index 41ad2ddac30d..6adf99531e30 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/CGExprScalar.cpp +++ b/contrib/llvm-project/clang/lib/CodeGen/CGExprScalar.cpp @@ -1894,8 +1894,8 @@ Value *ScalarExprEmitter::VisitInitListExpr(InitListExpr *E) { // initializer, since LLVM optimizers generally do not want to touch // shuffles. unsigned CurIdx = 0; - bool VIsUndefShuffle = false; - llvm::Value *V = llvm::UndefValue::get(VType); + bool VIsPoisonShuffle = false; + llvm::Value *V = llvm::PoisonValue::get(VType); for (unsigned i = 0; i != NumInitElements; ++i) { Expr *IE = E->getInit(i); Value *Init = Visit(IE); @@ -1915,16 +1915,16 @@ Value *ScalarExprEmitter::VisitInitListExpr(InitListExpr *E) { llvm::ConstantInt *C = cast<llvm::ConstantInt>(EI->getIndexOperand()); Value *LHS = nullptr, *RHS = nullptr; if (CurIdx == 0) { - // insert into undef -> shuffle (src, undef) + // insert into poison -> shuffle (src, poison) // shufflemask must use an i32 Args.push_back(getAsInt32(C, CGF.Int32Ty)); Args.resize(ResElts, -1); LHS = EI->getVectorOperand(); RHS = V; - VIsUndefShuffle = true; - } else if (VIsUndefShuffle) { - // insert into undefshuffle && size match -> shuffle (v, src) + VIsPoisonShuffle = true; + } else if (VIsPoisonShuffle) { + // insert into poison shuffle && size match -> shuffle (v, src) llvm::ShuffleVectorInst *SVV = cast<llvm::ShuffleVectorInst>(V); for (unsigned j = 0; j != CurIdx; ++j) Args.push_back(getMaskElt(SVV, j, 0)); @@ -1933,7 +1933,7 @@ Value *ScalarExprEmitter::VisitInitListExpr(InitListExpr *E) { LHS = cast<llvm::ShuffleVectorInst>(V)->getOperand(0); RHS = EI->getVectorOperand(); - VIsUndefShuffle = false; + VIsPoisonShuffle = false; } if (!Args.empty()) { V = Builder.CreateShuffleVector(LHS, RHS, Args); @@ -1944,7 +1944,7 @@ Value *ScalarExprEmitter::VisitInitListExpr(InitListExpr *E) { } V = Builder.CreateInsertElement(V, Init, Builder.getInt32(CurIdx), "vecinit"); - VIsUndefShuffle = false; + VIsPoisonShuffle = false; ++CurIdx; continue; } @@ -1962,9 +1962,9 @@ Value *ScalarExprEmitter::VisitInitListExpr(InitListExpr *E) { if (OpTy->getNumElements() == ResElts) { for (unsigned j = 0; j != CurIdx; ++j) { - // If the current vector initializer is a shuffle with undef, merge + // If the current vector initializer is a shuffle with poison, merge // this shuffle directly into it. - if (VIsUndefShuffle) { + if (VIsPoisonShuffle) { Args.push_back(getMaskElt(cast<llvm::ShuffleVectorInst>(V), j, 0)); } else { Args.push_back(j); @@ -1974,7 +1974,7 @@ Value *ScalarExprEmitter::VisitInitListExpr(InitListExpr *E) { Args.push_back(getMaskElt(SVI, j, Offset)); Args.resize(ResElts, -1); - if (VIsUndefShuffle) + if (VIsPoisonShuffle) V = cast<llvm::ShuffleVectorInst>(V)->getOperand(0); Init = SVOp; @@ -1997,12 +1997,12 @@ Value *ScalarExprEmitter::VisitInitListExpr(InitListExpr *E) { Args.resize(ResElts, -1); } - // If V is undef, make sure it ends up on the RHS of the shuffle to aid + // If V is poison, make sure it ends up on the RHS of the shuffle to aid // merging subsequent shuffles into this one. if (CurIdx == 0) std::swap(V, Init); V = Builder.CreateShuffleVector(V, Init, Args, "vecinit"); - VIsUndefShuffle = isa<llvm::UndefValue>(Init); + VIsPoisonShuffle = isa<llvm::PoisonValue>(Init); CurIdx += InitElts; } diff --git a/contrib/llvm-project/clang/lib/CodeGen/CGHLSLRuntime.cpp b/contrib/llvm-project/clang/lib/CodeGen/CGHLSLRuntime.cpp index 3e8a40e7540b..e887d35198b3 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/CGHLSLRuntime.cpp +++ b/contrib/llvm-project/clang/lib/CodeGen/CGHLSLRuntime.cpp @@ -182,10 +182,8 @@ void CGHLSLRuntime::finishCodeGen() { llvm::hlsl::ResourceKind RK = Buf.IsCBuffer ? llvm::hlsl::ResourceKind::CBuffer : llvm::hlsl::ResourceKind::TBuffer; - std::string TyName = - Buf.Name.str() + (Buf.IsCBuffer ? ".cb." : ".tb.") + "ty"; - addBufferResourceAnnotation(GV, TyName, RC, RK, /*IsROV=*/false, - Buf.Binding); + addBufferResourceAnnotation(GV, RC, RK, /*IsROV=*/false, + llvm::hlsl::ElementType::Invalid, Buf.Binding); } } @@ -194,10 +192,10 @@ CGHLSLRuntime::Buffer::Buffer(const HLSLBufferDecl *D) Binding(D->getAttr<HLSLResourceBindingAttr>()) {} void CGHLSLRuntime::addBufferResourceAnnotation(llvm::GlobalVariable *GV, - llvm::StringRef TyName, llvm::hlsl::ResourceClass RC, llvm::hlsl::ResourceKind RK, bool IsROV, + llvm::hlsl::ElementType ET, BufferResBinding &Binding) { llvm::Module &M = CGM.getModule(); @@ -216,15 +214,62 @@ void CGHLSLRuntime::addBufferResourceAnnotation(llvm::GlobalVariable *GV, assert(false && "Unsupported buffer type!"); return; } - assert(ResourceMD != nullptr && "ResourceMD must have been set by the switch above."); llvm::hlsl::FrontendResource Res( - GV, TyName, RK, IsROV, Binding.Reg.value_or(UINT_MAX), Binding.Space); + GV, RK, ET, IsROV, Binding.Reg.value_or(UINT_MAX), Binding.Space); ResourceMD->addOperand(Res.getMetadata()); } +static llvm::hlsl::ElementType +calculateElementType(const ASTContext &Context, const clang::Type *ResourceTy) { + using llvm::hlsl::ElementType; + + // TODO: We may need to update this when we add things like ByteAddressBuffer + // that don't have a template parameter (or, indeed, an element type). + const auto *TST = ResourceTy->getAs<TemplateSpecializationType>(); + assert(TST && "Resource types must be template specializations"); + ArrayRef<TemplateArgument> Args = TST->template_arguments(); + assert(!Args.empty() && "Resource has no element type"); + + // At this point we have a resource with an element type, so we can assume + // that it's valid or we would have diagnosed the error earlier. + QualType ElTy = Args[0].getAsType(); + + // We should either have a basic type or a vector of a basic type. + if (const auto *VecTy = ElTy->getAs<clang::VectorType>()) + ElTy = VecTy->getElementType(); + + if (ElTy->isSignedIntegerType()) { + switch (Context.getTypeSize(ElTy)) { + case 16: + return ElementType::I16; + case 32: + return ElementType::I32; + case 64: + return ElementType::I64; + } + } else if (ElTy->isUnsignedIntegerType()) { + switch (Context.getTypeSize(ElTy)) { + case 16: + return ElementType::U16; + case 32: + return ElementType::U32; + case 64: + return ElementType::U64; + } + } else if (ElTy->isSpecificBuiltinType(BuiltinType::Half)) + return ElementType::F16; + else if (ElTy->isSpecificBuiltinType(BuiltinType::Float)) + return ElementType::F32; + else if (ElTy->isSpecificBuiltinType(BuiltinType::Double)) + return ElementType::F64; + + // TODO: We need to handle unorm/snorm float types here once we support them + llvm_unreachable("Invalid element type for resource"); +} + void CGHLSLRuntime::annotateHLSLResource(const VarDecl *D, GlobalVariable *GV) { const Type *Ty = D->getType()->getPointeeOrArrayElementType(); if (!Ty) @@ -239,10 +284,10 @@ void CGHLSLRuntime::annotateHLSLResource(const VarDecl *D, GlobalVariable *GV) { llvm::hlsl::ResourceClass RC = Attr->getResourceClass(); llvm::hlsl::ResourceKind RK = Attr->getResourceKind(); bool IsROV = Attr->getIsROV(); + llvm::hlsl::ElementType ET = calculateElementType(CGM.getContext(), Ty); - QualType QT(Ty, 0); BufferResBinding Binding(D->getAttr<HLSLResourceBindingAttr>()); - addBufferResourceAnnotation(GV, QT.getAsString(), RC, RK, IsROV, Binding); + addBufferResourceAnnotation(GV, RC, RK, IsROV, ET, Binding); } CGHLSLRuntime::BufferResBinding::BufferResBinding( diff --git a/contrib/llvm-project/clang/lib/CodeGen/CGHLSLRuntime.h b/contrib/llvm-project/clang/lib/CodeGen/CGHLSLRuntime.h index bb500cb5c979..bffefb66740a 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/CGHLSLRuntime.h +++ b/contrib/llvm-project/clang/lib/CodeGen/CGHLSLRuntime.h @@ -90,9 +90,9 @@ public: private: void addBufferResourceAnnotation(llvm::GlobalVariable *GV, - llvm::StringRef TyName, llvm::hlsl::ResourceClass RC, llvm::hlsl::ResourceKind RK, bool IsROV, + llvm::hlsl::ElementType ET, BufferResBinding &Binding); void addConstant(VarDecl *D, Buffer &CB); void addBufferDecls(const DeclContext *DC, Buffer &CB); diff --git a/contrib/llvm-project/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/contrib/llvm-project/clang/lib/CodeGen/CGOpenMPRuntime.cpp index 7f7e6f530666..ea6645a39e83 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/contrib/llvm-project/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -6811,8 +6811,10 @@ private: OpenMPMapClauseKind MapType, ArrayRef<OpenMPMapModifierKind> MapModifiers, ArrayRef<OpenMPMotionModifierKind> MotionModifiers, OMPClauseMappableExprCommon::MappableExprComponentListRef Components, - MapCombinedInfoTy &CombinedInfo, StructRangeInfoTy &PartialStruct, - bool IsFirstComponentList, bool IsImplicit, + MapCombinedInfoTy &CombinedInfo, + MapCombinedInfoTy &StructBaseCombinedInfo, + StructRangeInfoTy &PartialStruct, bool IsFirstComponentList, + bool IsImplicit, bool GenerateAllInfoForClauses, const ValueDecl *Mapper = nullptr, bool ForDeviceAddr = false, const ValueDecl *BaseDecl = nullptr, const Expr *MapExpr = nullptr, ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef> @@ -7098,6 +7100,25 @@ private: bool IsNonContiguous = CombinedInfo.NonContigInfo.IsNonContiguous; bool IsPrevMemberReference = false; + // We need to check if we will be encountering any MEs. If we do not + // encounter any ME expression it means we will be mapping the whole struct. + // In that case we need to skip adding an entry for the struct to the + // CombinedInfo list and instead add an entry to the StructBaseCombinedInfo + // list only when generating all info for clauses. + bool IsMappingWholeStruct = true; + if (!GenerateAllInfoForClauses) { + IsMappingWholeStruct = false; + } else { + for (auto TempI = I; TempI != CE; ++TempI) { + const MemberExpr *PossibleME = + dyn_cast<MemberExpr>(TempI->getAssociatedExpression()); + if (PossibleME) { + IsMappingWholeStruct = false; + break; + } + } + } + for (; I != CE; ++I) { // If the current component is member of a struct (parent struct) mark it. if (!EncounteredME) { @@ -7317,21 +7338,41 @@ private: break; } llvm::Value *Size = getExprTypeSize(I->getAssociatedExpression()); + // Skip adding an entry in the CurInfo of this combined entry if the + // whole struct is currently being mapped. The struct needs to be added + // in the first position before any data internal to the struct is being + // mapped. if (!IsMemberPointerOrAddr || (Next == CE && MapType != OMPC_MAP_unknown)) { - CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr); - CombinedInfo.BasePointers.push_back(BP.getPointer()); - CombinedInfo.DevicePtrDecls.push_back(nullptr); - CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None); - CombinedInfo.Pointers.push_back(LB.getPointer()); - CombinedInfo.Sizes.push_back( - CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true)); - CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize - : 1); + if (!IsMappingWholeStruct) { + CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr); + CombinedInfo.BasePointers.push_back(BP.getPointer()); + CombinedInfo.DevicePtrDecls.push_back(nullptr); + CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None); + CombinedInfo.Pointers.push_back(LB.getPointer()); + CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast( + Size, CGF.Int64Ty, /*isSigned=*/true)); + CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize + : 1); + } else { + StructBaseCombinedInfo.Exprs.emplace_back(MapDecl, MapExpr); + StructBaseCombinedInfo.BasePointers.push_back(BP.getPointer()); + StructBaseCombinedInfo.DevicePtrDecls.push_back(nullptr); + StructBaseCombinedInfo.DevicePointers.push_back(DeviceInfoTy::None); + StructBaseCombinedInfo.Pointers.push_back(LB.getPointer()); + StructBaseCombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast( + Size, CGF.Int64Ty, /*isSigned=*/true)); + StructBaseCombinedInfo.NonContigInfo.Dims.push_back( + IsNonContiguous ? DimSize : 1); + } // If Mapper is valid, the last component inherits the mapper. bool HasMapper = Mapper && Next == CE; - CombinedInfo.Mappers.push_back(HasMapper ? Mapper : nullptr); + if (!IsMappingWholeStruct) + CombinedInfo.Mappers.push_back(HasMapper ? Mapper : nullptr); + else + StructBaseCombinedInfo.Mappers.push_back(HasMapper ? Mapper + : nullptr); // We need to add a pointer flag for each map that comes from the // same expression except for the first one. We also need to signal @@ -7363,7 +7404,10 @@ private: } } - CombinedInfo.Types.push_back(Flags); + if (!IsMappingWholeStruct) + CombinedInfo.Types.push_back(Flags); + else + StructBaseCombinedInfo.Types.push_back(Flags); } // If we have encountered a member expression so far, keep track of the @@ -7954,8 +7998,10 @@ private: for (const auto &Data : Info) { StructRangeInfoTy PartialStruct; - // Temporary generated information. + // Current struct information: MapCombinedInfoTy CurInfo; + // Current struct base information: + MapCombinedInfoTy StructBaseCurInfo; const Decl *D = Data.first; const ValueDecl *VD = cast_or_null<ValueDecl>(D); for (const auto &M : Data.second) { @@ -7965,29 +8011,55 @@ private: // Remember the current base pointer index. unsigned CurrentBasePointersIdx = CurInfo.BasePointers.size(); + unsigned StructBasePointersIdx = + StructBaseCurInfo.BasePointers.size(); CurInfo.NonContigInfo.IsNonContiguous = L.Components.back().isNonContiguous(); generateInfoForComponentList( L.MapType, L.MapModifiers, L.MotionModifiers, L.Components, - CurInfo, PartialStruct, /*IsFirstComponentList=*/false, - L.IsImplicit, L.Mapper, L.ForDeviceAddr, VD, L.VarRef); + CurInfo, StructBaseCurInfo, PartialStruct, + /*IsFirstComponentList=*/false, L.IsImplicit, + /*GenerateAllInfoForClauses*/ true, L.Mapper, L.ForDeviceAddr, VD, + L.VarRef); - // If this entry relates with a device pointer, set the relevant + // If this entry relates to a device pointer, set the relevant // declaration and add the 'return pointer' flag. if (L.ReturnDevicePointer) { - assert(CurInfo.BasePointers.size() > CurrentBasePointersIdx && + // Check whether a value was added to either CurInfo or + // StructBaseCurInfo and error if no value was added to either of + // them: + assert((CurrentBasePointersIdx < CurInfo.BasePointers.size() || + StructBasePointersIdx < + StructBaseCurInfo.BasePointers.size()) && "Unexpected number of mapped base pointers."); + // Choose a base pointer index which is always valid: const ValueDecl *RelevantVD = L.Components.back().getAssociatedDeclaration(); assert(RelevantVD && "No relevant declaration related with device pointer??"); - CurInfo.DevicePtrDecls[CurrentBasePointersIdx] = RelevantVD; - CurInfo.DevicePointers[CurrentBasePointersIdx] = - L.ForDeviceAddr ? DeviceInfoTy::Address : DeviceInfoTy::Pointer; - CurInfo.Types[CurrentBasePointersIdx] |= - OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM; + // If StructBaseCurInfo has been updated this iteration then work on + // the first new entry added to it i.e. make sure that when multiple + // values are added to any of the lists, the first value added is + // being modified by the assignments below (not the last value + // added). + if (StructBasePointersIdx < StructBaseCurInfo.BasePointers.size()) { + StructBaseCurInfo.DevicePtrDecls[StructBasePointersIdx] = + RelevantVD; + StructBaseCurInfo.DevicePointers[StructBasePointersIdx] = + L.ForDeviceAddr ? DeviceInfoTy::Address + : DeviceInfoTy::Pointer; + StructBaseCurInfo.Types[StructBasePointersIdx] |= + OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM; + } else { + CurInfo.DevicePtrDecls[CurrentBasePointersIdx] = RelevantVD; + CurInfo.DevicePointers[CurrentBasePointersIdx] = + L.ForDeviceAddr ? DeviceInfoTy::Address + : DeviceInfoTy::Pointer; + CurInfo.Types[CurrentBasePointersIdx] |= + OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM; + } } } } @@ -8034,17 +8106,24 @@ private: CurInfo.Mappers.push_back(nullptr); } } + + // Unify entries in one list making sure the struct mapping precedes the + // individual fields: + MapCombinedInfoTy UnionCurInfo; + UnionCurInfo.append(StructBaseCurInfo); + UnionCurInfo.append(CurInfo); + // If there is an entry in PartialStruct it means we have a struct with // individual members mapped. Emit an extra combined entry. if (PartialStruct.Base.isValid()) { - CurInfo.NonContigInfo.Dims.push_back(0); - emitCombinedEntry(CombinedInfo, CurInfo.Types, PartialStruct, + UnionCurInfo.NonContigInfo.Dims.push_back(0); + // Emit a combined entry: + emitCombinedEntry(CombinedInfo, UnionCurInfo.Types, PartialStruct, /*IsMapThis*/ !VD, OMPBuilder, VD); } - // We need to append the results of this capture to what we already - // have. - CombinedInfo.append(CurInfo); + // We need to append the results of this capture to what we already have. + CombinedInfo.append(UnionCurInfo); } // Append data for use_device_ptr clauses. CombinedInfo.append(UseDeviceDataCombinedInfo); @@ -8554,6 +8633,7 @@ public: // Associated with a capture, because the mapping flags depend on it. // Go through all of the elements with the overlapped elements. bool IsFirstComponentList = true; + MapCombinedInfoTy StructBaseCombinedInfo; for (const auto &Pair : OverlappedData) { const MapData &L = *Pair.getFirst(); OMPClauseMappableExprCommon::MappableExprComponentListRef Components; @@ -8568,7 +8648,8 @@ public: OverlappedComponents = Pair.getSecond(); generateInfoForComponentList( MapType, MapModifiers, std::nullopt, Components, CombinedInfo, - PartialStruct, IsFirstComponentList, IsImplicit, Mapper, + StructBaseCombinedInfo, PartialStruct, IsFirstComponentList, + IsImplicit, /*GenerateAllInfoForClauses*/ false, Mapper, /*ForDeviceAddr=*/false, VD, VarRef, OverlappedComponents); IsFirstComponentList = false; } @@ -8584,10 +8665,11 @@ public: L; auto It = OverlappedData.find(&L); if (It == OverlappedData.end()) - generateInfoForComponentList(MapType, MapModifiers, std::nullopt, - Components, CombinedInfo, PartialStruct, - IsFirstComponentList, IsImplicit, Mapper, - /*ForDeviceAddr=*/false, VD, VarRef); + generateInfoForComponentList( + MapType, MapModifiers, std::nullopt, Components, CombinedInfo, + StructBaseCombinedInfo, PartialStruct, IsFirstComponentList, + IsImplicit, /*GenerateAllInfoForClauses*/ false, Mapper, + /*ForDeviceAddr=*/false, VD, VarRef); IsFirstComponentList = false; } } diff --git a/contrib/llvm-project/clang/lib/CodeGen/CodeGenFunction.h b/contrib/llvm-project/clang/lib/CodeGen/CodeGenFunction.h index 618e78809db4..751d8110b13d 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/CodeGenFunction.h +++ b/contrib/llvm-project/clang/lib/CodeGen/CodeGenFunction.h @@ -3022,19 +3022,6 @@ public: void EmitBoundsCheck(const Expr *E, const Expr *Base, llvm::Value *Index, QualType IndexType, bool Accessed); - // Find a struct's flexible array member. It may be embedded inside multiple - // sub-structs, but must still be the last field. - const ValueDecl *FindFlexibleArrayMemberField(ASTContext &Ctx, - const RecordDecl *RD); - - /// Find the FieldDecl specified in a FAM's "counted_by" attribute. Returns - /// \p nullptr if either the attribute or the field doesn't exist. - const ValueDecl *FindCountedByField(const Expr *Base); - - /// Build an expression accessing the "counted_by" field. - const Expr *BuildCountedByFieldExpr(const Expr *Base, - const ValueDecl *CountedByVD); - llvm::Value *EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, bool isInc, bool isPre); ComplexPairTy EmitComplexPrePostIncDec(const UnaryOperator *E, LValue LV, @@ -4830,9 +4817,6 @@ private: llvm::Value *EmittedE, bool IsDynamic); - llvm::Value *emitFlexibleArrayMemberSize(const Expr *E, unsigned Type, - llvm::IntegerType *ResType); - void emitZeroOrPatternForAutoVarInit(QualType type, const VarDecl &D, Address Loc); diff --git a/contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp b/contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp index 7ad26ace328a..d78f2594a237 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp +++ b/contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp @@ -995,12 +995,7 @@ void CodeGenModule::Release() { uint32_t(CLANG_VERSION_MINOR)); getModule().addModuleFlag(llvm::Module::Warning, "zos_product_patchlevel", uint32_t(CLANG_VERSION_PATCHLEVEL)); - std::string ProductId; -#ifdef CLANG_VENDOR - ProductId = #CLANG_VENDOR; -#else - ProductId = "clang"; -#endif + std::string ProductId = getClangVendor() + "clang"; getModule().addModuleFlag(llvm::Module::Error, "zos_product_id", llvm::MDString::get(VMContext, ProductId)); @@ -1111,6 +1106,9 @@ void CodeGenModule::Release() { if (LangOpts.BranchTargetEnforcement) getModule().addModuleFlag(llvm::Module::Min, "branch-target-enforcement", 1); + if (LangOpts.BranchProtectionPAuthLR) + getModule().addModuleFlag(llvm::Module::Min, "branch-protection-pauth-lr", + 1); if (LangOpts.hasSignReturnAddress()) getModule().addModuleFlag(llvm::Module::Min, "sign-return-address", 1); if (LangOpts.isSignReturnAddressScopeAll()) diff --git a/contrib/llvm-project/clang/lib/CodeGen/Targets/AArch64.cpp b/contrib/llvm-project/clang/lib/CodeGen/Targets/AArch64.cpp index be5145daa00b..7102d190fe00 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/Targets/AArch64.cpp +++ b/contrib/llvm-project/clang/lib/CodeGen/Targets/AArch64.cpp @@ -136,6 +136,8 @@ public: Fn->addFnAttr("branch-target-enforcement", BPI.BranchTargetEnforcement ? "true" : "false"); + Fn->addFnAttr("branch-protection-pauth-lr", + BPI.BranchProtectionPAuthLR ? "true" : "false"); } bool isScalarizableAsmOperand(CodeGen::CodeGenFunction &CGF, diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/AIX.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/AIX.cpp index f9670ea6f251..e6126ff62db3 100644 --- a/contrib/llvm-project/clang/lib/Driver/ToolChains/AIX.cpp +++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/AIX.cpp @@ -328,6 +328,12 @@ void aix::Linker::ConstructJob(Compilation &C, const JobAction &JA, } } + if (D.IsFlangMode()) { + addFortranRuntimeLibraryPath(ToolChain, Args, CmdArgs); + addFortranRuntimeLibs(ToolChain, Args, CmdArgs); + CmdArgs.push_back("-lm"); + CmdArgs.push_back("-lpthread"); + } const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(), Exec, CmdArgs, Inputs, Output)); diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/RISCV.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/RISCV.cpp index 2e39fc29a931..80c0f88105d1 100644 --- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/RISCV.cpp +++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/RISCV.cpp @@ -45,6 +45,10 @@ static bool getArchFeatures(const Driver &D, StringRef Arch, (*ISAInfo)->toFeatures( Features, [&Args](const Twine &Str) { return Args.MakeArgString(Str); }, /*AddAllExtensions=*/true); + + if (EnableExperimentalExtensions) + Features.push_back(Args.MakeArgString("+experimental")); + return true; } diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Clang.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/Clang.cpp index de9fd5eaa1e0..70dc7e54aca1 100644 --- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Clang.cpp +++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Clang.cpp @@ -1497,7 +1497,7 @@ static void CollectARMPACBTIOptions(const ToolChain &TC, const ArgList &Args, << Triple.getArchName(); StringRef Scope, Key; - bool IndirectBranches; + bool IndirectBranches, BranchProtectionPAuthLR; if (A->getOption().matches(options::OPT_msign_return_address_EQ)) { Scope = A->getValue(); @@ -1506,6 +1506,7 @@ static void CollectARMPACBTIOptions(const ToolChain &TC, const ArgList &Args, << A->getSpelling() << Scope; Key = "a_key"; IndirectBranches = false; + BranchProtectionPAuthLR = false; } else { StringRef DiagMsg; llvm::ARM::ParsedBranchProtection PBP; @@ -1517,6 +1518,7 @@ static void CollectARMPACBTIOptions(const ToolChain &TC, const ArgList &Args, << "b-key" << A->getAsString(Args); Scope = PBP.Scope; Key = PBP.Key; + BranchProtectionPAuthLR = PBP.BranchProtectionPAuthLR; IndirectBranches = PBP.BranchTargetEnforcement; } @@ -1525,6 +1527,9 @@ static void CollectARMPACBTIOptions(const ToolChain &TC, const ArgList &Args, if (!Scope.equals("none")) CmdArgs.push_back( Args.MakeArgString(Twine("-msign-return-address-key=") + Key)); + if (BranchProtectionPAuthLR) + CmdArgs.push_back( + Args.MakeArgString(Twine("-mbranch-protection-pauth-lr"))); if (IndirectBranches) CmdArgs.push_back("-mbranch-target-enforce"); } @@ -3198,13 +3203,13 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D, options::OPT_fstrict_float_cast_overflow, false)) CmdArgs.push_back("-fno-strict-float-cast-overflow"); - if (const Arg *A = Args.getLastArg(options::OPT_fcx_limited_range)) + if (Args.hasArg(options::OPT_fcx_limited_range)) CmdArgs.push_back("-fcx-limited-range"); - if (const Arg *A = Args.getLastArg(options::OPT_fcx_fortran_rules)) + if (Args.hasArg(options::OPT_fcx_fortran_rules)) CmdArgs.push_back("-fcx-fortran-rules"); - if (const Arg *A = Args.getLastArg(options::OPT_fno_cx_limited_range)) + if (Args.hasArg(options::OPT_fno_cx_limited_range)) CmdArgs.push_back("-fno-cx-limited-range"); - if (const Arg *A = Args.getLastArg(options::OPT_fno_cx_fortran_rules)) + if (Args.hasArg(options::OPT_fno_cx_fortran_rules)) CmdArgs.push_back("-fno-cx-fortran-rules"); } diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/CommonArgs.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/CommonArgs.cpp index 45901ee7157f..6eb0ed8f3fed 100644 --- a/contrib/llvm-project/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -1174,8 +1174,9 @@ static void addFortranMain(const ToolChain &TC, const ArgList &Args, // The --whole-archive option needs to be part of the link line to make // sure that the main() function from Fortran_main.a is pulled in by the // linker. However, it shouldn't be used if it's already active. - // TODO: Find an equivalent of `--whole-archive` for Darwin. - if (!isWholeArchivePresent(Args) && !TC.getTriple().isMacOSX()) { + // TODO: Find an equivalent of `--whole-archive` for Darwin and AIX. + if (!isWholeArchivePresent(Args) && !TC.getTriple().isMacOSX() && + !TC.getTriple().isOSAIX()) { CmdArgs.push_back("--whole-archive"); CmdArgs.push_back("-lFortran_main"); CmdArgs.push_back("--no-whole-archive"); @@ -1317,28 +1318,28 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args, const SanitizerArgs &SanArgs = TC.getSanitizerArgs(Args); // Collect shared runtimes. if (SanArgs.needsSharedRt()) { - if (SanArgs.needsAsanRt() && SanArgs.linkRuntimes()) { + if (SanArgs.needsAsanRt()) { SharedRuntimes.push_back("asan"); if (!Args.hasArg(options::OPT_shared) && !TC.getTriple().isAndroid()) HelperStaticRuntimes.push_back("asan-preinit"); } - if (SanArgs.needsMemProfRt() && SanArgs.linkRuntimes()) { + if (SanArgs.needsMemProfRt()) { SharedRuntimes.push_back("memprof"); if (!Args.hasArg(options::OPT_shared) && !TC.getTriple().isAndroid()) HelperStaticRuntimes.push_back("memprof-preinit"); } - if (SanArgs.needsUbsanRt() && SanArgs.linkRuntimes()) { + if (SanArgs.needsUbsanRt()) { if (SanArgs.requiresMinimalRuntime()) SharedRuntimes.push_back("ubsan_minimal"); else SharedRuntimes.push_back("ubsan_standalone"); } - if (SanArgs.needsScudoRt() && SanArgs.linkRuntimes()) { + if (SanArgs.needsScudoRt()) { SharedRuntimes.push_back("scudo_standalone"); } - if (SanArgs.needsTsanRt() && SanArgs.linkRuntimes()) + if (SanArgs.needsTsanRt()) SharedRuntimes.push_back("tsan"); - if (SanArgs.needsHwasanRt() && SanArgs.linkRuntimes()) { + if (SanArgs.needsHwasanRt()) { if (SanArgs.needsHwasanAliasesRt()) SharedRuntimes.push_back("hwasan_aliases"); else @@ -1349,7 +1350,7 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args, } // The stats_client library is also statically linked into DSOs. - if (SanArgs.needsStatsRt() && SanArgs.linkRuntimes()) + if (SanArgs.needsStatsRt()) StaticRuntimes.push_back("stats_client"); // Always link the static runtime regardless of DSO or executable. @@ -1365,20 +1366,19 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args, // Each static runtime that has a DSO counterpart above is excluded below, // but runtimes that exist only as static are not affected by needsSharedRt. - if (!SanArgs.needsSharedRt() && SanArgs.needsAsanRt() && SanArgs.linkRuntimes()) { + if (!SanArgs.needsSharedRt() && SanArgs.needsAsanRt()) { StaticRuntimes.push_back("asan"); if (SanArgs.linkCXXRuntimes()) StaticRuntimes.push_back("asan_cxx"); } - if (!SanArgs.needsSharedRt() && SanArgs.needsMemProfRt() && - SanArgs.linkRuntimes()) { + if (!SanArgs.needsSharedRt() && SanArgs.needsMemProfRt()) { StaticRuntimes.push_back("memprof"); if (SanArgs.linkCXXRuntimes()) StaticRuntimes.push_back("memprof_cxx"); } - if (!SanArgs.needsSharedRt() && SanArgs.needsHwasanRt() && SanArgs.linkRuntimes()) { + if (!SanArgs.needsSharedRt() && SanArgs.needsHwasanRt()) { if (SanArgs.needsHwasanAliasesRt()) { StaticRuntimes.push_back("hwasan_aliases"); if (SanArgs.linkCXXRuntimes()) @@ -1389,22 +1389,21 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args, StaticRuntimes.push_back("hwasan_cxx"); } } - if (SanArgs.needsDfsanRt() && SanArgs.linkRuntimes()) + if (SanArgs.needsDfsanRt()) StaticRuntimes.push_back("dfsan"); - if (SanArgs.needsLsanRt() && SanArgs.linkRuntimes()) + if (SanArgs.needsLsanRt()) StaticRuntimes.push_back("lsan"); - if (SanArgs.needsMsanRt() && SanArgs.linkRuntimes()) { + if (SanArgs.needsMsanRt()) { StaticRuntimes.push_back("msan"); if (SanArgs.linkCXXRuntimes()) StaticRuntimes.push_back("msan_cxx"); } - if (!SanArgs.needsSharedRt() && SanArgs.needsTsanRt() && - SanArgs.linkRuntimes()) { + if (!SanArgs.needsSharedRt() && SanArgs.needsTsanRt()) { StaticRuntimes.push_back("tsan"); if (SanArgs.linkCXXRuntimes()) StaticRuntimes.push_back("tsan_cxx"); } - if (!SanArgs.needsSharedRt() && SanArgs.needsUbsanRt() && SanArgs.linkRuntimes()) { + if (!SanArgs.needsSharedRt() && SanArgs.needsUbsanRt()) { if (SanArgs.requiresMinimalRuntime()) { StaticRuntimes.push_back("ubsan_minimal"); } else { @@ -1413,24 +1412,24 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args, StaticRuntimes.push_back("ubsan_standalone_cxx"); } } - if (SanArgs.needsSafeStackRt() && SanArgs.linkRuntimes()) { + if (SanArgs.needsSafeStackRt()) { NonWholeStaticRuntimes.push_back("safestack"); RequiredSymbols.push_back("__safestack_init"); } - if (!(SanArgs.needsSharedRt() && SanArgs.needsUbsanRt() && SanArgs.linkRuntimes())) { - if (SanArgs.needsCfiRt() && SanArgs.linkRuntimes()) + if (!(SanArgs.needsSharedRt() && SanArgs.needsUbsanRt())) { + if (SanArgs.needsCfiRt()) StaticRuntimes.push_back("cfi"); - if (SanArgs.needsCfiDiagRt() && SanArgs.linkRuntimes()) { + if (SanArgs.needsCfiDiagRt()) { StaticRuntimes.push_back("cfi_diag"); if (SanArgs.linkCXXRuntimes()) StaticRuntimes.push_back("ubsan_standalone_cxx"); } } - if (SanArgs.needsStatsRt() && SanArgs.linkRuntimes()) { + if (SanArgs.needsStatsRt()) { NonWholeStaticRuntimes.push_back("stats"); RequiredSymbols.push_back("__sanitizer_stats_register"); } - if (!SanArgs.needsSharedRt() && SanArgs.needsScudoRt() && SanArgs.linkRuntimes()) { + if (!SanArgs.needsSharedRt() && SanArgs.needsScudoRt()) { StaticRuntimes.push_back("scudo_standalone"); if (SanArgs.linkCXXRuntimes()) StaticRuntimes.push_back("scudo_standalone_cxx"); @@ -1441,13 +1440,15 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args, // C runtime, etc). Returns true if sanitizer system deps need to be linked in. bool tools::addSanitizerRuntimes(const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs) { + const SanitizerArgs &SanArgs = TC.getSanitizerArgs(Args); SmallVector<StringRef, 4> SharedRuntimes, StaticRuntimes, NonWholeStaticRuntimes, HelperStaticRuntimes, RequiredSymbols; - collectSanitizerRuntimes(TC, Args, SharedRuntimes, StaticRuntimes, - NonWholeStaticRuntimes, HelperStaticRuntimes, - RequiredSymbols); + if (SanArgs.linkRuntimes()) { + collectSanitizerRuntimes(TC, Args, SharedRuntimes, StaticRuntimes, + NonWholeStaticRuntimes, HelperStaticRuntimes, + RequiredSymbols); + } - const SanitizerArgs &SanArgs = TC.getSanitizerArgs(Args); // Inject libfuzzer dependencies. if (SanArgs.needsFuzzer() && SanArgs.linkRuntimes() && !Args.hasArg(options::OPT_shared)) { diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Gnu.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/Gnu.cpp index 835215a83c40..38361d6889a1 100644 --- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Gnu.cpp +++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Gnu.cpp @@ -30,6 +30,7 @@ #include "llvm/Option/ArgList.h" #include "llvm/Support/CodeGen.h" #include "llvm/Support/Path.h" +#include "llvm/Support/RISCVISAInfo.h" #include "llvm/Support/VirtualFileSystem.h" #include "llvm/TargetParser/TargetParser.h" #include <system_error> @@ -1715,6 +1716,129 @@ static void findCSKYMultilibs(const Driver &D, const llvm::Triple &TargetTriple, Result.Multilibs = CSKYMultilibs; } +/// Extend the multi-lib re-use selection mechanism for RISC-V. +/// This function will try to re-use multi-lib if they are compatible. +/// Definition of compatible: +/// - ABI must be the same. +/// - multi-lib is a subset of current arch, e.g. multi-lib=march=rv32im +/// is a subset of march=rv32imc. +/// - march that contains atomic extension can't reuse multi-lib that +/// doesn't have atomic, vice versa. e.g. multi-lib=march=rv32im and +/// march=rv32ima are not compatible, because software and hardware +/// atomic operation can't work together correctly. +static bool +selectRISCVMultilib(const MultilibSet &RISCVMultilibSet, StringRef Arch, + const Multilib::flags_list &Flags, + llvm::SmallVectorImpl<Multilib> &SelectedMultilibs) { + // Try to find the perfect matching multi-lib first. + if (RISCVMultilibSet.select(Flags, SelectedMultilibs)) + return true; + + Multilib::flags_list NewFlags; + std::vector<MultilibBuilder> NewMultilibs; + + llvm::Expected<std::unique_ptr<llvm::RISCVISAInfo>> ParseResult = + llvm::RISCVISAInfo::parseArchString( + Arch, /*EnableExperimentalExtension=*/true, + /*ExperimentalExtensionVersionCheck=*/false); + if (!ParseResult) { + // Ignore any error here, we assume it will be handled in another place. + consumeError(ParseResult.takeError()); + return false; + } + + auto &ISAInfo = *ParseResult; + + addMultilibFlag(ISAInfo->getXLen() == 32, "-m32", NewFlags); + addMultilibFlag(ISAInfo->getXLen() == 64, "-m64", NewFlags); + + // Collect all flags except march=* + for (StringRef Flag : Flags) { + if (Flag.starts_with("!march=") || Flag.starts_with("-march=")) + continue; + + NewFlags.push_back(Flag.str()); + } + + llvm::StringSet<> AllArchExts; + // Reconstruct multi-lib list, and break march option into separated + // extension. e.g. march=rv32im -> +i +m + for (const auto &M : RISCVMultilibSet) { + bool Skip = false; + + MultilibBuilder NewMultilib = + MultilibBuilder(M.gccSuffix(), M.osSuffix(), M.includeSuffix()); + for (StringRef Flag : M.flags()) { + // Add back all flags except -march. + if (!Flag.consume_front("-march=")) { + NewMultilib.flag(Flag); + continue; + } + + // Break down -march into individual extension. + llvm::Expected<std::unique_ptr<llvm::RISCVISAInfo>> MLConfigParseResult = + llvm::RISCVISAInfo::parseArchString( + Flag, /*EnableExperimentalExtension=*/true, + /*ExperimentalExtensionVersionCheck=*/false); + if (!MLConfigParseResult) { + // Ignore any error here, we assume it will handled in another place. + llvm::consumeError(MLConfigParseResult.takeError()); + + // We might get a parsing error if rv32e in the list, we could just skip + // that and process the rest of multi-lib configs. + Skip = true; + continue; + } + auto &MLConfigISAInfo = *MLConfigParseResult; + + const llvm::RISCVISAInfo::OrderedExtensionMap &MLConfigArchExts = + MLConfigISAInfo->getExtensions(); + for (auto MLConfigArchExt : MLConfigArchExts) { + auto ExtName = MLConfigArchExt.first; + NewMultilib.flag(Twine("-", ExtName).str()); + + if (AllArchExts.insert(ExtName).second) { + addMultilibFlag(ISAInfo->hasExtension(ExtName), + Twine("-", ExtName).str(), NewFlags); + } + } + + // Check the XLEN explicitly. + if (MLConfigISAInfo->getXLen() == 32) { + NewMultilib.flag("-m32"); + NewMultilib.flag("-m64", /*Disallow*/ true); + } else { + NewMultilib.flag("-m32", /*Disallow*/ true); + NewMultilib.flag("-m64"); + } + + // Atomic extension must be explicitly checked, soft and hard atomic + // operation never co-work correctly. + if (!MLConfigISAInfo->hasExtension("a")) + NewMultilib.flag("-a", /*Disallow*/ true); + } + + if (Skip) + continue; + + NewMultilibs.emplace_back(NewMultilib); + } + + // Build an internal used only multi-lib list, used for checking any + // compatible multi-lib. + MultilibSet NewRISCVMultilibs = + MultilibSetBuilder().Either(NewMultilibs).makeMultilibSet(); + + if (NewRISCVMultilibs.select(NewFlags, SelectedMultilibs)) + for (const Multilib &NewSelectedM : SelectedMultilibs) + for (const auto &M : RISCVMultilibSet) + // Look up the corresponding multi-lib entry in original multi-lib set. + if (M.gccSuffix() == NewSelectedM.gccSuffix()) + return true; + + return false; +} + static void findRISCVBareMetalMultilibs(const Driver &D, const llvm::Triple &TargetTriple, StringRef Path, const ArgList &Args, @@ -1766,7 +1890,8 @@ static void findRISCVBareMetalMultilibs(const Driver &D, } } - if (RISCVMultilibs.select(Flags, Result.SelectedMultilibs)) + if (selectRISCVMultilib(RISCVMultilibs, MArch, Flags, + Result.SelectedMultilibs)) Result.Multilibs = RISCVMultilibs; } diff --git a/contrib/llvm-project/clang/lib/Format/ContinuationIndenter.cpp b/contrib/llvm-project/clang/lib/Format/ContinuationIndenter.cpp index bd319f21b05f..8489a30dd34a 100644 --- a/contrib/llvm-project/clang/lib/Format/ContinuationIndenter.cpp +++ b/contrib/llvm-project/clang/lib/Format/ContinuationIndenter.cpp @@ -583,17 +583,15 @@ bool ContinuationIndenter::mustBreak(const LineState &State) { return true; } - // If the return type spans multiple lines, wrap before the function name. - if (((Current.is(TT_FunctionDeclarationName) && - !State.Line->ReturnTypeWrapped && - // Don't break before a C# function when no break after return type. - (!Style.isCSharp() || - Style.AlwaysBreakAfterReturnType != FormatStyle::RTBS_None) && - // Don't always break between a JavaScript `function` and the function - // name. - !Style.isJavaScript()) || - (Current.is(tok::kw_operator) && Previous.isNot(tok::coloncolon))) && - Previous.isNot(tok::kw_template) && CurrentState.BreakBeforeParameter) { + if (Current.is(TT_FunctionDeclarationName) && + !State.Line->ReturnTypeWrapped && + // Don't break before a C# function when no break after return type. + (!Style.isCSharp() || + Style.AlwaysBreakAfterReturnType != FormatStyle::RTBS_None) && + // Don't always break between a JavaScript `function` and the function + // name. + !Style.isJavaScript() && Previous.isNot(tok::kw_template) && + CurrentState.BreakBeforeParameter) { return true; } diff --git a/contrib/llvm-project/clang/lib/Format/Format.cpp b/contrib/llvm-project/clang/lib/Format/Format.cpp index 668e959a9416..f798d555bf99 100644 --- a/contrib/llvm-project/clang/lib/Format/Format.cpp +++ b/contrib/llvm-project/clang/lib/Format/Format.cpp @@ -1315,7 +1315,6 @@ static void expandPresetsBraceWrapping(FormatStyle &Expanded) { Expanded.BraceWrapping.AfterStruct = true; Expanded.BraceWrapping.AfterUnion = true; Expanded.BraceWrapping.AfterExternBlock = true; - Expanded.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock; Expanded.BraceWrapping.SplitEmptyFunction = true; Expanded.BraceWrapping.SplitEmptyRecord = false; break; @@ -1335,7 +1334,6 @@ static void expandPresetsBraceWrapping(FormatStyle &Expanded) { Expanded.BraceWrapping.AfterStruct = true; Expanded.BraceWrapping.AfterUnion = true; Expanded.BraceWrapping.AfterExternBlock = true; - Expanded.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock; Expanded.BraceWrapping.BeforeCatch = true; Expanded.BraceWrapping.BeforeElse = true; Expanded.BraceWrapping.BeforeLambdaBody = true; @@ -1350,7 +1348,6 @@ static void expandPresetsBraceWrapping(FormatStyle &Expanded) { Expanded.BraceWrapping.AfterObjCDeclaration = true; Expanded.BraceWrapping.AfterStruct = true; Expanded.BraceWrapping.AfterExternBlock = true; - Expanded.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock; Expanded.BraceWrapping.BeforeCatch = true; Expanded.BraceWrapping.BeforeElse = true; Expanded.BraceWrapping.BeforeLambdaBody = true; @@ -1375,7 +1372,6 @@ static void expandPresetsBraceWrapping(FormatStyle &Expanded) { /*SplitEmptyFunction=*/true, /*SplitEmptyRecord=*/true, /*SplitEmptyNamespace=*/true}; - Expanded.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock; break; case FormatStyle::BS_WebKit: Expanded.BraceWrapping.AfterFunction = true; @@ -1702,6 +1698,9 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) { /*BasedOnStyle=*/"google", }, }; + GoogleStyle.AttributeMacros.push_back("GUARDED_BY"); + GoogleStyle.AttributeMacros.push_back("ABSL_GUARDED_BY"); + GoogleStyle.SpacesBeforeTrailingComments = 2; GoogleStyle.Standard = FormatStyle::LS_Auto; @@ -1909,7 +1908,6 @@ FormatStyle getMicrosoftStyle(FormatStyle::LanguageKind Language) { Style.BraceWrapping.AfterObjCDeclaration = true; Style.BraceWrapping.AfterStruct = true; Style.BraceWrapping.AfterExternBlock = true; - Style.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock; Style.BraceWrapping.BeforeCatch = true; Style.BraceWrapping.BeforeElse = true; Style.BraceWrapping.BeforeWhile = false; diff --git a/contrib/llvm-project/clang/lib/Format/MatchFilePath.cpp b/contrib/llvm-project/clang/lib/Format/MatchFilePath.cpp new file mode 100644 index 000000000000..412ee4954587 --- /dev/null +++ b/contrib/llvm-project/clang/lib/Format/MatchFilePath.cpp @@ -0,0 +1,122 @@ +//===--- MatchFilePath.cpp - Match file path with pattern -------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file implements the functionality of matching a file path name to +/// a pattern, similar to the POSIX fnmatch() function. +/// +//===----------------------------------------------------------------------===// + +#include "MatchFilePath.h" + +using namespace llvm; + +namespace clang { +namespace format { + +// Check whether `FilePath` matches `Pattern` based on POSIX (1003.1-2008) +// 2.13.1, 2.13.2, and Rule 1 of 2.13.3. +bool matchFilePath(StringRef Pattern, StringRef FilePath) { + assert(!Pattern.empty()); + assert(!FilePath.empty()); + + // No match if `Pattern` ends with a non-meta character not equal to the last + // character of `FilePath`. + if (const auto C = Pattern.back(); !strchr("?*]", C) && C != FilePath.back()) + return false; + + constexpr auto Separator = '/'; + const auto EOP = Pattern.size(); // End of `Pattern`. + const auto End = FilePath.size(); // End of `FilePath`. + unsigned I = 0; // Index to `Pattern`. + + for (unsigned J = 0; J < End; ++J) { + if (I == EOP) + return false; + + switch (const auto F = FilePath[J]; Pattern[I]) { + case '\\': + if (++I == EOP || F != Pattern[I]) + return false; + break; + case '?': + if (F == Separator) + return false; + break; + case '*': { + while (++I < EOP && Pattern[I] == '*') { // Skip consecutive stars. + } + const auto K = FilePath.find(Separator, J); // Index of next `Separator`. + const bool NoMoreSeparatorsInFilePath = K == StringRef::npos; + if (I == EOP) // `Pattern` ends with a star. + return NoMoreSeparatorsInFilePath; + // `Pattern` ends with a lone backslash. + if (Pattern[I] == '\\' && ++I == EOP) + return false; + // The star is followed by a (possibly escaped) `Separator`. + if (Pattern[I] == Separator) { + if (NoMoreSeparatorsInFilePath) + return false; + J = K; // Skip to next `Separator` in `FilePath`. + break; + } + // Recurse. + for (auto Pat = Pattern.substr(I); J < End && FilePath[J] != Separator; + ++J) { + if (matchFilePath(Pat, FilePath.substr(J))) + return true; + } + return false; + } + case '[': + // Skip e.g. `[!]`. + if (I + 3 < EOP || (I + 3 == EOP && Pattern[I + 1] != '!')) { + // Skip unpaired `[`, brackets containing slashes, and `[]`. + if (const auto K = Pattern.find_first_of("]/", I + 1); + K != StringRef::npos && Pattern[K] == ']' && K > I + 1) { + if (F == Separator) + return false; + ++I; // After the `[`. + bool Negated = false; + if (Pattern[I] == '!') { + Negated = true; + ++I; // After the `!`. + } + bool Match = false; + do { + if (I + 2 < K && Pattern[I + 1] == '-') { + Match = Pattern[I] <= F && F <= Pattern[I + 2]; + I += 3; // After the range, e.g. `A-Z`. + } else { + Match = F == Pattern[I++]; + } + } while (!Match && I < K); + if (Negated ? Match : !Match) + return false; + I = K + 1; // After the `]`. + continue; + } + } + [[fallthrough]]; // Match `[` literally. + default: + if (F != Pattern[I]) + return false; + } + + ++I; + } + + // Match trailing stars with null strings. + while (I < EOP && Pattern[I] == '*') + ++I; + + return I == EOP; +} + +} // namespace format +} // namespace clang diff --git a/contrib/llvm-project/clang/lib/Format/MatchFilePath.h b/contrib/llvm-project/clang/lib/Format/MatchFilePath.h new file mode 100644 index 000000000000..482dab7c748e --- /dev/null +++ b/contrib/llvm-project/clang/lib/Format/MatchFilePath.h @@ -0,0 +1,22 @@ +//===--- MatchFilePath.h ----------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LIB_FORMAT_MATCHFILEPATH_H +#define LLVM_CLANG_LIB_FORMAT_MATCHFILEPATH_H + +#include "llvm/ADT/StringRef.h" + +namespace clang { +namespace format { + +bool matchFilePath(llvm::StringRef Pattern, llvm::StringRef FilePath); + +} // end namespace format +} // end namespace clang + +#endif diff --git a/contrib/llvm-project/clang/lib/Format/TokenAnnotator.cpp b/contrib/llvm-project/clang/lib/Format/TokenAnnotator.cpp index f3551af34243..3ac3aa3c5e3a 100644 --- a/contrib/llvm-project/clang/lib/Format/TokenAnnotator.cpp +++ b/contrib/llvm-project/clang/lib/Format/TokenAnnotator.cpp @@ -3403,7 +3403,8 @@ static bool isFunctionDeclarationName(bool IsCpp, const FormatToken &Current, continue; } if (Tok->is(tok::kw_const) || Tok->isSimpleTypeSpecifier() || - Tok->isOneOf(TT_PointerOrReference, TT_StartOfName, tok::ellipsis)) { + Tok->isOneOf(TT_PointerOrReference, TT_StartOfName, tok::ellipsis, + TT_TypeName)) { return true; } if (Tok->isOneOf(tok::l_brace, TT_ObjCMethodExpr) || Tok->Tok.isLiteral()) diff --git a/contrib/llvm-project/clang/lib/Format/UnwrappedLineParser.cpp b/contrib/llvm-project/clang/lib/Format/UnwrappedLineParser.cpp index c38b4c884070..684609747a55 100644 --- a/contrib/llvm-project/clang/lib/Format/UnwrappedLineParser.cpp +++ b/contrib/llvm-project/clang/lib/Format/UnwrappedLineParser.cpp @@ -1650,8 +1650,10 @@ void UnwrappedLineParser::parseStructuralElement( return; } // In Verilog labels can be any expression, so we don't do them here. - if (!Style.isVerilog() && Tokens->peekNextToken()->is(tok::colon) && - !Line->MustBeDeclaration) { + // JS doesn't have macros, and within classes colons indicate fields, not + // labels. + if (!Style.isJavaScript() && !Style.isVerilog() && + Tokens->peekNextToken()->is(tok::colon) && !Line->MustBeDeclaration) { nextToken(); Line->Tokens.begin()->Tok->MustBreakBefore = true; FormatTok->setFinalizedType(TT_GotoLabelColon); diff --git a/contrib/llvm-project/clang/lib/Headers/adcintrin.h b/contrib/llvm-project/clang/lib/Headers/adcintrin.h new file mode 100644 index 000000000000..0065a1b543f8 --- /dev/null +++ b/contrib/llvm-project/clang/lib/Headers/adcintrin.h @@ -0,0 +1,160 @@ +/*===---- adcintrin.h - ADC intrinsics -------------------------------------=== + * + * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. + * See https://llvm.org/LICENSE.txt for license information. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + * + *===-----------------------------------------------------------------------=== + */ + +#ifndef __ADCINTRIN_H +#define __ADCINTRIN_H + +#if !defined(__i386__) && !defined(__x86_64__) +#error "This header is only meant to be used on x86 and x64 architecture" +#endif + +/* Define the default attributes for the functions in this file. */ +#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__)) + +/* Use C++ inline semantics in C++, GNU inline for C mode. */ +#if defined(__cplusplus) +#define __INLINE __inline +#else +#define __INLINE static __inline +#endif + +#if defined(__cplusplus) +extern "C" { +#endif + +/// Adds unsigned 32-bit integers \a __x and \a __y, plus 0 or 1 as indicated +/// by the carry flag \a __cf. Stores the unsigned 32-bit sum in the memory +/// at \a __p, and returns the 8-bit carry-out (carry flag). +/// +/// \code{.operation} +/// temp := (__cf == 0) ? 0 : 1 +/// Store32(__p, __x + __y + temp) +/// result := CF +/// \endcode +/// +/// \headerfile <immintrin.h> +/// +/// This intrinsic corresponds to the \c ADC instruction. +/// +/// \param __cf +/// The 8-bit unsigned carry flag; any non-zero value indicates carry. +/// \param __x +/// A 32-bit unsigned addend. +/// \param __y +/// A 32-bit unsigned addend. +/// \param __p +/// Pointer to memory for storing the sum. +/// \returns The 8-bit unsigned carry-out value. +__INLINE unsigned char __DEFAULT_FN_ATTRS _addcarry_u32(unsigned char __cf, + unsigned int __x, + unsigned int __y, + unsigned int *__p) { + return __builtin_ia32_addcarryx_u32(__cf, __x, __y, __p); +} + +/// Adds unsigned 32-bit integer \a __y to 0 or 1 as indicated by the carry +/// flag \a __cf, and subtracts the result from unsigned 32-bit integer +/// \a __x. Stores the unsigned 32-bit difference in the memory at \a __p, +/// and returns the 8-bit carry-out (carry or overflow flag). +/// +/// \code{.operation} +/// temp := (__cf == 0) ? 0 : 1 +/// Store32(__p, __x - (__y + temp)) +/// result := CF +/// \endcode +/// +/// \headerfile <immintrin.h> +/// +/// This intrinsic corresponds to the \c SBB instruction. +/// +/// \param __cf +/// The 8-bit unsigned carry flag; any non-zero value indicates carry. +/// \param __x +/// The 32-bit unsigned minuend. +/// \param __y +/// The 32-bit unsigned subtrahend. +/// \param __p +/// Pointer to memory for storing the difference. +/// \returns The 8-bit unsigned carry-out value. +__INLINE unsigned char __DEFAULT_FN_ATTRS _subborrow_u32(unsigned char __cf, + unsigned int __x, + unsigned int __y, + unsigned int *__p) { + return __builtin_ia32_subborrow_u32(__cf, __x, __y, __p); +} + +#ifdef __x86_64__ +/// Adds unsigned 64-bit integers \a __x and \a __y, plus 0 or 1 as indicated +/// by the carry flag \a __cf. Stores the unsigned 64-bit sum in the memory +/// at \a __p, and returns the 8-bit carry-out (carry flag). +/// +/// \code{.operation} +/// temp := (__cf == 0) ? 0 : 1 +/// Store64(__p, __x + __y + temp) +/// result := CF +/// \endcode +/// +/// \headerfile <immintrin.h> +/// +/// This intrinsic corresponds to the \c ADC instruction. +/// +/// \param __cf +/// The 8-bit unsigned carry flag; any non-zero value indicates carry. +/// \param __x +/// A 64-bit unsigned addend. +/// \param __y +/// A 64-bit unsigned addend. +/// \param __p +/// Pointer to memory for storing the sum. +/// \returns The 8-bit unsigned carry-out value. +__INLINE unsigned char __DEFAULT_FN_ATTRS +_addcarry_u64(unsigned char __cf, unsigned long long __x, + unsigned long long __y, unsigned long long *__p) { + return __builtin_ia32_addcarryx_u64(__cf, __x, __y, __p); +} + +/// Adds unsigned 64-bit integer \a __y to 0 or 1 as indicated by the carry +/// flag \a __cf, and subtracts the result from unsigned 64-bit integer +/// \a __x. Stores the unsigned 64-bit difference in the memory at \a __p, +/// and returns the 8-bit carry-out (carry or overflow flag). +/// +/// \code{.operation} +/// temp := (__cf == 0) ? 0 : 1 +/// Store64(__p, __x - (__y + temp)) +/// result := CF +/// \endcode +/// +/// \headerfile <immintrin.h> +/// +/// This intrinsic corresponds to the \c ADC instruction. +/// +/// \param __cf +/// The 8-bit unsigned carry flag; any non-zero value indicates carry. +/// \param __x +/// The 64-bit unsigned minuend. +/// \param __y +/// The 64-bit unsigned subtrahend. +/// \param __p +/// Pointer to memory for storing the difference. +/// \returns The 8-bit unsigned carry-out value. +__INLINE unsigned char __DEFAULT_FN_ATTRS +_subborrow_u64(unsigned char __cf, unsigned long long __x, + unsigned long long __y, unsigned long long *__p) { + return __builtin_ia32_subborrow_u64(__cf, __x, __y, __p); +} +#endif + +#if defined(__cplusplus) +} +#endif + +#undef __INLINE +#undef __DEFAULT_FN_ATTRS + +#endif /* __ADCINTRIN_H */ diff --git a/contrib/llvm-project/clang/lib/Headers/adxintrin.h b/contrib/llvm-project/clang/lib/Headers/adxintrin.h index 20f6211e567b..bc6a4caf3533 100644 --- a/contrib/llvm-project/clang/lib/Headers/adxintrin.h +++ b/contrib/llvm-project/clang/lib/Headers/adxintrin.h @@ -15,7 +15,8 @@ #define __ADXINTRIN_H /* Define the default attributes for the functions in this file. */ -#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__)) +#define __DEFAULT_FN_ATTRS \ + __attribute__((__always_inline__, __nodebug__, __target__("adx"))) /* Use C++ inline semantics in C++, GNU inline for C mode. */ #if defined(__cplusplus) @@ -53,10 +54,10 @@ extern "C" { /// \param __p /// Pointer to memory for storing the sum. /// \returns The 8-bit unsigned carry-out value. -__INLINE unsigned char - __attribute__((__always_inline__, __nodebug__, __target__("adx"))) - _addcarryx_u32(unsigned char __cf, unsigned int __x, unsigned int __y, - unsigned int *__p) { +__INLINE unsigned char __DEFAULT_FN_ATTRS _addcarryx_u32(unsigned char __cf, + unsigned int __x, + unsigned int __y, + unsigned int *__p) { return __builtin_ia32_addcarryx_u32(__cf, __x, __y, __p); } @@ -84,137 +85,10 @@ __INLINE unsigned char /// \param __p /// Pointer to memory for storing the sum. /// \returns The 8-bit unsigned carry-out value. -__INLINE unsigned char - __attribute__((__always_inline__, __nodebug__, __target__("adx"))) - _addcarryx_u64(unsigned char __cf, unsigned long long __x, - unsigned long long __y, unsigned long long *__p) { - return __builtin_ia32_addcarryx_u64(__cf, __x, __y, __p); -} -#endif - -/* Intrinsics that are also available if __ADX__ is undefined. */ - -/// Adds unsigned 32-bit integers \a __x and \a __y, plus 0 or 1 as indicated -/// by the carry flag \a __cf. Stores the unsigned 32-bit sum in the memory -/// at \a __p, and returns the 8-bit carry-out (carry flag). -/// -/// \code{.operation} -/// temp := (__cf == 0) ? 0 : 1 -/// Store32(__p, __x + __y + temp) -/// result := CF -/// \endcode -/// -/// \headerfile <immintrin.h> -/// -/// This intrinsic corresponds to the \c ADC instruction. -/// -/// \param __cf -/// The 8-bit unsigned carry flag; any non-zero value indicates carry. -/// \param __x -/// A 32-bit unsigned addend. -/// \param __y -/// A 32-bit unsigned addend. -/// \param __p -/// Pointer to memory for storing the sum. -/// \returns The 8-bit unsigned carry-out value. -__INLINE unsigned char __DEFAULT_FN_ATTRS _addcarry_u32(unsigned char __cf, - unsigned int __x, - unsigned int __y, - unsigned int *__p) { - return __builtin_ia32_addcarryx_u32(__cf, __x, __y, __p); -} - -#ifdef __x86_64__ -/// Adds unsigned 64-bit integers \a __x and \a __y, plus 0 or 1 as indicated -/// by the carry flag \a __cf. Stores the unsigned 64-bit sum in the memory -/// at \a __p, and returns the 8-bit carry-out (carry flag). -/// -/// \code{.operation} -/// temp := (__cf == 0) ? 0 : 1 -/// Store64(__p, __x + __y + temp) -/// result := CF -/// \endcode -/// -/// \headerfile <immintrin.h> -/// -/// This intrinsic corresponds to the \c ADC instruction. -/// -/// \param __cf -/// The 8-bit unsigned carry flag; any non-zero value indicates carry. -/// \param __x -/// A 64-bit unsigned addend. -/// \param __y -/// A 64-bit unsigned addend. -/// \param __p -/// Pointer to memory for storing the sum. -/// \returns The 8-bit unsigned carry-out value. __INLINE unsigned char __DEFAULT_FN_ATTRS -_addcarry_u64(unsigned char __cf, unsigned long long __x, - unsigned long long __y, unsigned long long *__p) { - return __builtin_ia32_addcarryx_u64(__cf, __x, __y, __p); -} -#endif - -/// Adds unsigned 32-bit integer \a __y to 0 or 1 as indicated by the carry -/// flag \a __cf, and subtracts the result from unsigned 32-bit integer -/// \a __x. Stores the unsigned 32-bit difference in the memory at \a __p, -/// and returns the 8-bit carry-out (carry or overflow flag). -/// -/// \code{.operation} -/// temp := (__cf == 0) ? 0 : 1 -/// Store32(__p, __x - (__y + temp)) -/// result := CF -/// \endcode -/// -/// \headerfile <immintrin.h> -/// -/// This intrinsic corresponds to the \c SBB instruction. -/// -/// \param __cf -/// The 8-bit unsigned carry flag; any non-zero value indicates carry. -/// \param __x -/// The 32-bit unsigned minuend. -/// \param __y -/// The 32-bit unsigned subtrahend. -/// \param __p -/// Pointer to memory for storing the difference. -/// \returns The 8-bit unsigned carry-out value. -__INLINE unsigned char __DEFAULT_FN_ATTRS _subborrow_u32(unsigned char __cf, - unsigned int __x, - unsigned int __y, - unsigned int *__p) { - return __builtin_ia32_subborrow_u32(__cf, __x, __y, __p); -} - -#ifdef __x86_64__ -/// Adds unsigned 64-bit integer \a __y to 0 or 1 as indicated by the carry -/// flag \a __cf, and subtracts the result from unsigned 64-bit integer -/// \a __x. Stores the unsigned 64-bit difference in the memory at \a __p, -/// and returns the 8-bit carry-out (carry or overflow flag). -/// -/// \code{.operation} -/// temp := (__cf == 0) ? 0 : 1 -/// Store64(__p, __x - (__y + temp)) -/// result := CF -/// \endcode -/// -/// \headerfile <immintrin.h> -/// -/// This intrinsic corresponds to the \c ADC instruction. -/// -/// \param __cf -/// The 8-bit unsigned carry flag; any non-zero value indicates carry. -/// \param __x -/// The 64-bit unsigned minuend. -/// \param __y -/// The 64-bit unsigned subtrahend. -/// \param __p -/// Pointer to memory for storing the difference. -/// \returns The 8-bit unsigned carry-out value. -__INLINE unsigned char __DEFAULT_FN_ATTRS -_subborrow_u64(unsigned char __cf, unsigned long long __x, +_addcarryx_u64(unsigned char __cf, unsigned long long __x, unsigned long long __y, unsigned long long *__p) { - return __builtin_ia32_subborrow_u64(__cf, __x, __y, __p); + return __builtin_ia32_addcarryx_u64(__cf, __x, __y, __p); } #endif @@ -222,6 +96,7 @@ _subborrow_u64(unsigned char __cf, unsigned long long __x, } #endif +#undef __INLINE #undef __DEFAULT_FN_ATTRS #endif /* __ADXINTRIN_H */ diff --git a/contrib/llvm-project/clang/lib/Headers/immintrin.h b/contrib/llvm-project/clang/lib/Headers/immintrin.h index 9bfe2fcdabdb..0149a1cdea63 100644 --- a/contrib/llvm-project/clang/lib/Headers/immintrin.h +++ b/contrib/llvm-project/clang/lib/Headers/immintrin.h @@ -580,9 +580,13 @@ _storebe_i64(void * __P, long long __D) { #include <cetintrin.h> #endif -/* Some intrinsics inside adxintrin.h are available only on processors with ADX, - * whereas others are also available at all times. */ +/* Intrinsics inside adcintrin.h are available at all times. */ +#include <adcintrin.h> + +#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ + defined(__ADX__) #include <adxintrin.h> +#endif #if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ defined(__RDSEED__) diff --git a/contrib/llvm-project/clang/lib/Headers/riscv_bitmanip.h b/contrib/llvm-project/clang/lib/Headers/riscv_bitmanip.h index 1a81cc8618c9..2bc7ee022a96 100644 --- a/contrib/llvm-project/clang/lib/Headers/riscv_bitmanip.h +++ b/contrib/llvm-project/clang/lib/Headers/riscv_bitmanip.h @@ -34,7 +34,7 @@ __riscv_ctz_32(uint32_t __x) { static __inline__ unsigned __attribute__((__always_inline__, __nodebug__)) __riscv_cpop_32(uint32_t __x) { - return __builtin_riscv_cpop_32(__x); + return __builtin_popcount(__x); } #if __riscv_xlen == 64 @@ -55,7 +55,7 @@ __riscv_ctz_64(uint64_t __x) { static __inline__ unsigned __attribute__((__always_inline__, __nodebug__)) __riscv_cpop_64(uint64_t __x) { - return __builtin_riscv_cpop_64(__x); + return __builtin_popcountll(__x); } #endif #endif // defined(__riscv_zbb) @@ -120,7 +120,23 @@ __riscv_zip_32(uint32_t __x) { #endif #endif // defined(__riscv_zbkb) -#if defined(__riscv_zbkc) +#if defined(__riscv_zbc) +#if __riscv_xlen == 32 +static __inline__ uint32_t __attribute__((__always_inline__, __nodebug__)) +__riscv_clmulr_32(uint32_t __x, uint32_t __y) { + return __builtin_riscv_clmulr_32(__x, __y); +} +#endif + +#if __riscv_xlen == 64 +static __inline__ uint64_t __attribute__((__always_inline__, __nodebug__)) +__riscv_clmulr_64(uint64_t __x, uint64_t __y) { + return __builtin_riscv_clmulr_64(__x, __y); +} +#endif +#endif // defined(__riscv_zbc) + +#if defined(__riscv_zbkc) || defined(__riscv_zbc) static __inline__ uint32_t __attribute__((__always_inline__, __nodebug__)) __riscv_clmul_32(uint32_t __x, uint32_t __y) { return __builtin_riscv_clmul_32(__x, __y); @@ -144,7 +160,7 @@ __riscv_clmulh_64(uint64_t __x, uint64_t __y) { return __builtin_riscv_clmulh_64(__x, __y); } #endif -#endif // defined(__riscv_zbkc) +#endif // defined(__riscv_zbkc) || defined(__riscv_zbc) #if defined(__riscv_zbkx) #if __riscv_xlen == 32 diff --git a/contrib/llvm-project/clang/lib/Interpreter/CodeCompletion.cpp b/contrib/llvm-project/clang/lib/Interpreter/CodeCompletion.cpp index c40e11b9d1ec..25183ae9eeb9 100644 --- a/contrib/llvm-project/clang/lib/Interpreter/CodeCompletion.cpp +++ b/contrib/llvm-project/clang/lib/Interpreter/CodeCompletion.cpp @@ -12,6 +12,7 @@ #include "clang/Interpreter/CodeCompletion.h" #include "clang/AST/ASTImporter.h" +#include "clang/AST/DeclLookups.h" #include "clang/AST/DeclarationName.h" #include "clang/AST/ExternalASTSource.h" #include "clang/Basic/IdentifierTable.h" @@ -23,6 +24,8 @@ #include "clang/Sema/CodeCompleteConsumer.h" #include "clang/Sema/CodeCompleteOptions.h" #include "clang/Sema/Sema.h" +#include "llvm/Support/Debug.h" +#define DEBUG_TYPE "REPLCC" namespace clang { @@ -39,11 +42,15 @@ clang::CodeCompleteOptions getClangCompleteOpts() { class ReplCompletionConsumer : public CodeCompleteConsumer { public: - ReplCompletionConsumer(std::vector<std::string> &Results) + ReplCompletionConsumer(std::vector<std::string> &Results, + ReplCodeCompleter &CC) : CodeCompleteConsumer(getClangCompleteOpts()), CCAllocator(std::make_shared<GlobalCodeCompletionAllocator>()), - CCTUInfo(CCAllocator), Results(Results){}; + CCTUInfo(CCAllocator), Results(Results), CC(CC) {} + // The entry of handling code completion. When the function is called, we + // create a `Context`-based handler (see classes defined below) to handle each + // completion result. void ProcessCodeCompleteResults(class Sema &S, CodeCompletionContext Context, CodeCompletionResult *InResults, unsigned NumResults) final; @@ -56,26 +63,147 @@ private: std::shared_ptr<GlobalCodeCompletionAllocator> CCAllocator; CodeCompletionTUInfo CCTUInfo; std::vector<std::string> &Results; + ReplCodeCompleter &CC; +}; + +/// The class CompletionContextHandler contains four interfaces, each of +/// which handles one type of completion result. +/// Its derived classes are used to create concrete handlers based on +/// \c CodeCompletionContext. +class CompletionContextHandler { +protected: + CodeCompletionContext CCC; + std::vector<std::string> &Results; + +private: + Sema &S; + +public: + CompletionContextHandler(Sema &S, CodeCompletionContext CCC, + std::vector<std::string> &Results) + : CCC(CCC), Results(Results), S(S) {} + + virtual ~CompletionContextHandler() = default; + /// Converts a Declaration completion result to a completion string, and then + /// stores it in Results. + virtual void handleDeclaration(const CodeCompletionResult &Result) { + auto PreferredType = CCC.getPreferredType(); + if (PreferredType.isNull()) { + Results.push_back(Result.Declaration->getName().str()); + return; + } + + if (auto *VD = dyn_cast<VarDecl>(Result.Declaration)) { + auto ArgumentType = VD->getType(); + if (PreferredType->isReferenceType()) { + QualType RT = PreferredType->castAs<ReferenceType>()->getPointeeType(); + Sema::ReferenceConversions RefConv; + Sema::ReferenceCompareResult RefRelationship = + S.CompareReferenceRelationship(SourceLocation(), RT, ArgumentType, + &RefConv); + switch (RefRelationship) { + case Sema::Ref_Compatible: + case Sema::Ref_Related: + Results.push_back(VD->getName().str()); + break; + case Sema::Ref_Incompatible: + break; + } + } else if (S.Context.hasSameType(ArgumentType, PreferredType)) { + Results.push_back(VD->getName().str()); + } + } + } + + /// Converts a Keyword completion result to a completion string, and then + /// stores it in Results. + virtual void handleKeyword(const CodeCompletionResult &Result) { + auto Prefix = S.getPreprocessor().getCodeCompletionFilter(); + // Add keyword to the completion results only if we are in a type-aware + // situation. + if (!CCC.getBaseType().isNull() || !CCC.getPreferredType().isNull()) + return; + if (StringRef(Result.Keyword).starts_with(Prefix)) + Results.push_back(Result.Keyword); + } + + /// Converts a Pattern completion result to a completion string, and then + /// stores it in Results. + virtual void handlePattern(const CodeCompletionResult &Result) {} + + /// Converts a Macro completion result to a completion string, and then stores + /// it in Results. + virtual void handleMacro(const CodeCompletionResult &Result) {} +}; + +class DotMemberAccessHandler : public CompletionContextHandler { +public: + DotMemberAccessHandler(Sema &S, CodeCompletionContext CCC, + std::vector<std::string> &Results) + : CompletionContextHandler(S, CCC, Results) {} + void handleDeclaration(const CodeCompletionResult &Result) override { + auto *ID = Result.Declaration->getIdentifier(); + if (!ID) + return; + if (!isa<CXXMethodDecl>(Result.Declaration)) + return; + const auto *Fun = cast<CXXMethodDecl>(Result.Declaration); + if (Fun->getParent()->getCanonicalDecl() == + CCC.getBaseType()->getAsCXXRecordDecl()->getCanonicalDecl()) { + LLVM_DEBUG(llvm::dbgs() << "[In HandleCodeCompleteDOT] Name : " + << ID->getName() << "\n"); + Results.push_back(ID->getName().str()); + } + } + + void handleKeyword(const CodeCompletionResult &Result) override {} }; void ReplCompletionConsumer::ProcessCodeCompleteResults( class Sema &S, CodeCompletionContext Context, CodeCompletionResult *InResults, unsigned NumResults) { - for (unsigned I = 0; I < NumResults; ++I) { + + auto Prefix = S.getPreprocessor().getCodeCompletionFilter(); + CC.Prefix = Prefix; + + std::unique_ptr<CompletionContextHandler> CCH; + + // initialize fine-grained code completion handler based on the code + // completion context. + switch (Context.getKind()) { + case CodeCompletionContext::CCC_DotMemberAccess: + CCH.reset(new DotMemberAccessHandler(S, Context, this->Results)); + break; + default: + CCH.reset(new CompletionContextHandler(S, Context, this->Results)); + }; + + for (unsigned I = 0; I < NumResults; I++) { auto &Result = InResults[I]; switch (Result.Kind) { case CodeCompletionResult::RK_Declaration: - if (auto *ID = Result.Declaration->getIdentifier()) { - Results.push_back(ID->getName().str()); + if (Result.Hidden) { + break; + } + if (!Result.Declaration->getDeclName().isIdentifier() || + !Result.Declaration->getName().starts_with(Prefix)) { + break; } + CCH->handleDeclaration(Result); break; case CodeCompletionResult::RK_Keyword: - Results.push_back(Result.Keyword); + CCH->handleKeyword(Result); break; - default: + case CodeCompletionResult::RK_Macro: + CCH->handleMacro(Result); + break; + case CodeCompletionResult::RK_Pattern: + CCH->handlePattern(Result); break; } } + + std::sort(Results.begin(), Results.end()); } class IncrementalSyntaxOnlyAction : public SyntaxOnlyAction { @@ -118,6 +246,16 @@ void IncrementalSyntaxOnlyAction::ExecuteAction() { CI.getASTContext().getTranslationUnitDecl()->setHasExternalVisibleStorage( true); + // Load all external decls into current context. Under the hood, it calls + // ExternalSource::completeVisibleDeclsMap, which make all decls on the redecl + // chain visible. + // + // This is crucial to code completion on dot members, since a bound variable + // before "." would be otherwise treated out-of-scope. + // + // clang-repl> Foo f1; + // clang-repl> f1.<tab> + CI.getASTContext().getTranslationUnitDecl()->lookups(); SyntaxOnlyAction::ExecuteAction(); } @@ -134,6 +272,7 @@ ExternalSource::ExternalSource(ASTContext &ChildASTCtxt, FileManager &ChildFM, bool ExternalSource::FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name) { + IdentifierTable &ParentIdTable = ParentASTCtxt.Idents; auto ParentDeclName = @@ -159,29 +298,67 @@ void ExternalSource::completeVisibleDeclsMap( for (auto *DeclCtxt = ParentTUDeclCtxt; DeclCtxt != nullptr; DeclCtxt = DeclCtxt->getPreviousDecl()) { for (auto &IDeclContext : DeclCtxt->decls()) { - if (NamedDecl *Decl = llvm::dyn_cast<NamedDecl>(IDeclContext)) { - if (auto DeclOrErr = Importer->Import(Decl)) { - if (NamedDecl *importedNamedDecl = - llvm::dyn_cast<NamedDecl>(*DeclOrErr)) { - SetExternalVisibleDeclsForName(ChildDeclContext, - importedNamedDecl->getDeclName(), - importedNamedDecl); - } - - } else { - llvm::consumeError(DeclOrErr.takeError()); - } + if (!llvm::isa<NamedDecl>(IDeclContext)) + continue; + + NamedDecl *Decl = llvm::cast<NamedDecl>(IDeclContext); + + auto DeclOrErr = Importer->Import(Decl); + if (!DeclOrErr) { + // if an error happens, it usually means the decl has already been + // imported or the decl is a result of a failed import. But in our + // case, every import is fresh each time code completion is + // triggered. So Import usually doesn't fail. If it does, it just means + // the related decl can't be used in code completion and we can safely + // drop it. + llvm::consumeError(DeclOrErr.takeError()); + continue; } + + if (!llvm::isa<NamedDecl>(*DeclOrErr)) + continue; + + NamedDecl *importedNamedDecl = llvm::cast<NamedDecl>(*DeclOrErr); + + SetExternalVisibleDeclsForName(ChildDeclContext, + importedNamedDecl->getDeclName(), + importedNamedDecl); + + if (!llvm::isa<CXXRecordDecl>(importedNamedDecl)) + continue; + + auto *Record = llvm::cast<CXXRecordDecl>(importedNamedDecl); + + if (auto Err = Importer->ImportDefinition(Decl)) { + // the same as above + consumeError(std::move(Err)); + continue; + } + + Record->setHasLoadedFieldsFromExternalStorage(true); + LLVM_DEBUG(llvm::dbgs() + << "\nCXXRecrod : " << Record->getName() << " size(methods): " + << std::distance(Record->method_begin(), Record->method_end()) + << " has def?: " << Record->hasDefinition() + << " # (methods): " + << std::distance(Record->getDefinition()->method_begin(), + Record->getDefinition()->method_end()) + << "\n"); + for (auto *Meth : Record->methods()) + SetExternalVisibleDeclsForName(ChildDeclContext, Meth->getDeclName(), + Meth); } ChildDeclContext->setHasExternalLexicalStorage(false); } } -void codeComplete(CompilerInstance *InterpCI, llvm::StringRef Content, - unsigned Line, unsigned Col, const CompilerInstance *ParentCI, - std::vector<std::string> &CCResults) { +void ReplCodeCompleter::codeComplete(CompilerInstance *InterpCI, + llvm::StringRef Content, unsigned Line, + unsigned Col, + const CompilerInstance *ParentCI, + std::vector<std::string> &CCResults) { auto DiagOpts = DiagnosticOptions(); - auto consumer = ReplCompletionConsumer(CCResults); + auto consumer = ReplCompletionConsumer(CCResults, *this); auto diag = InterpCI->getDiagnosticsPtr(); std::unique_ptr<ASTUnit> AU(ASTUnit::LoadFromCompilerInvocationAction( diff --git a/contrib/llvm-project/clang/lib/Interpreter/Interpreter.cpp b/contrib/llvm-project/clang/lib/Interpreter/Interpreter.cpp index 7968c62cbd3e..c9fcef5b5b5a 100644 --- a/contrib/llvm-project/clang/lib/Interpreter/Interpreter.cpp +++ b/contrib/llvm-project/clang/lib/Interpreter/Interpreter.cpp @@ -319,6 +319,10 @@ const CompilerInstance *Interpreter::getCompilerInstance() const { return IncrParser->getCI(); } +CompilerInstance *Interpreter::getCompilerInstance() { + return IncrParser->getCI(); +} + llvm::Expected<llvm::orc::LLJIT &> Interpreter::getExecutionEngine() { if (!IncrExecutor) { if (auto Err = CreateExecutor()) diff --git a/contrib/llvm-project/clang/lib/Lex/PPDirectives.cpp b/contrib/llvm-project/clang/lib/Lex/PPDirectives.cpp index 112bc8dc572c..9f82a6d073e3 100644 --- a/contrib/llvm-project/clang/lib/Lex/PPDirectives.cpp +++ b/contrib/llvm-project/clang/lib/Lex/PPDirectives.cpp @@ -1858,11 +1858,18 @@ static void diagnoseAutoModuleImport( // path to the file, build a properly-cased replacement in the vector, // and return true if the replacement should be suggested. static bool trySimplifyPath(SmallVectorImpl<StringRef> &Components, - StringRef RealPathName) { + StringRef RealPathName, + llvm::sys::path::Style Separator) { auto RealPathComponentIter = llvm::sys::path::rbegin(RealPathName); auto RealPathComponentEnd = llvm::sys::path::rend(RealPathName); int Cnt = 0; bool SuggestReplacement = false; + + auto IsSep = [Separator](StringRef Component) { + return Component.size() == 1 && + llvm::sys::path::is_separator(Component[0], Separator); + }; + // Below is a best-effort to handle ".." in paths. It is admittedly // not 100% correct in the presence of symlinks. for (auto &Component : llvm::reverse(Components)) { @@ -1872,10 +1879,11 @@ static bool trySimplifyPath(SmallVectorImpl<StringRef> &Components, } else if (Cnt) { --Cnt; } else if (RealPathComponentIter != RealPathComponentEnd) { - if (Component != *RealPathComponentIter) { - // If these path components differ by more than just case, then we - // may be looking at symlinked paths. Bail on this diagnostic to avoid - // noisy false positives. + if (!IsSep(Component) && !IsSep(*RealPathComponentIter) && + Component != *RealPathComponentIter) { + // If these non-separator path components differ by more than just case, + // then we may be looking at symlinked paths. Bail on this diagnostic to + // avoid noisy false positives. SuggestReplacement = RealPathComponentIter->equals_insensitive(Component); if (!SuggestReplacement) @@ -2451,7 +2459,7 @@ Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport( } #endif - if (trySimplifyPath(Components, RealPathName)) { + if (trySimplifyPath(Components, RealPathName, BackslashStyle)) { SmallString<128> Path; Path.reserve(Name.size()+2); Path.push_back(isAngled ? '<' : '"'); @@ -2474,7 +2482,7 @@ Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport( // got copied when the C: was processed and we want to skip that entry. if (!(Component.size() == 1 && IsSep(Component[0]))) Path.append(Component); - else if (!Path.empty()) + else if (Path.size() != 1) continue; // Append the separator(s) the user used, or the close quote diff --git a/contrib/llvm-project/clang/lib/Parse/ParseOpenACC.cpp b/contrib/llvm-project/clang/lib/Parse/ParseOpenACC.cpp index f7f096762e91..67325f0a286a 100644 --- a/contrib/llvm-project/clang/lib/Parse/ParseOpenACC.cpp +++ b/contrib/llvm-project/clang/lib/Parse/ParseOpenACC.cpp @@ -69,6 +69,29 @@ OpenACCDirectiveKindEx getOpenACCDirectiveKind(Token Tok) { .Default(OpenACCDirectiveKindEx::Invalid); } +// Translate single-token string representations to the OpenCC Clause Kind. +OpenACCClauseKind getOpenACCClauseKind(Token Tok) { + // auto is a keyword in some language modes, so make sure we parse it + // correctly. + if (Tok.is(tok::kw_auto)) + return OpenACCClauseKind::Auto; + + if (!Tok.is(tok::identifier)) + return OpenACCClauseKind::Invalid; + + return llvm::StringSwitch<OpenACCClauseKind>( + Tok.getIdentifierInfo()->getName()) + .Case("auto", OpenACCClauseKind::Auto) + .Case("finalize", OpenACCClauseKind::Finalize) + .Case("if_present", OpenACCClauseKind::IfPresent) + .Case("independent", OpenACCClauseKind::Independent) + .Case("nohost", OpenACCClauseKind::NoHost) + .Case("seq", OpenACCClauseKind::Seq) + .Case("vector", OpenACCClauseKind::Vector) + .Case("worker", OpenACCClauseKind::Worker) + .Default(OpenACCClauseKind::Invalid); +} + // Since 'atomic' is effectively a compound directive, this will decode the // second part of the directive. OpenACCAtomicKind getOpenACCAtomicKind(Token Tok) { @@ -164,6 +187,10 @@ ParseOpenACCEnterExitDataDirective(Parser &P, Token FirstTok, return OpenACCDirectiveKind::Invalid; } + // Consume the second name anyway, this way we can continue on without making + // this oddly look like a clause. + P.ConsumeAnyToken(); + if (!isOpenACCDirectiveKind(OpenACCDirectiveKind::Data, SecondTok)) { if (!SecondTok.is(tok::identifier)) P.Diag(SecondTok, diag::err_expected) << tok::identifier; @@ -174,8 +201,6 @@ ParseOpenACCEnterExitDataDirective(Parser &P, Token FirstTok, return OpenACCDirectiveKind::Invalid; } - P.ConsumeToken(); - return ExtDirKind == OpenACCDirectiveKindEx::Enter ? OpenACCDirectiveKind::EnterData : OpenACCDirectiveKind::ExitData; @@ -208,6 +233,10 @@ OpenACCDirectiveKind ParseOpenACCDirectiveKind(Parser &P) { // introspect on the spelling before then. if (FirstTok.isNot(tok::identifier)) { P.Diag(FirstTok, diag::err_acc_missing_directive); + + if (P.getCurToken().isNot(tok::annot_pragma_openacc_end)) + P.ConsumeAnyToken(); + return OpenACCDirectiveKind::Invalid; } @@ -262,12 +291,57 @@ OpenACCDirectiveKind ParseOpenACCDirectiveKind(Parser &P) { return DirKind; } +// The OpenACC Clause List is a comma or space-delimited list of clauses (see +// the comment on ParseOpenACCClauseList). The concept of a 'clause' doesn't +// really have its owner grammar and each individual one has its own definition. +// However, they all are named with a single-identifier (or auto!) token, +// followed in some cases by either braces or parens. +bool ParseOpenACCClause(Parser &P) { + if (!P.getCurToken().isOneOf(tok::identifier, tok::kw_auto)) + return P.Diag(P.getCurToken(), diag::err_expected) << tok::identifier; + + OpenACCClauseKind Kind = getOpenACCClauseKind(P.getCurToken()); + + if (Kind == OpenACCClauseKind::Invalid) + return P.Diag(P.getCurToken(), diag::err_acc_invalid_clause) + << P.getCurToken().getIdentifierInfo(); + + // Consume the clause name. + P.ConsumeToken(); + + // FIXME: For future clauses, we need to handle parens/etc below. + return false; +} + +// Skip until we see the end of pragma token, but don't consume it. This is us +// just giving up on the rest of the pragma so we can continue executing. We +// have to do this because 'SkipUntil' considers paren balancing, which isn't +// what we want. +void SkipUntilEndOfDirective(Parser &P) { + while (P.getCurToken().isNot(tok::annot_pragma_openacc_end)) + P.ConsumeAnyToken(); +} + +// OpenACC 3.3, section 1.7: +// To simplify the specification and convey appropriate constraint information, +// a pqr-list is a comma-separated list of pdr items. The one exception is a +// clause-list, which is a list of one or more clauses optionally separated by +// commas. void ParseOpenACCClauseList(Parser &P) { - // FIXME: In the future, we'll start parsing the clauses here, but for now we - // haven't implemented that, so just emit the unimplemented diagnostic and - // fail reasonably. - if (P.getCurToken().isNot(tok::annot_pragma_openacc_end)) - P.Diag(P.getCurToken(), diag::warn_pragma_acc_unimplemented_clause_parsing); + bool FirstClause = true; + while (P.getCurToken().isNot(tok::annot_pragma_openacc_end)) { + // Comma is optional in a clause-list. + if (!FirstClause && P.getCurToken().is(tok::comma)) + P.ConsumeToken(); + FirstClause = false; + + // Recovering from a bad clause is really difficult, so we just give up on + // error. + if (ParseOpenACCClause(P)) { + SkipUntilEndOfDirective(P); + return; + } + } } } // namespace @@ -499,7 +573,9 @@ void Parser::ParseOpenACCDirective() { ParseOpenACCClauseList(*this); Diag(getCurToken(), diag::warn_pragma_acc_unimplemented); - SkipUntil(tok::annot_pragma_openacc_end); + assert(Tok.is(tok::annot_pragma_openacc_end) && + "Didn't parse all OpenACC Clauses"); + ConsumeAnnotationToken(); } // Parse OpenACC directive on a declaration. diff --git a/contrib/llvm-project/clang/lib/Sema/SemaChecking.cpp b/contrib/llvm-project/clang/lib/Sema/SemaChecking.cpp index d4a40b850cea..2a69325f0295 100644 --- a/contrib/llvm-project/clang/lib/Sema/SemaChecking.cpp +++ b/contrib/llvm-project/clang/lib/Sema/SemaChecking.cpp @@ -3156,7 +3156,6 @@ static void checkArmStreamingBuiltin(Sema &S, CallExpr *TheCall, const FunctionDecl *FD, ArmStreamingType BuiltinType) { ArmStreamingType FnType = getArmStreamingFnType(FD); - if (FnType == ArmStreaming && BuiltinType == ArmNonStreaming) { S.Diag(TheCall->getBeginLoc(), diag::warn_attribute_arm_sm_incompat_builtin) << TheCall->getSourceRange() << "streaming"; @@ -3168,9 +3167,77 @@ static void checkArmStreamingBuiltin(Sema &S, CallExpr *TheCall, << TheCall->getSourceRange() << "streaming compatible"; return; } + + if (FnType == ArmNonStreaming && BuiltinType == ArmStreaming) { + S.Diag(TheCall->getBeginLoc(), diag::warn_attribute_arm_sm_incompat_builtin) + << TheCall->getSourceRange() << "non-streaming"; + } +} + +static bool hasSMEZAState(const FunctionDecl *FD) { + if (FD->hasAttr<ArmNewZAAttr>()) + return true; + if (const auto *T = FD->getType()->getAs<FunctionProtoType>()) + if (T->getAArch64SMEAttributes() & FunctionType::SME_PStateZASharedMask) + return true; + return false; +} + +static bool hasSMEZAState(unsigned BuiltinID) { + switch (BuiltinID) { + default: + return false; +#define GET_SME_BUILTIN_HAS_ZA_STATE +#include "clang/Basic/arm_sme_builtins_za_state.inc" +#undef GET_SME_BUILTIN_HAS_ZA_STATE + } +} + +bool Sema::CheckSMEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { + if (const FunctionDecl *FD = getCurFunctionDecl()) { + std::optional<ArmStreamingType> BuiltinType; + + switch (BuiltinID) { +#define GET_SME_STREAMING_ATTRS +#include "clang/Basic/arm_sme_streaming_attrs.inc" +#undef GET_SME_STREAMING_ATTRS + } + + if (BuiltinType) + checkArmStreamingBuiltin(*this, TheCall, FD, *BuiltinType); + + if (hasSMEZAState(BuiltinID) && !hasSMEZAState(FD)) + Diag(TheCall->getBeginLoc(), + diag::warn_attribute_arm_za_builtin_no_za_state) + << TheCall->getSourceRange(); + } + + // Range check SME intrinsics that take immediate values. + SmallVector<std::tuple<int, int, int>, 3> ImmChecks; + + switch (BuiltinID) { + default: + return false; +#define GET_SME_IMMEDIATE_CHECK +#include "clang/Basic/arm_sme_sema_rangechecks.inc" +#undef GET_SME_IMMEDIATE_CHECK + } + + return ParseSVEImmChecks(TheCall, ImmChecks); } bool Sema::CheckSVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { + if (const FunctionDecl *FD = getCurFunctionDecl()) { + std::optional<ArmStreamingType> BuiltinType; + + switch (BuiltinID) { +#define GET_SVE_STREAMING_ATTRS +#include "clang/Basic/arm_sve_streaming_attrs.inc" +#undef GET_SVE_STREAMING_ATTRS + } + if (BuiltinType) + checkArmStreamingBuiltin(*this, TheCall, FD, *BuiltinType); + } // Range check SVE intrinsics that take immediate values. SmallVector<std::tuple<int, int, int>, 3> ImmChecks; @@ -3180,9 +3247,6 @@ bool Sema::CheckSVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { #define GET_SVE_IMMEDIATE_CHECK #include "clang/Basic/arm_sve_sema_rangechecks.inc" #undef GET_SVE_IMMEDIATE_CHECK -#define GET_SME_IMMEDIATE_CHECK -#include "clang/Basic/arm_sme_sema_rangechecks.inc" -#undef GET_SME_IMMEDIATE_CHECK } return ParseSVEImmChecks(TheCall, ImmChecks); @@ -3569,6 +3633,9 @@ bool Sema::CheckAArch64BuiltinFunctionCall(const TargetInfo &TI, if (CheckSVEBuiltinFunctionCall(BuiltinID, TheCall)) return true; + if (CheckSMEBuiltinFunctionCall(BuiltinID, TheCall)) + return true; + // For intrinsics which take an immediate value as part of the instruction, // range check them here. unsigned i = 0, l = 0, u = 0; @@ -5322,7 +5389,7 @@ bool Sema::CheckRISCVBuiltinFunctionCall(const TargetInfo &TI, QualType Op2Type = TheCall->getArg(1)->getType(); QualType Op3Type = TheCall->getArg(2)->getType(); uint64_t ElemSize = Op1Type->isRVVType(32, false) ? 32 : 64; - if (ElemSize == 64 && !TI.hasFeature("experimental-zvknhb")) + if (ElemSize == 64 && !TI.hasFeature("zvknhb")) return Diag(TheCall->getBeginLoc(), diag::err_riscv_type_requires_extension) << Op1Type << "zvknhb"; diff --git a/contrib/llvm-project/clang/lib/Sema/SemaDecl.cpp b/contrib/llvm-project/clang/lib/Sema/SemaDecl.cpp index be6a136ef37b..ffbe317d5599 100644 --- a/contrib/llvm-project/clang/lib/Sema/SemaDecl.cpp +++ b/contrib/llvm-project/clang/lib/Sema/SemaDecl.cpp @@ -2005,12 +2005,12 @@ static bool ShouldDiagnoseUnusedDecl(const LangOptions &LangOpts, if (D->isInvalidDecl()) return false; - if (auto *DD = dyn_cast<DecompositionDecl>(D)) { + if (const auto *DD = dyn_cast<DecompositionDecl>(D)) { // For a decomposition declaration, warn if none of the bindings are // referenced, instead of if the variable itself is referenced (which // it is, by the bindings' expressions). bool IsAllPlaceholders = true; - for (auto *BD : DD->bindings()) { + for (const auto *BD : DD->bindings()) { if (BD->isReferenced()) return false; IsAllPlaceholders = IsAllPlaceholders && BD->isPlaceholderVar(LangOpts); @@ -2054,7 +2054,7 @@ static bool ShouldDiagnoseUnusedDecl(const LangOptions &LangOpts, if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { const Expr *Init = VD->getInit(); - if (const auto *Cleanups = dyn_cast_or_null<ExprWithCleanups>(Init)) + if (const auto *Cleanups = dyn_cast_if_present<ExprWithCleanups>(Init)) Init = Cleanups->getSubExpr(); const auto *Ty = VD->getType().getTypePtr(); @@ -2068,11 +2068,10 @@ static bool ShouldDiagnoseUnusedDecl(const LangOptions &LangOpts, // Warn for reference variables whose initializtion performs lifetime // extension. - if (const auto *MTE = dyn_cast_or_null<MaterializeTemporaryExpr>(Init)) { - if (MTE->getExtendingDecl()) { - Ty = VD->getType().getNonReferenceType().getTypePtr(); - Init = MTE->getSubExpr()->IgnoreImplicitAsWritten(); - } + if (const auto *MTE = dyn_cast_if_present<MaterializeTemporaryExpr>(Init); + MTE && MTE->getExtendingDecl()) { + Ty = VD->getType().getNonReferenceType().getTypePtr(); + Init = MTE->getSubExpr()->IgnoreImplicitAsWritten(); } // If we failed to complete the type for some reason, or if the type is @@ -2089,15 +2088,14 @@ static bool ShouldDiagnoseUnusedDecl(const LangOptions &LangOpts, if (Tag->hasAttr<UnusedAttr>()) return false; - if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Tag)) { + if (const auto *RD = dyn_cast<CXXRecordDecl>(Tag)) { if (!RD->hasTrivialDestructor() && !RD->hasAttr<WarnUnusedAttr>()) return false; if (Init) { - const CXXConstructExpr *Construct = - dyn_cast<CXXConstructExpr>(Init); + const auto *Construct = dyn_cast<CXXConstructExpr>(Init); if (Construct && !Construct->isElidable()) { - CXXConstructorDecl *CD = Construct->getConstructor(); + const CXXConstructorDecl *CD = Construct->getConstructor(); if (!CD->isTrivial() && !RD->hasAttr<WarnUnusedAttr>() && (VD->getInit()->isValueDependent() || !VD->evaluateValue())) return false; @@ -2211,10 +2209,9 @@ void Sema::DiagnoseUnusedButSetDecl(const VarDecl *VD, return; // In C++, don't warn for record types that don't have WarnUnusedAttr, to // mimic gcc's behavior. - if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Tag)) { - if (!RD->hasAttr<WarnUnusedAttr>()) - return; - } + if (const auto *RD = dyn_cast<CXXRecordDecl>(Tag); + RD && !RD->hasAttr<WarnUnusedAttr>()) + return; } // Don't warn about __block Objective-C pointer variables, as they might @@ -12957,7 +12954,7 @@ QualType Sema::deduceVarTypeFromInitializer(VarDecl *VDecl, // FIXME: Initialization should not be taking a mutable list of inits. SmallVector<Expr*, 8> InitsCopy(DeduceInits.begin(), DeduceInits.end()); return DeduceTemplateSpecializationFromInitializer(TSI, Entity, Kind, - InitsCopy, PL); + InitsCopy); } if (DirectInit) { @@ -19518,20 +19515,6 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, CDecl->setIvarRBraceLoc(RBrac); } } - - // Check the "counted_by" attribute to ensure that the count field exists in - // the struct. Make sure we're performing this check on the outer-most - // record. This is a C-only feature. - if (!getLangOpts().CPlusPlus && Record && - !isa<RecordDecl>(Record->getParent())) { - auto Pred = [](const Decl *D) { - if (const auto *FD = dyn_cast_if_present<FieldDecl>(D)) - return FD->hasAttr<CountedByAttr>(); - return false; - }; - if (const FieldDecl *FD = Record->findFieldIf(Pred)) - CheckCountedByAttr(S, FD); - } } /// Determine whether the given integral value is representable within diff --git a/contrib/llvm-project/clang/lib/Sema/SemaDeclAttr.cpp b/contrib/llvm-project/clang/lib/Sema/SemaDeclAttr.cpp index 5b29b05dee54..af8b90ecfed9 100644 --- a/contrib/llvm-project/clang/lib/Sema/SemaDeclAttr.cpp +++ b/contrib/llvm-project/clang/lib/Sema/SemaDeclAttr.cpp @@ -8445,92 +8445,6 @@ static void handleZeroCallUsedRegsAttr(Sema &S, Decl *D, const ParsedAttr &AL) { D->addAttr(ZeroCallUsedRegsAttr::Create(S.Context, Kind, AL)); } -static void handleCountedByAttr(Sema &S, Decl *D, const ParsedAttr &AL) { - if (!AL.isArgIdent(0)) { - S.Diag(AL.getLoc(), diag::err_attribute_argument_type) - << AL << AANT_ArgumentIdentifier; - return; - } - - IdentifierLoc *IL = AL.getArgAsIdent(0); - CountedByAttr *CBA = - ::new (S.Context) CountedByAttr(S.Context, AL, IL->Ident); - CBA->setCountedByFieldLoc(IL->Loc); - D->addAttr(CBA); -} - -bool Sema::CheckCountedByAttr(Scope *S, const FieldDecl *FD) { - const auto *CBA = FD->getAttr<CountedByAttr>(); - const IdentifierInfo *FieldName = CBA->getCountedByField(); - DeclarationNameInfo NameInfo(FieldName, - CBA->getCountedByFieldLoc().getBegin()); - - LookupResult MemResult(*this, NameInfo, Sema::LookupMemberName); - LookupName(MemResult, S); - - if (MemResult.empty()) { - // The "counted_by" field needs to exist within the struct. - LookupResult OrdResult(*this, NameInfo, Sema::LookupOrdinaryName); - LookupName(OrdResult, S); - - if (!OrdResult.empty()) { - SourceRange SR = FD->getLocation(); - Diag(SR.getBegin(), diag::err_counted_by_must_be_in_structure) - << FieldName << SR; - - if (auto *ND = OrdResult.getAsSingle<NamedDecl>()) { - SR = ND->getLocation(); - Diag(SR.getBegin(), diag::note_flexible_array_counted_by_attr_field) - << ND << SR; - } - return true; - } - - CXXScopeSpec SS; - DeclFilterCCC<FieldDecl> Filter(FieldName); - return DiagnoseEmptyLookup(S, SS, MemResult, Filter, nullptr, std::nullopt, - const_cast<DeclContext *>(FD->getDeclContext())); - } - - LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel = - LangOptions::StrictFlexArraysLevelKind::IncompleteOnly; - - if (!Decl::isFlexibleArrayMemberLike(Context, FD, FD->getType(), - StrictFlexArraysLevel, true)) { - // The "counted_by" attribute must be on a flexible array member. - SourceRange SR = FD->getLocation(); - Diag(SR.getBegin(), diag::err_counted_by_attr_not_on_flexible_array_member) - << SR; - return true; - } - - if (const FieldDecl *Field = MemResult.getAsSingle<FieldDecl>()) { - if (Field->hasAttr<CountedByAttr>()) { - // The "counted_by" field can't point to the flexible array member. - SourceRange SR = CBA->getCountedByFieldLoc(); - Diag(SR.getBegin(), diag::err_counted_by_attr_refers_to_flexible_array) - << CBA->getCountedByField() << SR; - return true; - } - - if (!Field->getType()->isIntegerType() || - Field->getType()->isBooleanType()) { - // The "counted_by" field must have an integer type. - SourceRange SR = CBA->getCountedByFieldLoc(); - Diag(SR.getBegin(), - diag::err_flexible_array_counted_by_attr_field_not_integer) - << CBA->getCountedByField() << SR; - - SR = Field->getLocation(); - Diag(SR.getBegin(), diag::note_flexible_array_counted_by_attr_field) - << Field << SR; - return true; - } - } - - return false; -} - static void handleFunctionReturnThunksAttr(Sema &S, Decl *D, const ParsedAttr &AL) { StringRef KindStr; @@ -9488,10 +9402,6 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL, handleAvailableOnlyInDefaultEvalMethod(S, D, AL); break; - case ParsedAttr::AT_CountedBy: - handleCountedByAttr(S, D, AL); - break; - // Microsoft attributes: case ParsedAttr::AT_LayoutVersion: handleLayoutVersion(S, D, AL); diff --git a/contrib/llvm-project/clang/lib/Sema/SemaExpr.cpp b/contrib/llvm-project/clang/lib/Sema/SemaExpr.cpp index c7185d56cc99..960f513d1111 100644 --- a/contrib/llvm-project/clang/lib/Sema/SemaExpr.cpp +++ b/contrib/llvm-project/clang/lib/Sema/SemaExpr.cpp @@ -2469,8 +2469,7 @@ bool Sema::DiagnoseDependentMemberLookup(const LookupResult &R) { bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, CorrectionCandidateCallback &CCC, TemplateArgumentListInfo *ExplicitTemplateArgs, - ArrayRef<Expr *> Args, DeclContext *LookupCtx, - TypoExpr **Out) { + ArrayRef<Expr *> Args, TypoExpr **Out) { DeclarationName Name = R.getLookupName(); unsigned diagnostic = diag::err_undeclared_var_use; @@ -2486,8 +2485,7 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, // unqualified lookup. This is useful when (for example) the // original lookup would not have found something because it was a // dependent name. - DeclContext *DC = - LookupCtx ? LookupCtx : (SS.isEmpty() ? CurContext : nullptr); + DeclContext *DC = SS.isEmpty() ? CurContext : nullptr; while (DC) { if (isa<CXXRecordDecl>(DC)) { LookupQualifiedName(R, DC); @@ -2530,12 +2528,12 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, emitEmptyLookupTypoDiagnostic(TC, *this, SS, Name, TypoLoc, Args, diagnostic, diagnostic_suggest); }, - nullptr, CTK_ErrorRecovery, LookupCtx); + nullptr, CTK_ErrorRecovery); if (*Out) return true; - } else if (S && (Corrected = - CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), S, - &SS, CCC, CTK_ErrorRecovery, LookupCtx))) { + } else if (S && + (Corrected = CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), + S, &SS, CCC, CTK_ErrorRecovery))) { std::string CorrectedStr(Corrected.getAsString(getLangOpts())); bool DroppedSpecifier = Corrected.WillReplaceSpecifier() && Name.getAsString() == CorrectedStr; @@ -2825,7 +2823,7 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS, // a template name, but we happen to have always already looked up the name // before we get here if it must be a template name. if (DiagnoseEmptyLookup(S, SS, R, CCC ? *CCC : DefaultValidator, nullptr, - std::nullopt, nullptr, &TE)) { + std::nullopt, &TE)) { if (TE && KeywordReplacement) { auto &State = getTypoExprState(TE); auto BestTC = State.Consumer->getNextCorrection(); diff --git a/contrib/llvm-project/clang/lib/Sema/SemaExprCXX.cpp b/contrib/llvm-project/clang/lib/Sema/SemaExprCXX.cpp index 081b568762ae..4ae04358d5df 100644 --- a/contrib/llvm-project/clang/lib/Sema/SemaExprCXX.cpp +++ b/contrib/llvm-project/clang/lib/Sema/SemaExprCXX.cpp @@ -843,21 +843,21 @@ Sema::ActOnCXXThrow(Scope *S, SourceLocation OpLoc, Expr *Ex) { // operation from the operand to the exception object (15.1) can be // omitted by constructing the automatic object directly into the // exception object - if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Ex->IgnoreParens())) - if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) { - if (Var->hasLocalStorage() && !Var->getType().isVolatileQualified()) { - for( ; S; S = S->getParent()) { - if (S->isDeclScope(Var)) { - IsThrownVarInScope = true; - break; - } - - // FIXME: Many of the scope checks here seem incorrect. - if (S->getFlags() & - (Scope::FnScope | Scope::ClassScope | Scope::BlockScope | - Scope::ObjCMethodScope | Scope::TryScope)) - break; + if (const auto *DRE = dyn_cast<DeclRefExpr>(Ex->IgnoreParens())) + if (const auto *Var = dyn_cast<VarDecl>(DRE->getDecl()); + Var && Var->hasLocalStorage() && + !Var->getType().isVolatileQualified()) { + for (; S; S = S->getParent()) { + if (S->isDeclScope(Var)) { + IsThrownVarInScope = true; + break; } + + // FIXME: Many of the scope checks here seem incorrect. + if (S->getFlags() & + (Scope::FnScope | Scope::ClassScope | Scope::BlockScope | + Scope::ObjCMethodScope | Scope::TryScope)) + break; } } } diff --git a/contrib/llvm-project/clang/lib/Sema/SemaExprMember.cpp b/contrib/llvm-project/clang/lib/Sema/SemaExprMember.cpp index 473eea55bb6b..2abec3d86a27 100644 --- a/contrib/llvm-project/clang/lib/Sema/SemaExprMember.cpp +++ b/contrib/llvm-project/clang/lib/Sema/SemaExprMember.cpp @@ -253,7 +253,9 @@ static void diagnoseInstanceReference(Sema &SemaRef, SemaRef.Diag(Loc, diag::err_member_call_without_object) << Range << /*static*/ 0; else { - const auto *Callee = dyn_cast<CXXMethodDecl>(Rep); + if (const auto *Tpl = dyn_cast<FunctionTemplateDecl>(Rep)) + Rep = Tpl->getTemplatedDecl(); + const auto *Callee = cast<CXXMethodDecl>(Rep); auto Diag = SemaRef.Diag(Loc, diag::err_member_call_without_object) << Range << Callee->isExplicitObjectMemberFunction(); if (!Replacement.empty()) diff --git a/contrib/llvm-project/clang/lib/Sema/SemaInit.cpp b/contrib/llvm-project/clang/lib/Sema/SemaInit.cpp index 035eaae58965..61d244f3bb97 100644 --- a/contrib/llvm-project/clang/lib/Sema/SemaInit.cpp +++ b/contrib/llvm-project/clang/lib/Sema/SemaInit.cpp @@ -25,6 +25,7 @@ #include "clang/Sema/EnterExpressionEvaluationContext.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" +#include "clang/Sema/Ownership.h" #include "clang/Sema/SemaInternal.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/FoldingSet.h" @@ -465,8 +466,7 @@ class InitListChecker { void FillInEmptyInitForField(unsigned Init, FieldDecl *Field, const InitializedEntity &ParentEntity, InitListExpr *ILE, bool &RequiresSecondPass, - bool FillWithNoInit = false, - bool WarnIfMissing = false); + bool FillWithNoInit = false); void FillInEmptyInitializations(const InitializedEntity &Entity, InitListExpr *ILE, bool &RequiresSecondPass, InitListExpr *OuterILE, unsigned OuterIndex, @@ -655,16 +655,11 @@ void InitListChecker::FillInEmptyInitForBase( } } -static bool hasAnyDesignatedInits(const InitListExpr *IL) { - return llvm::any_of(*IL, [=](const Stmt *Init) { - return isa_and_nonnull<DesignatedInitExpr>(Init); - }); -} - -void InitListChecker::FillInEmptyInitForField( - unsigned Init, FieldDecl *Field, const InitializedEntity &ParentEntity, - InitListExpr *ILE, bool &RequiresSecondPass, bool FillWithNoInit, - bool WarnIfMissing) { +void InitListChecker::FillInEmptyInitForField(unsigned Init, FieldDecl *Field, + const InitializedEntity &ParentEntity, + InitListExpr *ILE, + bool &RequiresSecondPass, + bool FillWithNoInit) { SourceLocation Loc = ILE->getEndLoc(); unsigned NumInits = ILE->getNumInits(); InitializedEntity MemberEntity @@ -732,52 +727,15 @@ void InitListChecker::FillInEmptyInitForField( if (hadError || VerifyOnly) { // Do nothing - } else { - if (WarnIfMissing) { - auto CheckAnonMember = [&](const FieldDecl *FD, - auto &&CheckAnonMember) -> FieldDecl * { - FieldDecl *Uninitialized = nullptr; - RecordDecl *RD = FD->getType()->getAsRecordDecl(); - assert(RD && "Not anonymous member checked?"); - for (auto *F : RD->fields()) { - FieldDecl *UninitializedFieldInF = nullptr; - if (F->isAnonymousStructOrUnion()) - UninitializedFieldInF = CheckAnonMember(F, CheckAnonMember); - else if (!F->isUnnamedBitfield() && - !F->getType()->isIncompleteArrayType() && - !F->hasInClassInitializer()) - UninitializedFieldInF = F; - - if (RD->isUnion() && !UninitializedFieldInF) - return nullptr; - if (!Uninitialized) - Uninitialized = UninitializedFieldInF; - } - return Uninitialized; - }; - - FieldDecl *FieldToDiagnose = nullptr; - if (Field->isAnonymousStructOrUnion()) - FieldToDiagnose = CheckAnonMember(Field, CheckAnonMember); - else if (!Field->isUnnamedBitfield() && - !Field->getType()->isIncompleteArrayType()) - FieldToDiagnose = Field; - - if (FieldToDiagnose) - SemaRef.Diag(Loc, diag::warn_missing_field_initializers) - << FieldToDiagnose; - } - - if (Init < NumInits) { - ILE->setInit(Init, MemberInit.getAs<Expr>()); - } else if (!isa<ImplicitValueInitExpr>(MemberInit.get())) { - // Empty initialization requires a constructor call, so - // extend the initializer list to include the constructor - // call and make a note that we'll need to take another pass - // through the initializer list. - ILE->updateInit(SemaRef.Context, Init, MemberInit.getAs<Expr>()); - RequiresSecondPass = true; - } + } else if (Init < NumInits) { + ILE->setInit(Init, MemberInit.getAs<Expr>()); + } else if (!isa<ImplicitValueInitExpr>(MemberInit.get())) { + // Empty initialization requires a constructor call, so + // extend the initializer list to include the constructor + // call and make a note that we'll need to take another pass + // through the initializer list. + ILE->updateInit(SemaRef.Context, Init, MemberInit.getAs<Expr>()); + RequiresSecondPass = true; } } else if (InitListExpr *InnerILE = dyn_cast<InitListExpr>(ILE->getInit(Init))) { @@ -845,36 +803,9 @@ InitListChecker::FillInEmptyInitializations(const InitializedEntity &Entity, } } } else { - InitListExpr *SForm = - ILE->isSyntacticForm() ? ILE : ILE->getSyntacticForm(); // The fields beyond ILE->getNumInits() are default initialized, so in // order to leave them uninitialized, the ILE is expanded and the extra // fields are then filled with NoInitExpr. - - // Some checks that are required for missing fields warning are bound to - // how many elements the initializer list originally was provided; perform - // them before the list is expanded. - bool WarnIfMissingField = - !SForm->isIdiomaticZeroInitializer(SemaRef.getLangOpts()) && - ILE->getNumInits(); - - // Disable check for missing fields when designators are used in C to - // match gcc behaviour. - // FIXME: Should we emulate possible gcc warning bug? - WarnIfMissingField &= - SemaRef.getLangOpts().CPlusPlus || !hasAnyDesignatedInits(SForm); - - if (OuterILE) { - // When nested designators are present, there might be two nested init - // lists created and only outer will contain designated initializer - // expression, so check outer list as well. - InitListExpr *OuterSForm = OuterILE->isSyntacticForm() - ? OuterILE - : OuterILE->getSyntacticForm(); - WarnIfMissingField &= SemaRef.getLangOpts().CPlusPlus || - !hasAnyDesignatedInits(OuterSForm); - } - unsigned NumElems = numStructUnionElements(ILE->getType()); if (!RDecl->isUnion() && RDecl->hasFlexibleArrayMember()) ++NumElems; @@ -902,7 +833,7 @@ InitListChecker::FillInEmptyInitializations(const InitializedEntity &Entity, return; FillInEmptyInitForField(Init, Field, Entity, ILE, RequiresSecondPass, - FillWithNoInit, WarnIfMissingField); + FillWithNoInit); if (hadError) return; @@ -1017,6 +948,13 @@ InitListChecker::FillInEmptyInitializations(const InitializedEntity &Entity, } } +static bool hasAnyDesignatedInits(const InitListExpr *IL) { + for (const Stmt *Init : *IL) + if (isa_and_nonnull<DesignatedInitExpr>(Init)) + return true; + return false; +} + InitListChecker::InitListChecker( Sema &S, const InitializedEntity &Entity, InitListExpr *IL, QualType &T, bool VerifyOnly, bool TreatUnavailableAsInvalid, bool InOverloadResolution, @@ -2288,8 +2226,12 @@ void InitListChecker::CheckStructUnionTypes( size_t NumRecordDecls = llvm::count_if(RD->decls(), [&](const Decl *D) { return isa<FieldDecl>(D) || isa<RecordDecl>(D); }); + bool CheckForMissingFields = + !IList->isIdiomaticZeroInitializer(SemaRef.getLangOpts()); bool HasDesignatedInit = false; + llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields; + while (Index < IList->getNumInits()) { Expr *Init = IList->getInit(Index); SourceLocation InitLoc = Init->getBeginLoc(); @@ -2313,17 +2255,24 @@ void InitListChecker::CheckStructUnionTypes( // Find the field named by the designated initializer. DesignatedInitExpr::Designator *D = DIE->getDesignator(0); - if (!VerifyOnly && D->isFieldDesignator() && !DesignatedInitFailed) { + if (!VerifyOnly && D->isFieldDesignator()) { FieldDecl *F = D->getFieldDecl(); - QualType ET = SemaRef.Context.getBaseElementType(F->getType()); - if (checkDestructorReference(ET, InitLoc, SemaRef)) { - hadError = true; - return; + InitializedFields.insert(F); + if (!DesignatedInitFailed) { + QualType ET = SemaRef.Context.getBaseElementType(F->getType()); + if (checkDestructorReference(ET, InitLoc, SemaRef)) { + hadError = true; + return; + } } } InitializedSomething = true; + // Disable check for missing fields when designators are used. + // This matches gcc behaviour. + if (!SemaRef.getLangOpts().CPlusPlus) + CheckForMissingFields = false; continue; } @@ -2402,6 +2351,7 @@ void InitListChecker::CheckStructUnionTypes( CheckSubElementType(MemberEntity, IList, Field->getType(), Index, StructuredList, StructuredIndex); InitializedSomething = true; + InitializedFields.insert(*Field); if (RD->isUnion() && StructuredList) { // Initialize the first field within the union. @@ -2411,6 +2361,28 @@ void InitListChecker::CheckStructUnionTypes( ++Field; } + // Emit warnings for missing struct field initializers. + if (!VerifyOnly && InitializedSomething && CheckForMissingFields && + !RD->isUnion()) { + // It is possible we have one or more unnamed bitfields remaining. + // Find first (if any) named field and emit warning. + for (RecordDecl::field_iterator it = HasDesignatedInit ? RD->field_begin() + : Field, + end = RD->field_end(); + it != end; ++it) { + if (HasDesignatedInit && InitializedFields.count(*it)) + continue; + + if (!it->isUnnamedBitfield() && !it->hasInClassInitializer() && + !it->getType()->isIncompleteArrayType()) { + SemaRef.Diag(IList->getSourceRange().getEnd(), + diag::warn_missing_field_initializers) + << *it; + break; + } + } + } + // Check that any remaining fields can be value-initialized if we're not // building a structured list. (If we are, we'll check this later.) if (!StructuredList && Field != FieldEnd && !RD->isUnion() && @@ -5458,18 +5430,12 @@ static void TryOrBuildParenListInitialization( auto HandleInitializedEntity = [&](const InitializedEntity &SubEntity, const InitializationKind &SubKind, Expr *Arg, Expr **InitExpr = nullptr) { - InitializationSequence IS = [&]() { - if (Arg) - return InitializationSequence(S, SubEntity, SubKind, Arg); - return InitializationSequence(S, SubEntity, SubKind, std::nullopt); - }(); + InitializationSequence IS = InitializationSequence( + S, SubEntity, SubKind, Arg ? MultiExprArg(Arg) : std::nullopt); if (IS.Failed()) { if (!VerifyOnly) { - if (Arg) - IS.Diagnose(S, SubEntity, SubKind, Arg); - else - IS.Diagnose(S, SubEntity, SubKind, std::nullopt); + IS.Diagnose(S, SubEntity, SubKind, Arg ? ArrayRef(Arg) : std::nullopt); } else { Sequence.SetFailed( InitializationSequence::FK_ParenthesizedListInitFailed); @@ -5479,10 +5445,8 @@ static void TryOrBuildParenListInitialization( } if (!VerifyOnly) { ExprResult ER; - if (Arg) - ER = IS.Perform(S, SubEntity, SubKind, Arg); - else - ER = IS.Perform(S, SubEntity, SubKind, std::nullopt); + ER = IS.Perform(S, SubEntity, SubKind, + Arg ? MultiExprArg(Arg) : std::nullopt); if (InitExpr) *InitExpr = ER.get(); else @@ -10439,40 +10403,53 @@ static void DiagnoseNarrowingInInitList(Sema &S, // No narrowing occurred. return; - case NK_Type_Narrowing: + case NK_Type_Narrowing: { // This was a floating-to-integer conversion, which is always considered a // narrowing conversion even if the value is a constant and can be // represented exactly as an integer. - S.Diag(PostInit->getBeginLoc(), NarrowingErrs(S.getLangOpts()) - ? diag::ext_init_list_type_narrowing - : diag::warn_init_list_type_narrowing) + QualType T = EntityType.getNonReferenceType(); + S.Diag(PostInit->getBeginLoc(), + NarrowingErrs(S.getLangOpts()) + ? (T == EntityType + ? diag::ext_init_list_type_narrowing + : diag::ext_init_list_type_narrowing_const_reference) + : diag::warn_init_list_type_narrowing) << PostInit->getSourceRange() << PreNarrowingType.getLocalUnqualifiedType() - << EntityType.getNonReferenceType().getLocalUnqualifiedType(); + << T.getLocalUnqualifiedType(); break; + } - case NK_Constant_Narrowing: + case NK_Constant_Narrowing: { // A constant value was narrowed. + QualType T = EntityType.getNonReferenceType(); S.Diag(PostInit->getBeginLoc(), NarrowingErrs(S.getLangOpts()) - ? diag::ext_init_list_constant_narrowing + ? (T == EntityType + ? diag::ext_init_list_constant_narrowing + : diag::ext_init_list_constant_narrowing_const_reference) : diag::warn_init_list_constant_narrowing) << PostInit->getSourceRange() << ConstantValue.getAsString(S.getASTContext(), ConstantType) << EntityType.getNonReferenceType().getLocalUnqualifiedType(); break; + } - case NK_Variable_Narrowing: + case NK_Variable_Narrowing: { // A variable's value may have been narrowed. + QualType T = EntityType.getNonReferenceType(); S.Diag(PostInit->getBeginLoc(), NarrowingErrs(S.getLangOpts()) - ? diag::ext_init_list_variable_narrowing + ? (T == EntityType + ? diag::ext_init_list_variable_narrowing + : diag::ext_init_list_variable_narrowing_const_reference) : diag::warn_init_list_variable_narrowing) << PostInit->getSourceRange() << PreNarrowingType.getLocalUnqualifiedType() << EntityType.getNonReferenceType().getLocalUnqualifiedType(); break; } + } SmallString<128> StaticCast; llvm::raw_svector_ostream OS(StaticCast); @@ -10590,7 +10567,7 @@ static bool isOrIsDerivedFromSpecializationOf(CXXRecordDecl *RD, QualType Sema::DeduceTemplateSpecializationFromInitializer( TypeSourceInfo *TSInfo, const InitializedEntity &Entity, - const InitializationKind &Kind, MultiExprArg Inits, ParenListExpr *PL) { + const InitializationKind &Kind, MultiExprArg Inits) { auto *DeducedTST = dyn_cast<DeducedTemplateSpecializationType>( TSInfo->getType()->getContainedDeducedType()); assert(DeducedTST && "not a deduced template specialization type"); @@ -10821,9 +10798,12 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer( if (getLangOpts().CPlusPlus20 && !HasAnyDeductionGuide) { if (ListInit && ListInit->getNumInits()) { SynthesizeAggrGuide(ListInit); - } else if (PL && PL->getNumExprs()) { - InitListExpr TempListInit(getASTContext(), PL->getLParenLoc(), - PL->exprs(), PL->getRParenLoc()); + } else if (Inits.size()) { // parenthesized expression-list + // Inits are expressions inside the parentheses. We don't have + // the parentheses source locations, use the begin/end of Inits as the + // best heuristic. + InitListExpr TempListInit(getASTContext(), Inits.front()->getBeginLoc(), + Inits, Inits.back()->getEndLoc()); SynthesizeAggrGuide(&TempListInit); } } diff --git a/contrib/llvm-project/clang/lib/Sema/SemaOpenMP.cpp b/contrib/llvm-project/clang/lib/Sema/SemaOpenMP.cpp index e400f248d15a..3826994ef212 100644 --- a/contrib/llvm-project/clang/lib/Sema/SemaOpenMP.cpp +++ b/contrib/llvm-project/clang/lib/Sema/SemaOpenMP.cpp @@ -14658,6 +14658,19 @@ StmtResult Sema::ActOnOpenMPTargetTeamsDirective(ArrayRef<OMPClause *> Clauses, } setFunctionHasBranchProtectedScope(); + const OMPClause *BareClause = nullptr; + bool HasThreadLimitAndNumTeamsClause = hasClauses(Clauses, OMPC_num_teams) && + hasClauses(Clauses, OMPC_thread_limit); + bool HasBareClause = llvm::any_of(Clauses, [&](const OMPClause *C) { + BareClause = C; + return C->getClauseKind() == OMPC_ompx_bare; + }); + + if (HasBareClause && !HasThreadLimitAndNumTeamsClause) { + Diag(BareClause->getBeginLoc(), diag::err_ompx_bare_no_grid); + return StmtError(); + } + return OMPTargetTeamsDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt); } diff --git a/contrib/llvm-project/clang/lib/Sema/SemaRISCVVectorLookup.cpp b/contrib/llvm-project/clang/lib/Sema/SemaRISCVVectorLookup.cpp index e4642e4da016..3ed3e6195441 100644 --- a/contrib/llvm-project/clang/lib/Sema/SemaRISCVVectorLookup.cpp +++ b/contrib/llvm-project/clang/lib/Sema/SemaRISCVVectorLookup.cpp @@ -206,15 +206,16 @@ void RISCVIntrinsicManagerImpl::ConstructRVVIntrinsics( {"xsfvfwmaccqqq", RVV_REQ_Xsfvfwmaccqqq}, {"xsfvqmaccdod", RVV_REQ_Xsfvqmaccdod}, {"xsfvqmaccqoq", RVV_REQ_Xsfvqmaccqoq}, - {"experimental-zvbb", RVV_REQ_Zvbb}, - {"experimental-zvbc", RVV_REQ_Zvbc}, - {"experimental-zvkb", RVV_REQ_Zvkb}, - {"experimental-zvkg", RVV_REQ_Zvkg}, - {"experimental-zvkned", RVV_REQ_Zvkned}, - {"experimental-zvknha", RVV_REQ_Zvknha}, - {"experimental-zvknhb", RVV_REQ_Zvknhb}, - {"experimental-zvksed", RVV_REQ_Zvksed}, - {"experimental-zvksh", RVV_REQ_Zvksh}}; + {"zvbb", RVV_REQ_Zvbb}, + {"zvbc", RVV_REQ_Zvbc}, + {"zvkb", RVV_REQ_Zvkb}, + {"zvkg", RVV_REQ_Zvkg}, + {"zvkned", RVV_REQ_Zvkned}, + {"zvknha", RVV_REQ_Zvknha}, + {"zvknhb", RVV_REQ_Zvknhb}, + {"zvksed", RVV_REQ_Zvksed}, + {"zvksh", RVV_REQ_Zvksh}, + {"experimental", RVV_REQ_Experimental}}; // Construction of RVVIntrinsicRecords need to sync with createRVVIntrinsics // in RISCVVEmitter.cpp. diff --git a/contrib/llvm-project/clang/lib/Sema/SemaStmt.cpp b/contrib/llvm-project/clang/lib/Sema/SemaStmt.cpp index 63348d27a8c9..f0b03db69084 100644 --- a/contrib/llvm-project/clang/lib/Sema/SemaStmt.cpp +++ b/contrib/llvm-project/clang/lib/Sema/SemaStmt.cpp @@ -1271,6 +1271,9 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, bool CaseListIsErroneous = false; + // FIXME: We'd better diagnose missing or duplicate default labels even + // in the dependent case. Because default labels themselves are never + // dependent. for (SwitchCase *SC = SS->getSwitchCaseList(); SC && !HasDependentValue; SC = SC->getNextSwitchCase()) { @@ -1327,9 +1330,6 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, } } - if (!TheDefaultStmt) - Diag(SwitchLoc, diag::warn_switch_default); - if (!HasDependentValue) { // If we don't have a default statement, check whether the // condition is constant. @@ -1344,6 +1344,7 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, assert(!HasConstantCond || (ConstantCondValue.getBitWidth() == CondWidth && ConstantCondValue.isSigned() == CondIsSigned)); + Diag(SwitchLoc, diag::warn_switch_default); } bool ShouldCheckConstantCond = HasConstantCond; diff --git a/contrib/llvm-project/clang/lib/Sema/SemaTemplate.cpp b/contrib/llvm-project/clang/lib/Sema/SemaTemplate.cpp index f10abeaba0d4..5fcc39ec7005 100644 --- a/contrib/llvm-project/clang/lib/Sema/SemaTemplate.cpp +++ b/contrib/llvm-project/clang/lib/Sema/SemaTemplate.cpp @@ -1824,6 +1824,15 @@ static void SetNestedNameSpecifier(Sema &S, TagDecl *T, T->setQualifierInfo(SS.getWithLocInContext(S.Context)); } +// Returns the template parameter list with all default template argument +// information. +static TemplateParameterList *GetTemplateParameterList(TemplateDecl *TD) { + // Make sure we get the template parameter list from the most + // recent declaration, since that is the only one that is guaranteed to + // have all the default template argument information. + return cast<TemplateDecl>(TD->getMostRecentDecl())->getTemplateParameters(); +} + DeclResult Sema::CheckClassTemplate( Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc, @@ -2061,13 +2070,13 @@ DeclResult Sema::CheckClassTemplate( if (!(TUK == TUK_Friend && CurContext->isDependentContext()) && CheckTemplateParameterList( TemplateParams, - PrevClassTemplate - ? PrevClassTemplate->getMostRecentDecl()->getTemplateParameters() - : nullptr, + PrevClassTemplate ? GetTemplateParameterList(PrevClassTemplate) + : nullptr, (SS.isSet() && SemanticContext && SemanticContext->isRecord() && SemanticContext->isDependentContext()) ? TPC_ClassTemplateMember - : TUK == TUK_Friend ? TPC_FriendClassTemplate : TPC_ClassTemplate, + : TUK == TUK_Friend ? TPC_FriendClassTemplate + : TPC_ClassTemplate, SkipBody)) Invalid = true; @@ -2298,7 +2307,7 @@ struct ConvertConstructorToDeductionGuideTransform { // -- The template parameters are the template parameters of the class // template followed by the template parameters (including default // template arguments) of the constructor, if any. - TemplateParameterList *TemplateParams = Template->getTemplateParameters(); + TemplateParameterList *TemplateParams = GetTemplateParameterList(Template); if (FTD) { TemplateParameterList *InnerParams = FTD->getTemplateParameters(); SmallVector<NamedDecl *, 16> AllParams; @@ -2424,7 +2433,7 @@ struct ConvertConstructorToDeductionGuideTransform { Params.push_back(NewParam); } - return buildDeductionGuide(Template->getTemplateParameters(), nullptr, + return buildDeductionGuide(GetTemplateParameterList(Template), nullptr, ExplicitSpecifier(), TSI, Loc, Loc, Loc); } @@ -5956,12 +5965,7 @@ bool Sema::CheckTemplateArgumentList( // template. TemplateArgumentListInfo NewArgs = TemplateArgs; - // Make sure we get the template parameter list from the most - // recent declaration, since that is the only one that is guaranteed to - // have all the default template argument information. - TemplateParameterList *Params = - cast<TemplateDecl>(Template->getMostRecentDecl()) - ->getTemplateParameters(); + TemplateParameterList *Params = GetTemplateParameterList(Template); SourceLocation RAngleLoc = NewArgs.getRAngleLoc(); diff --git a/contrib/llvm-project/clang/lib/Serialization/ASTReaderDecl.cpp b/contrib/llvm-project/clang/lib/Serialization/ASTReaderDecl.cpp index 7140a14aefbf..d989707d5575 100644 --- a/contrib/llvm-project/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/contrib/llvm-project/clang/lib/Serialization/ASTReaderDecl.cpp @@ -584,7 +584,18 @@ void ASTDeclReader::Visit(Decl *D) { void ASTDeclReader::VisitDecl(Decl *D) { BitsUnpacker DeclBits(Record.readInt()); + auto ModuleOwnership = + (Decl::ModuleOwnershipKind)DeclBits.getNextBits(/*Width=*/3); + D->setReferenced(DeclBits.getNextBit()); + D->Used = DeclBits.getNextBit(); + IsDeclMarkedUsed |= D->Used; + D->setAccess((AccessSpecifier)DeclBits.getNextBits(/*Width=*/2)); + D->setImplicit(DeclBits.getNextBit()); bool HasStandaloneLexicalDC = DeclBits.getNextBit(); + bool HasAttrs = DeclBits.getNextBit(); + D->setTopLevelDeclInObjCContainer(DeclBits.getNextBit()); + D->InvalidDecl = DeclBits.getNextBit(); + D->FromASTFile = true; if (D->isTemplateParameter() || D->isTemplateParameterPack() || isa<ParmVarDecl, ObjCTypeParamDecl>(D)) { @@ -623,20 +634,6 @@ void ASTDeclReader::VisitDecl(Decl *D) { } D->setLocation(ThisDeclLoc); - D->InvalidDecl = DeclBits.getNextBit(); - bool HasAttrs = DeclBits.getNextBit(); - D->setImplicit(DeclBits.getNextBit()); - D->Used = DeclBits.getNextBit(); - IsDeclMarkedUsed |= D->Used; - D->setReferenced(DeclBits.getNextBit()); - D->setTopLevelDeclInObjCContainer(DeclBits.getNextBit()); - D->setAccess((AccessSpecifier)DeclBits.getNextBits(/*Width=*/2)); - D->FromASTFile = true; - auto ModuleOwnership = - (Decl::ModuleOwnershipKind)DeclBits.getNextBits(/*Width=*/3); - bool ModulePrivate = - (ModuleOwnership == Decl::ModuleOwnershipKind::ModulePrivate); - if (HasAttrs) { AttrVec Attrs; Record.readAttributes(Attrs); @@ -647,8 +644,9 @@ void ASTDeclReader::VisitDecl(Decl *D) { // Determine whether this declaration is part of a (sub)module. If so, it // may not yet be visible. + bool ModulePrivate = + (ModuleOwnership == Decl::ModuleOwnershipKind::ModulePrivate); if (unsigned SubmoduleID = readSubmoduleID()) { - switch (ModuleOwnership) { case Decl::ModuleOwnershipKind::Visible: ModuleOwnership = Decl::ModuleOwnershipKind::VisibleWhenImported; @@ -1065,9 +1063,11 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { // after everything else is read. BitsUnpacker FunctionDeclBits(Record.readInt()); + FD->setCachedLinkage((Linkage)FunctionDeclBits.getNextBits(/*Width=*/3)); FD->setStorageClass((StorageClass)FunctionDeclBits.getNextBits(/*Width=*/3)); FD->setInlineSpecified(FunctionDeclBits.getNextBit()); FD->setImplicitlyInline(FunctionDeclBits.getNextBit()); + FD->setHasSkippedBody(FunctionDeclBits.getNextBit()); FD->setVirtualAsWritten(FunctionDeclBits.getNextBit()); // We defer calling `FunctionDecl::setPure()` here as for methods of // `CXXTemplateSpecializationDecl`s, we may not have connected up the @@ -1081,16 +1081,14 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { FD->setDefaulted(FunctionDeclBits.getNextBit()); FD->setExplicitlyDefaulted(FunctionDeclBits.getNextBit()); FD->setIneligibleOrNotSelected(FunctionDeclBits.getNextBit()); - FD->setHasImplicitReturnZero(FunctionDeclBits.getNextBit()); FD->setConstexprKind( (ConstexprSpecKind)FunctionDeclBits.getNextBits(/*Width=*/2)); - FD->setUsesSEHTry(FunctionDeclBits.getNextBit()); - FD->setHasSkippedBody(FunctionDeclBits.getNextBit()); + FD->setHasImplicitReturnZero(FunctionDeclBits.getNextBit()); FD->setIsMultiVersion(FunctionDeclBits.getNextBit()); FD->setLateTemplateParsed(FunctionDeclBits.getNextBit()); FD->setFriendConstraintRefersToEnclosingTemplate( FunctionDeclBits.getNextBit()); - FD->setCachedLinkage((Linkage)FunctionDeclBits.getNextBits(/*Width=*/3)); + FD->setUsesSEHTry(FunctionDeclBits.getNextBit()); FD->EndRangeLoc = readSourceLocation(); if (FD->isExplicitlyDefaulted()) @@ -1597,6 +1595,8 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitVarDeclImpl(VarDecl *VD) { VisitDeclaratorDecl(VD); BitsUnpacker VarDeclBits(Record.readInt()); + auto VarLinkage = Linkage(VarDeclBits.getNextBits(/*Width=*/3)); + bool DefGeneratedInModule = VarDeclBits.getNextBit(); VD->VarDeclBits.SClass = (StorageClass)VarDeclBits.getNextBits(/*Width=*/3); VD->VarDeclBits.TSCSpec = VarDeclBits.getNextBits(/*Width=*/2); VD->VarDeclBits.InitStyle = VarDeclBits.getNextBits(/*Width=*/2); @@ -1608,17 +1608,20 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitVarDeclImpl(VarDecl *VD) { VD->NonParmVarDeclBits.ExceptionVar = VarDeclBits.getNextBit(); VD->NonParmVarDeclBits.NRVOVariable = VarDeclBits.getNextBit(); VD->NonParmVarDeclBits.CXXForRangeDecl = VarDeclBits.getNextBit(); - VD->NonParmVarDeclBits.ObjCForDecl = VarDeclBits.getNextBit(); + VD->NonParmVarDeclBits.IsInline = VarDeclBits.getNextBit(); VD->NonParmVarDeclBits.IsInlineSpecified = VarDeclBits.getNextBit(); VD->NonParmVarDeclBits.IsConstexpr = VarDeclBits.getNextBit(); VD->NonParmVarDeclBits.IsInitCapture = VarDeclBits.getNextBit(); VD->NonParmVarDeclBits.PreviousDeclInSameBlockScope = VarDeclBits.getNextBit(); - VD->NonParmVarDeclBits.ImplicitParamKind = - VarDeclBits.getNextBits(/*Width*/ 3); + VD->NonParmVarDeclBits.EscapingByref = VarDeclBits.getNextBit(); HasDeducedType = VarDeclBits.getNextBit(); + VD->NonParmVarDeclBits.ImplicitParamKind = + VarDeclBits.getNextBits(/*Width*/ 3); + + VD->NonParmVarDeclBits.ObjCForDecl = VarDeclBits.getNextBit(); } // If this variable has a deduced type, defer reading that type until we are @@ -1630,7 +1633,6 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitVarDeclImpl(VarDecl *VD) { VD->setType(Reader.GetType(DeferredTypeID)); DeferredTypeID = 0; - auto VarLinkage = Linkage(VarDeclBits.getNextBits(/*Width=*/3)); VD->setCachedLinkage(VarLinkage); // Reconstruct the one piece of the IdentifierNamespace that we need. @@ -1638,7 +1640,7 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitVarDeclImpl(VarDecl *VD) { VD->getLexicalDeclContext()->isFunctionOrMethod()) VD->setLocalExternDecl(); - if (VarDeclBits.getNextBit()) { + if (DefGeneratedInModule) { Reader.DefinitionSource[VD] = Loc.F->Kind == ModuleKind::MK_MainFile || Reader.getContext().getLangOpts().BuildingPCHWithObjectFile; @@ -2660,7 +2662,7 @@ void ASTDeclReader::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) { D->setDeclaredWithTypename(Record.readInt()); - if (Record.readBool()) { + if (D->hasTypeConstraint()) { ConceptReference *CR = nullptr; if (Record.readBool()) CR = Record.readConceptReference(); diff --git a/contrib/llvm-project/clang/lib/Serialization/ASTReaderStmt.cpp b/contrib/llvm-project/clang/lib/Serialization/ASTReaderStmt.cpp index b3a6f619372b..21aed570ba26 100644 --- a/contrib/llvm-project/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/contrib/llvm-project/clang/lib/Serialization/ASTReaderStmt.cpp @@ -73,6 +73,8 @@ namespace clang { ASTRecordReader &Record; llvm::BitstreamCursor &DeclsCursor; + std::optional<BitsUnpacker> CurrentUnpackingBits; + SourceLocation readSourceLocation() { return Record.readSourceLocation(); } @@ -110,6 +112,9 @@ namespace clang { /// itself. static const unsigned NumExprFields = NumStmtFields + 2; + /// The number of bits required for the packing bits for the Expr class. + static const unsigned NumExprBits = 10; + /// Read and initialize a ExplicitTemplateArgumentList structure. void ReadTemplateKWAndArgsInfo(ASTTemplateKWAndArgsInfo &Args, TemplateArgumentLoc *ArgsLocArray, @@ -214,9 +219,11 @@ void ASTStmtReader::VisitAttributedStmt(AttributedStmt *S) { void ASTStmtReader::VisitIfStmt(IfStmt *S) { VisitStmt(S); - bool HasElse = Record.readInt(); - bool HasVar = Record.readInt(); - bool HasInit = Record.readInt(); + CurrentUnpackingBits.emplace(Record.readInt()); + + bool HasElse = CurrentUnpackingBits->getNextBit(); + bool HasVar = CurrentUnpackingBits->getNextBit(); + bool HasInit = CurrentUnpackingBits->getNextBit(); S->setStatementKind(static_cast<IfStatementKind>(Record.readInt())); S->setCond(Record.readSubExpr()); @@ -523,14 +530,15 @@ void ASTStmtReader::VisitCapturedStmt(CapturedStmt *S) { void ASTStmtReader::VisitExpr(Expr *E) { VisitStmt(E); + CurrentUnpackingBits.emplace(Record.readInt()); + E->setDependence(static_cast<ExprDependence>( + CurrentUnpackingBits->getNextBits(/*Width=*/5))); + E->setValueKind(static_cast<ExprValueKind>( + CurrentUnpackingBits->getNextBits(/*Width=*/2))); + E->setObjectKind(static_cast<ExprObjectKind>( + CurrentUnpackingBits->getNextBits(/*Width=*/3))); + E->setType(Record.readType()); - BitsUnpacker ExprBits(Record.readInt()); - E->setDependence( - static_cast<ExprDependence>(ExprBits.getNextBits(/*Width=*/5))); - E->setValueKind( - static_cast<ExprValueKind>(ExprBits.getNextBits(/*Width=*/2))); - E->setObjectKind( - static_cast<ExprObjectKind>(ExprBits.getNextBits(/*Width=*/3))); assert(Record.getIdx() == NumExprFields && "Incorrect expression field count"); } @@ -591,13 +599,17 @@ void ASTStmtReader::VisitPredefinedExpr(PredefinedExpr *E) { void ASTStmtReader::VisitDeclRefExpr(DeclRefExpr *E) { VisitExpr(E); - E->DeclRefExprBits.HasQualifier = Record.readInt(); - E->DeclRefExprBits.HasFoundDecl = Record.readInt(); - E->DeclRefExprBits.HasTemplateKWAndArgsInfo = Record.readInt(); - E->DeclRefExprBits.HadMultipleCandidates = Record.readInt(); - E->DeclRefExprBits.RefersToEnclosingVariableOrCapture = Record.readInt(); - E->DeclRefExprBits.NonOdrUseReason = Record.readInt(); - E->DeclRefExprBits.IsImmediateEscalating = Record.readInt(); + CurrentUnpackingBits.emplace(Record.readInt()); + E->DeclRefExprBits.HadMultipleCandidates = CurrentUnpackingBits->getNextBit(); + E->DeclRefExprBits.RefersToEnclosingVariableOrCapture = + CurrentUnpackingBits->getNextBit(); + E->DeclRefExprBits.NonOdrUseReason = + CurrentUnpackingBits->getNextBits(/*Width=*/2); + E->DeclRefExprBits.IsImmediateEscalating = CurrentUnpackingBits->getNextBit(); + E->DeclRefExprBits.HasFoundDecl = CurrentUnpackingBits->getNextBit(); + E->DeclRefExprBits.HasQualifier = CurrentUnpackingBits->getNextBit(); + E->DeclRefExprBits.HasTemplateKWAndArgsInfo = + CurrentUnpackingBits->getNextBit(); E->DeclRefExprBits.CapturedByCopyInLambdaWithExplicitObjectParameter = false; unsigned NumTemplateArgs = 0; if (E->hasTemplateKWAndArgsInfo()) @@ -706,12 +718,13 @@ void ASTStmtReader::VisitParenListExpr(ParenListExpr *E) { void ASTStmtReader::VisitUnaryOperator(UnaryOperator *E) { VisitExpr(E); - bool hasFP_Features = Record.readInt(); + bool hasFP_Features = CurrentUnpackingBits->getNextBit(); assert(hasFP_Features == E->hasStoredFPFeatures()); E->setSubExpr(Record.readSubExpr()); - E->setOpcode((UnaryOperator::Opcode)Record.readInt()); + E->setOpcode( + (UnaryOperator::Opcode)CurrentUnpackingBits->getNextBits(/*Width=*/5)); E->setOperatorLoc(readSourceLocation()); - E->setCanOverflow(Record.readInt()); + E->setCanOverflow(CurrentUnpackingBits->getNextBit()); if (hasFP_Features) E->setStoredFPFeatures( FPOptionsOverride::getFromOpaqueInt(Record.readInt())); @@ -1000,12 +1013,11 @@ void ASTStmtReader::VisitOMPIteratorExpr(OMPIteratorExpr *E) { void ASTStmtReader::VisitCallExpr(CallExpr *E) { VisitExpr(E); - BitsUnpacker CallExprBits = Record.readInt(); - - unsigned NumArgs = CallExprBits.getNextBits(/*Width=*/16); - bool HasFPFeatures = CallExprBits.getNextBit(); + unsigned NumArgs = Record.readInt(); + CurrentUnpackingBits.emplace(Record.readInt()); E->setADLCallKind( - static_cast<CallExpr::ADLCallKind>(CallExprBits.getNextBit())); + static_cast<CallExpr::ADLCallKind>(CurrentUnpackingBits->getNextBit())); + bool HasFPFeatures = CurrentUnpackingBits->getNextBit(); assert((NumArgs == E->getNumArgs()) && "Wrong NumArgs!"); E->setRParenLoc(readSourceLocation()); E->setCallee(Record.readSubExpr()); @@ -1024,27 +1036,29 @@ void ASTStmtReader::VisitCXXMemberCallExpr(CXXMemberCallExpr *E) { void ASTStmtReader::VisitMemberExpr(MemberExpr *E) { VisitExpr(E); - bool HasQualifier = Record.readInt(); - bool HasFoundDecl = Record.readInt(); - bool HasTemplateInfo = Record.readInt(); + CurrentUnpackingBits.emplace(Record.readInt()); + bool HasQualifier = CurrentUnpackingBits->getNextBit(); + bool HasFoundDecl = CurrentUnpackingBits->getNextBit(); + bool HasTemplateInfo = CurrentUnpackingBits->getNextBit(); unsigned NumTemplateArgs = Record.readInt(); E->Base = Record.readSubExpr(); E->MemberDecl = Record.readDeclAs<ValueDecl>(); E->MemberDNLoc = Record.readDeclarationNameLoc(E->MemberDecl->getDeclName()); E->MemberLoc = Record.readSourceLocation(); - E->MemberExprBits.IsArrow = Record.readInt(); + E->MemberExprBits.IsArrow = CurrentUnpackingBits->getNextBit(); E->MemberExprBits.HasQualifierOrFoundDecl = HasQualifier || HasFoundDecl; E->MemberExprBits.HasTemplateKWAndArgsInfo = HasTemplateInfo; - E->MemberExprBits.HadMultipleCandidates = Record.readInt(); - E->MemberExprBits.NonOdrUseReason = Record.readInt(); + E->MemberExprBits.HadMultipleCandidates = CurrentUnpackingBits->getNextBit(); + E->MemberExprBits.NonOdrUseReason = + CurrentUnpackingBits->getNextBits(/*Width=*/2); E->MemberExprBits.OperatorLoc = Record.readSourceLocation(); if (HasQualifier || HasFoundDecl) { DeclAccessPair FoundDecl; if (HasFoundDecl) { auto *FoundD = Record.readDeclAs<NamedDecl>(); - auto AS = (AccessSpecifier)Record.readInt(); + auto AS = (AccessSpecifier)CurrentUnpackingBits->getNextBits(/*Width=*/2); FoundDecl = DeclAccessPair::make(FoundD, AS); } else { FoundDecl = DeclAccessPair::make(E->MemberDecl, @@ -1091,10 +1105,14 @@ void ASTStmtReader::VisitCastExpr(CastExpr *E) { VisitExpr(E); unsigned NumBaseSpecs = Record.readInt(); assert(NumBaseSpecs == E->path_size()); - unsigned HasFPFeatures = Record.readInt(); + + CurrentUnpackingBits.emplace(Record.readInt()); + E->setCastKind((CastKind)CurrentUnpackingBits->getNextBits(/*Width=*/7)); + unsigned HasFPFeatures = CurrentUnpackingBits->getNextBit(); assert(E->hasStoredFPFeatures() == HasFPFeatures); + E->setSubExpr(Record.readSubExpr()); - E->setCastKind((CastKind)Record.readInt()); + CastExpr::path_iterator BaseI = E->path_begin(); while (NumBaseSpecs--) { auto *BaseSpec = new (Record.getContext()) CXXBaseSpecifier; @@ -1107,10 +1125,12 @@ void ASTStmtReader::VisitCastExpr(CastExpr *E) { } void ASTStmtReader::VisitBinaryOperator(BinaryOperator *E) { - bool hasFP_Features; VisitExpr(E); - E->setHasStoredFPFeatures(hasFP_Features = Record.readInt()); - E->setOpcode((BinaryOperator::Opcode)Record.readInt()); + CurrentUnpackingBits.emplace(Record.readInt()); + E->setOpcode( + (BinaryOperator::Opcode)CurrentUnpackingBits->getNextBits(/*Width=*/6)); + bool hasFP_Features = CurrentUnpackingBits->getNextBit(); + E->setHasStoredFPFeatures(hasFP_Features); E->setLHS(Record.readSubExpr()); E->setRHS(Record.readSubExpr()); E->setOperatorLoc(readSourceLocation()); @@ -1148,7 +1168,7 @@ ASTStmtReader::VisitBinaryConditionalOperator(BinaryConditionalOperator *E) { void ASTStmtReader::VisitImplicitCastExpr(ImplicitCastExpr *E) { VisitCastExpr(E); - E->setIsPartOfExplicitCast(Record.readInt()); + E->setIsPartOfExplicitCast(CurrentUnpackingBits->getNextBit()); } void ASTStmtReader::VisitExplicitCastExpr(ExplicitCastExpr *E) { @@ -1764,8 +1784,8 @@ void ASTStmtReader::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) { SourceRange R = readSourceRange(); E->Loc = R.getBegin(); E->RParenLoc = R.getEnd(); - R = readSourceRange(); - E->AngleBrackets = R; + if (CurrentUnpackingBits->getNextBit()) + E->AngleBrackets = readSourceRange(); } void ASTStmtReader::VisitCXXStaticCastExpr(CXXStaticCastExpr *E) { @@ -1961,9 +1981,10 @@ void ASTStmtReader::VisitCXXDependentScopeMemberExpr( CXXDependentScopeMemberExpr *E) { VisitExpr(E); - bool HasTemplateKWAndArgsInfo = Record.readInt(); unsigned NumTemplateArgs = Record.readInt(); - bool HasFirstQualifierFoundInScope = Record.readInt(); + CurrentUnpackingBits.emplace(Record.readInt()); + bool HasTemplateKWAndArgsInfo = CurrentUnpackingBits->getNextBit(); + bool HasFirstQualifierFoundInScope = CurrentUnpackingBits->getNextBit(); assert((HasTemplateKWAndArgsInfo == E->hasTemplateKWAndArgsInfo()) && "Wrong HasTemplateKWAndArgsInfo!"); @@ -1979,11 +2000,18 @@ void ASTStmtReader::VisitCXXDependentScopeMemberExpr( assert((NumTemplateArgs == E->getNumTemplateArgs()) && "Wrong NumTemplateArgs!"); - E->CXXDependentScopeMemberExprBits.IsArrow = Record.readInt(); - E->CXXDependentScopeMemberExprBits.OperatorLoc = readSourceLocation(); + E->CXXDependentScopeMemberExprBits.IsArrow = + CurrentUnpackingBits->getNextBit(); + E->BaseType = Record.readType(); E->QualifierLoc = Record.readNestedNameSpecifierLoc(); - E->Base = Record.readSubExpr(); + // not ImplicitAccess + if (CurrentUnpackingBits->getNextBit()) + E->Base = Record.readSubExpr(); + else + E->Base = nullptr; + + E->CXXDependentScopeMemberExprBits.OperatorLoc = readSourceLocation(); if (HasFirstQualifierFoundInScope) *E->getTrailingObjects<NamedDecl *>() = readDeclAs<NamedDecl>(); @@ -1995,11 +2023,11 @@ void ASTStmtReader::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) { VisitExpr(E); - if (Record.readInt()) // HasTemplateKWAndArgsInfo + if (CurrentUnpackingBits->getNextBit()) // HasTemplateKWAndArgsInfo ReadTemplateKWAndArgsInfo( *E->getTrailingObjects<ASTTemplateKWAndArgsInfo>(), E->getTrailingObjects<TemplateArgumentLoc>(), - /*NumTemplateArgs=*/Record.readInt()); + /*NumTemplateArgs=*/CurrentUnpackingBits->getNextBits(/*Width=*/16)); E->QualifierLoc = Record.readNestedNameSpecifierLoc(); E->NameInfo = Record.readDeclarationNameInfo(); @@ -2022,15 +2050,15 @@ ASTStmtReader::VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E) { void ASTStmtReader::VisitOverloadExpr(OverloadExpr *E) { VisitExpr(E); - BitsUnpacker OverloadExprBits = Record.readInt(); - unsigned NumResults = OverloadExprBits.getNextBits(/*Width=*/14); - bool HasTemplateKWAndArgsInfo = OverloadExprBits.getNextBit(); + unsigned NumResults = Record.readInt(); + CurrentUnpackingBits.emplace(Record.readInt()); + bool HasTemplateKWAndArgsInfo = CurrentUnpackingBits->getNextBit(); assert((E->getNumDecls() == NumResults) && "Wrong NumResults!"); assert((E->hasTemplateKWAndArgsInfo() == HasTemplateKWAndArgsInfo) && "Wrong HasTemplateKWAndArgsInfo!"); if (HasTemplateKWAndArgsInfo) { - unsigned NumTemplateArgs = OverloadExprBits.getNextBits(/*Width=*/14); + unsigned NumTemplateArgs = Record.readInt(); ReadTemplateKWAndArgsInfo(*E->getTrailingASTTemplateKWAndArgsInfo(), E->getTrailingTemplateArgumentLoc(), NumTemplateArgs); @@ -2057,17 +2085,24 @@ void ASTStmtReader::VisitOverloadExpr(OverloadExpr *E) { void ASTStmtReader::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E) { VisitOverloadExpr(E); - E->UnresolvedMemberExprBits.IsArrow = Record.readInt(); - E->UnresolvedMemberExprBits.HasUnresolvedUsing = Record.readInt(); - E->Base = Record.readSubExpr(); - E->BaseType = Record.readType(); + E->UnresolvedMemberExprBits.IsArrow = CurrentUnpackingBits->getNextBit(); + E->UnresolvedMemberExprBits.HasUnresolvedUsing = + CurrentUnpackingBits->getNextBit(); + + if (/*!isImplicitAccess=*/CurrentUnpackingBits->getNextBit()) + E->Base = Record.readSubExpr(); + else + E->Base = nullptr; + E->OperatorLoc = readSourceLocation(); + + E->BaseType = Record.readType(); } void ASTStmtReader::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) { VisitOverloadExpr(E); - E->UnresolvedLookupExprBits.RequiresADL = Record.readInt(); - E->UnresolvedLookupExprBits.Overloaded = Record.readInt(); + E->UnresolvedLookupExprBits.RequiresADL = CurrentUnpackingBits->getNextBit(); + E->UnresolvedLookupExprBits.Overloaded = CurrentUnpackingBits->getNextBit(); E->NamingClass = readDeclAs<CXXRecordDecl>(); } @@ -2142,9 +2177,12 @@ void ASTStmtReader::VisitSubstNonTypeTemplateParmExpr( SubstNonTypeTemplateParmExpr *E) { VisitExpr(E); E->AssociatedDeclAndRef.setPointer(readDeclAs<Decl>()); - E->AssociatedDeclAndRef.setInt(Record.readInt()); - E->Index = Record.readInt(); - E->PackIndex = Record.readInt(); + E->AssociatedDeclAndRef.setInt(CurrentUnpackingBits->getNextBit()); + E->Index = CurrentUnpackingBits->getNextBits(/*Width=*/12); + if (CurrentUnpackingBits->getNextBit()) + E->PackIndex = Record.readInt(); + else + E->PackIndex = 0; E->SubstNonTypeTemplateParmExprBits.NameLoc = readSourceLocation(); E->Replacement = Record.readSubExpr(); } @@ -2836,11 +2874,12 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { S = new (Context) NullStmt(Empty); break; - case STMT_COMPOUND: - S = CompoundStmt::CreateEmpty( - Context, /*NumStmts=*/Record[ASTStmtReader::NumStmtFields], - /*HasFPFeatures=*/Record[ASTStmtReader::NumStmtFields + 1]); + case STMT_COMPOUND: { + unsigned NumStmts = Record[ASTStmtReader::NumStmtFields]; + bool HasFPFeatures = Record[ASTStmtReader::NumStmtFields + 1]; + S = CompoundStmt::CreateEmpty(Context, NumStmts, HasFPFeatures); break; + } case STMT_CASE: S = CaseStmt::CreateEmpty( @@ -2862,13 +2901,14 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { /*NumAttrs*/Record[ASTStmtReader::NumStmtFields]); break; - case STMT_IF: - S = IfStmt::CreateEmpty( - Context, - /* HasElse=*/Record[ASTStmtReader::NumStmtFields], - /* HasVar=*/Record[ASTStmtReader::NumStmtFields + 1], - /* HasInit=*/Record[ASTStmtReader::NumStmtFields + 2]); + case STMT_IF: { + BitsUnpacker IfStmtBits(Record[ASTStmtReader::NumStmtFields]); + bool HasElse = IfStmtBits.getNextBit(); + bool HasVar = IfStmtBits.getNextBit(); + bool HasInit = IfStmtBits.getNextBit(); + S = IfStmt::CreateEmpty(Context, HasElse, HasVar, HasInit); break; + } case STMT_SWITCH: S = SwitchStmt::CreateEmpty( @@ -2945,17 +2985,19 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { /*HasFunctionName*/ Record[ASTStmtReader::NumExprFields]); break; - case EXPR_DECL_REF: - S = DeclRefExpr::CreateEmpty( - Context, - /*HasQualifier=*/Record[ASTStmtReader::NumExprFields], - /*HasFoundDecl=*/Record[ASTStmtReader::NumExprFields + 1], - /*HasTemplateKWAndArgsInfo=*/Record[ASTStmtReader::NumExprFields + 2], - /*NumTemplateArgs=*/ - Record[ASTStmtReader::NumExprFields + 2] - ? Record[ASTStmtReader::NumExprFields + 7] - : 0); + case EXPR_DECL_REF: { + BitsUnpacker DeclRefExprBits(Record[ASTStmtReader::NumExprFields]); + DeclRefExprBits.advance(5); + bool HasFoundDecl = DeclRefExprBits.getNextBit(); + bool HasQualifier = DeclRefExprBits.getNextBit(); + bool HasTemplateKWAndArgsInfo = DeclRefExprBits.getNextBit(); + unsigned NumTemplateArgs = HasTemplateKWAndArgsInfo + ? Record[ASTStmtReader::NumExprFields + 1] + : 0; + S = DeclRefExpr::CreateEmpty(Context, HasQualifier, HasFoundDecl, + HasTemplateKWAndArgsInfo, NumTemplateArgs); break; + } case EXPR_INTEGER_LITERAL: S = IntegerLiteral::Create(Context, Empty); @@ -2995,10 +3037,13 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { /* NumExprs=*/Record[ASTStmtReader::NumExprFields]); break; - case EXPR_UNARY_OPERATOR: - S = UnaryOperator::CreateEmpty(Context, - Record[ASTStmtReader::NumExprFields]); + case EXPR_UNARY_OPERATOR: { + BitsUnpacker UnaryOperatorBits(Record[ASTStmtReader::NumStmtFields]); + UnaryOperatorBits.advance(ASTStmtReader::NumExprBits); + bool HasFPFeatures = UnaryOperatorBits.getNextBit(); + S = UnaryOperator::CreateEmpty(Context, HasFPFeatures); break; + } case EXPR_OFFSETOF: S = OffsetOfExpr::CreateEmpty(Context, @@ -3033,8 +3078,9 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { break; case EXPR_CALL: { - BitsUnpacker CallExprBits(Record[ASTStmtReader::NumExprFields]); - auto NumArgs = CallExprBits.getNextBits(/*Width=*/16); + auto NumArgs = Record[ASTStmtReader::NumExprFields]; + BitsUnpacker CallExprBits(Record[ASTStmtReader::NumExprFields + 1]); + CallExprBits.advance(1); auto HasFPFeatures = CallExprBits.getNextBit(); S = CallExpr::CreateEmpty(Context, NumArgs, HasFPFeatures, Empty); break; @@ -3045,22 +3091,32 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { Context, /*NumArgs=*/Record[ASTStmtReader::NumExprFields]); break; - case EXPR_MEMBER: - S = MemberExpr::CreateEmpty(Context, Record[ASTStmtReader::NumExprFields], - Record[ASTStmtReader::NumExprFields + 1], - Record[ASTStmtReader::NumExprFields + 2], - Record[ASTStmtReader::NumExprFields + 3]); + case EXPR_MEMBER: { + BitsUnpacker ExprMemberBits(Record[ASTStmtReader::NumExprFields]); + bool HasQualifier = ExprMemberBits.getNextBit(); + bool HasFoundDecl = ExprMemberBits.getNextBit(); + bool HasTemplateInfo = ExprMemberBits.getNextBit(); + unsigned NumTemplateArgs = Record[ASTStmtReader::NumExprFields + 1]; + S = MemberExpr::CreateEmpty(Context, HasQualifier, HasFoundDecl, + HasTemplateInfo, NumTemplateArgs); break; + } - case EXPR_BINARY_OPERATOR: - S = BinaryOperator::CreateEmpty(Context, - Record[ASTStmtReader::NumExprFields]); + case EXPR_BINARY_OPERATOR: { + BitsUnpacker BinaryOperatorBits(Record[ASTStmtReader::NumExprFields]); + BinaryOperatorBits.advance(/*Size of opcode*/ 6); + bool HasFPFeatures = BinaryOperatorBits.getNextBit(); + S = BinaryOperator::CreateEmpty(Context, HasFPFeatures); break; + } - case EXPR_COMPOUND_ASSIGN_OPERATOR: - S = CompoundAssignOperator::CreateEmpty( - Context, Record[ASTStmtReader::NumExprFields]); + case EXPR_COMPOUND_ASSIGN_OPERATOR: { + BitsUnpacker BinaryOperatorBits(Record[ASTStmtReader::NumExprFields]); + BinaryOperatorBits.advance(/*Size of opcode*/ 6); + bool HasFPFeatures = BinaryOperatorBits.getNextBit(); + S = CompoundAssignOperator::CreateEmpty(Context, HasFPFeatures); break; + } case EXPR_CONDITIONAL_OPERATOR: S = new (Context) ConditionalOperator(Empty); @@ -3070,19 +3126,23 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { S = new (Context) BinaryConditionalOperator(Empty); break; - case EXPR_IMPLICIT_CAST: - S = ImplicitCastExpr::CreateEmpty( - Context, - /*PathSize*/ Record[ASTStmtReader::NumExprFields], - /*HasFPFeatures*/ Record[ASTStmtReader::NumExprFields + 1]); + case EXPR_IMPLICIT_CAST: { + unsigned PathSize = Record[ASTStmtReader::NumExprFields]; + BitsUnpacker CastExprBits(Record[ASTStmtReader::NumExprFields + 1]); + CastExprBits.advance(7); + bool HasFPFeatures = CastExprBits.getNextBit(); + S = ImplicitCastExpr::CreateEmpty(Context, PathSize, HasFPFeatures); break; + } - case EXPR_CSTYLE_CAST: - S = CStyleCastExpr::CreateEmpty( - Context, - /*PathSize*/ Record[ASTStmtReader::NumExprFields], - /*HasFPFeatures*/ Record[ASTStmtReader::NumExprFields + 1]); + case EXPR_CSTYLE_CAST: { + unsigned PathSize = Record[ASTStmtReader::NumExprFields]; + BitsUnpacker CastExprBits(Record[ASTStmtReader::NumExprFields + 1]); + CastExprBits.advance(7); + bool HasFPFeatures = CastExprBits.getNextBit(); + S = CStyleCastExpr::CreateEmpty(Context, PathSize, HasFPFeatures); break; + } case EXPR_COMPOUND_LITERAL: S = new (Context) CompoundLiteralExpr(Empty); @@ -3777,8 +3837,9 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { } case EXPR_CXX_OPERATOR_CALL: { - BitsUnpacker CallExprBits(Record[ASTStmtReader::NumExprFields]); - auto NumArgs = CallExprBits.getNextBits(/*Width=*/16); + auto NumArgs = Record[ASTStmtReader::NumExprFields]; + BitsUnpacker CallExprBits(Record[ASTStmtReader::NumExprFields + 1]); + CallExprBits.advance(1); auto HasFPFeatures = CallExprBits.getNextBit(); S = CXXOperatorCallExpr::CreateEmpty(Context, NumArgs, HasFPFeatures, Empty); @@ -3786,8 +3847,9 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { } case EXPR_CXX_MEMBER_CALL: { - BitsUnpacker CallExprBits(Record[ASTStmtReader::NumExprFields]); - auto NumArgs = CallExprBits.getNextBits(/*Width=*/16); + auto NumArgs = Record[ASTStmtReader::NumExprFields]; + BitsUnpacker CallExprBits(Record[ASTStmtReader::NumExprFields + 1]); + CallExprBits.advance(1); auto HasFPFeatures = CallExprBits.getNextBit(); S = CXXMemberCallExpr::CreateEmpty(Context, NumArgs, HasFPFeatures, Empty); @@ -3814,22 +3876,26 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { /* NumArgs=*/Record[ASTStmtReader::NumExprFields]); break; - case EXPR_CXX_STATIC_CAST: - S = CXXStaticCastExpr::CreateEmpty( - Context, - /*PathSize*/ Record[ASTStmtReader::NumExprFields], - /*HasFPFeatures*/ Record[ASTStmtReader::NumExprFields + 1]); + case EXPR_CXX_STATIC_CAST: { + unsigned PathSize = Record[ASTStmtReader::NumExprFields]; + BitsUnpacker CastExprBits(Record[ASTStmtReader::NumExprFields + 1]); + CastExprBits.advance(7); + bool HasFPFeatures = CastExprBits.getNextBit(); + S = CXXStaticCastExpr::CreateEmpty(Context, PathSize, HasFPFeatures); break; + } - case EXPR_CXX_DYNAMIC_CAST: - S = CXXDynamicCastExpr::CreateEmpty(Context, - /*PathSize*/ Record[ASTStmtReader::NumExprFields]); + case EXPR_CXX_DYNAMIC_CAST: { + unsigned PathSize = Record[ASTStmtReader::NumExprFields]; + S = CXXDynamicCastExpr::CreateEmpty(Context, PathSize); break; + } - case EXPR_CXX_REINTERPRET_CAST: - S = CXXReinterpretCastExpr::CreateEmpty(Context, - /*PathSize*/ Record[ASTStmtReader::NumExprFields]); + case EXPR_CXX_REINTERPRET_CAST: { + unsigned PathSize = Record[ASTStmtReader::NumExprFields]; + S = CXXReinterpretCastExpr::CreateEmpty(Context, PathSize); break; + } case EXPR_CXX_CONST_CAST: S = CXXConstCastExpr::CreateEmpty(Context); @@ -3839,21 +3905,28 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { S = CXXAddrspaceCastExpr::CreateEmpty(Context); break; - case EXPR_CXX_FUNCTIONAL_CAST: - S = CXXFunctionalCastExpr::CreateEmpty( - Context, - /*PathSize*/ Record[ASTStmtReader::NumExprFields], - /*HasFPFeatures*/ Record[ASTStmtReader::NumExprFields + 1]); + case EXPR_CXX_FUNCTIONAL_CAST: { + unsigned PathSize = Record[ASTStmtReader::NumExprFields]; + BitsUnpacker CastExprBits(Record[ASTStmtReader::NumExprFields + 1]); + CastExprBits.advance(7); + bool HasFPFeatures = CastExprBits.getNextBit(); + S = CXXFunctionalCastExpr::CreateEmpty(Context, PathSize, HasFPFeatures); break; + } - case EXPR_BUILTIN_BIT_CAST: - assert(Record[ASTStmtReader::NumExprFields] == 0 && "Wrong PathSize!"); + case EXPR_BUILTIN_BIT_CAST: { +#ifndef NDEBUG + unsigned PathSize = Record[ASTStmtReader::NumExprFields]; + assert(PathSize == 0 && "Wrong PathSize!"); +#endif S = new (Context) BuiltinBitCastExpr(Empty); break; + } case EXPR_USER_DEFINED_LITERAL: { - BitsUnpacker CallExprBits(Record[ASTStmtReader::NumExprFields]); - auto NumArgs = CallExprBits.getNextBits(/*Width=*/16); + auto NumArgs = Record[ASTStmtReader::NumExprFields]; + BitsUnpacker CallExprBits(Record[ASTStmtReader::NumExprFields + 1]); + CallExprBits.advance(1); auto HasFPFeatures = CallExprBits.getNextBit(); S = UserDefinedLiteral::CreateEmpty(Context, NumArgs, HasFPFeatures, Empty); @@ -3944,47 +4017,62 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { Record[ASTStmtReader::NumExprFields]); break; - case EXPR_CXX_DEPENDENT_SCOPE_MEMBER: + case EXPR_CXX_DEPENDENT_SCOPE_MEMBER: { + unsigned NumTemplateArgs = Record[ASTStmtReader::NumExprFields]; + BitsUnpacker DependentScopeMemberBits( + Record[ASTStmtReader::NumExprFields + 1]); + bool HasTemplateKWAndArgsInfo = DependentScopeMemberBits.getNextBit(); + + bool HasFirstQualifierFoundInScope = + DependentScopeMemberBits.getNextBit(); S = CXXDependentScopeMemberExpr::CreateEmpty( - Context, - /*HasTemplateKWAndArgsInfo=*/Record[ASTStmtReader::NumExprFields], - /*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields + 1], - /*HasFirstQualifierFoundInScope=*/ - Record[ASTStmtReader::NumExprFields + 2]); + Context, HasTemplateKWAndArgsInfo, NumTemplateArgs, + HasFirstQualifierFoundInScope); break; + } - case EXPR_CXX_DEPENDENT_SCOPE_DECL_REF: - S = DependentScopeDeclRefExpr::CreateEmpty(Context, - /*HasTemplateKWAndArgsInfo=*/Record[ASTStmtReader::NumExprFields], - /*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields] - ? Record[ASTStmtReader::NumExprFields + 1] - : 0); + case EXPR_CXX_DEPENDENT_SCOPE_DECL_REF: { + BitsUnpacker DependentScopeDeclRefBits( + Record[ASTStmtReader::NumStmtFields]); + DependentScopeDeclRefBits.advance(ASTStmtReader::NumExprBits); + bool HasTemplateKWAndArgsInfo = DependentScopeDeclRefBits.getNextBit(); + unsigned NumTemplateArgs = + HasTemplateKWAndArgsInfo + ? DependentScopeDeclRefBits.getNextBits(/*Width=*/16) + : 0; + S = DependentScopeDeclRefExpr::CreateEmpty( + Context, HasTemplateKWAndArgsInfo, NumTemplateArgs); break; + } case EXPR_CXX_UNRESOLVED_CONSTRUCT: S = CXXUnresolvedConstructExpr::CreateEmpty(Context, /*NumArgs=*/Record[ASTStmtReader::NumExprFields]); break; - case EXPR_CXX_UNRESOLVED_MEMBER: + case EXPR_CXX_UNRESOLVED_MEMBER: { + auto NumResults = Record[ASTStmtReader::NumExprFields]; + BitsUnpacker OverloadExprBits(Record[ASTStmtReader::NumExprFields + 1]); + auto HasTemplateKWAndArgsInfo = OverloadExprBits.getNextBit(); + auto NumTemplateArgs = HasTemplateKWAndArgsInfo + ? Record[ASTStmtReader::NumExprFields + 2] + : 0; S = UnresolvedMemberExpr::CreateEmpty( - Context, - /*NumResults=*/Record[ASTStmtReader::NumExprFields] & ((1 << 14) - 1), - /*HasTemplateKWAndArgsInfo=*/ - (Record[ASTStmtReader::NumExprFields] >> 14) & (0x1), - /*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields] >> 14 & - ((1 << 14) - 1)); + Context, NumResults, HasTemplateKWAndArgsInfo, NumTemplateArgs); break; + } - case EXPR_CXX_UNRESOLVED_LOOKUP: + case EXPR_CXX_UNRESOLVED_LOOKUP: { + auto NumResults = Record[ASTStmtReader::NumExprFields]; + BitsUnpacker OverloadExprBits(Record[ASTStmtReader::NumExprFields + 1]); + auto HasTemplateKWAndArgsInfo = OverloadExprBits.getNextBit(); + auto NumTemplateArgs = HasTemplateKWAndArgsInfo + ? Record[ASTStmtReader::NumExprFields + 2] + : 0; S = UnresolvedLookupExpr::CreateEmpty( - Context, - /*NumResults=*/Record[ASTStmtReader::NumExprFields] & ((1 << 14) - 1), - /*HasTemplateKWAndArgsInfo=*/ - (Record[ASTStmtReader::NumExprFields] >> 14) & (0x1), - /*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields] >> 14 & - ((1 << 14) - 1)); + Context, NumResults, HasTemplateKWAndArgsInfo, NumTemplateArgs); break; + } case EXPR_TYPE_TRAIT: S = TypeTraitExpr::CreateDeserialized(Context, @@ -4044,8 +4132,9 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { break; case EXPR_CUDA_KERNEL_CALL: { - BitsUnpacker CallExprBits(Record[ASTStmtReader::NumExprFields]); - auto NumArgs = CallExprBits.getNextBits(/*Width=*/16); + auto NumArgs = Record[ASTStmtReader::NumExprFields]; + BitsUnpacker CallExprBits(Record[ASTStmtReader::NumExprFields + 1]); + CallExprBits.advance(1); auto HasFPFeatures = CallExprBits.getNextBit(); S = CUDAKernelCallExpr::CreateEmpty(Context, NumArgs, HasFPFeatures, Empty); diff --git a/contrib/llvm-project/clang/lib/Serialization/ASTWriter.cpp b/contrib/llvm-project/clang/lib/Serialization/ASTWriter.cpp index 91eb2af8f8ad..78939bfd533f 100644 --- a/contrib/llvm-project/clang/lib/Serialization/ASTWriter.cpp +++ b/contrib/llvm-project/clang/lib/Serialization/ASTWriter.cpp @@ -6003,12 +6003,17 @@ void ASTRecordWriter::AddCXXDefinitionData(const CXXRecordDecl *D) { BitsPacker DefinitionBits; -#define FIELD(Name, Width, Merge) DefinitionBits.addBits(Data.Name, Width); +#define FIELD(Name, Width, Merge) \ + if (!DefinitionBits.canWriteNextNBits(Width)) { \ + Record->push_back(DefinitionBits); \ + DefinitionBits.reset(0); \ + } \ + DefinitionBits.addBits(Data.Name, Width); + #include "clang/AST/CXXRecordDeclDefinitionBits.def" #undef FIELD - while (DefinitionBits.hasUnconsumedValues()) - Record->push_back(DefinitionBits.getNextValue()); + Record->push_back(DefinitionBits); // getODRHash will compute the ODRHash if it has not been previously computed. Record->push_back(D->getODRHash()); @@ -6047,7 +6052,7 @@ void ASTRecordWriter::AddCXXDefinitionData(const CXXRecordDecl *D) { LambdaBits.addBits(Lambda.CaptureDefault, /*Width=*/2); LambdaBits.addBits(Lambda.NumCaptures, /*Width=*/15); LambdaBits.addBit(Lambda.HasKnownInternalLinkage); - Record->push_back(LambdaBits.getNextValue()); + Record->push_back(LambdaBits); Record->push_back(Lambda.NumExplicitCaptures); Record->push_back(Lambda.ManglingNumber); @@ -6058,10 +6063,12 @@ void ASTRecordWriter::AddCXXDefinitionData(const CXXRecordDecl *D) { for (unsigned I = 0, N = Lambda.NumCaptures; I != N; ++I) { const LambdaCapture &Capture = Lambda.Captures.front()[I]; AddSourceLocation(Capture.getLocation()); + BitsPacker CaptureBits; CaptureBits.addBit(Capture.isImplicit()); CaptureBits.addBits(Capture.getCaptureKind(), /*Width=*/3); Record->push_back(CaptureBits); + switch (Capture.getCaptureKind()) { case LCK_StarThis: case LCK_This: diff --git a/contrib/llvm-project/clang/lib/Serialization/ASTWriterDecl.cpp b/contrib/llvm-project/clang/lib/Serialization/ASTWriterDecl.cpp index 43169b2befc6..2554abc682a1 100644 --- a/contrib/llvm-project/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/contrib/llvm-project/clang/lib/Serialization/ASTWriterDecl.cpp @@ -321,15 +321,25 @@ void ASTDeclWriter::Visit(Decl *D) { void ASTDeclWriter::VisitDecl(Decl *D) { BitsPacker DeclBits; + + // The order matters here. It will be better to put the bit with higher + // probability to be 0 in the end of the bits. + // + // Since we're using VBR6 format to store it. + // It will be pretty effient if all the higher bits are 0. + // For example, if we need to pack 8 bits into a value and the stored value + // is 0xf0, the actual stored value will be 0b000111'110000, which takes 12 + // bits actually. However, if we changed the order to be 0x0f, then we can + // store it as 0b001111, which takes 6 bits only now. + DeclBits.addBits((uint64_t)D->getModuleOwnershipKind(), /*BitWidth=*/3); + DeclBits.addBit(D->isReferenced()); + DeclBits.addBit(D->isUsed(false)); + DeclBits.addBits(D->getAccess(), /*BitWidth=*/2); + DeclBits.addBit(D->isImplicit()); DeclBits.addBit(D->getDeclContext() != D->getLexicalDeclContext()); - DeclBits.addBit(D->isInvalidDecl()); DeclBits.addBit(D->hasAttrs()); - DeclBits.addBit(D->isImplicit()); - DeclBits.addBit(D->isUsed(false)); - DeclBits.addBit(D->isReferenced()); DeclBits.addBit(D->isTopLevelDeclInObjCContainer()); - DeclBits.addBits(D->getAccess(), /*BitWidth=*/2); - DeclBits.addBits((uint64_t)D->getModuleOwnershipKind(), /*BitWidth=*/3); + DeclBits.addBit(D->isInvalidDecl()); Record.push_back(DeclBits); Record.AddDeclRef(cast_or_null<Decl>(D->getDeclContext())); @@ -493,21 +503,13 @@ void ASTDeclWriter::VisitEnumDecl(EnumDecl *D) { Record.AddDeclRef(nullptr); } - if (D->getDeclContext() == D->getLexicalDeclContext() && - !D->hasAttrs() && - !D->isImplicit() && - !D->isUsed(false) && - !D->hasExtInfo() && + if (D->getDeclContext() == D->getLexicalDeclContext() && !D->hasAttrs() && + !D->isInvalidDecl() && !D->isImplicit() && !D->hasExtInfo() && !D->getTypedefNameForAnonDecl() && D->getFirstDecl() == D->getMostRecentDecl() && - !D->isInvalidDecl() && - !D->isReferenced() && !D->isTopLevelDeclInObjCContainer() && - D->getAccess() == AS_none && - !D->isModulePrivate() && !CXXRecordDecl::classofKind(D->getKind()) && - !D->getIntegerTypeSourceInfo() && - !D->getMemberSpecializationInfo() && + !D->getIntegerTypeSourceInfo() && !D->getMemberSpecializationInfo() && !needsAnonymousDeclarationNumber(D) && D->getDeclName().getNameKind() == DeclarationName::Identifier) AbbrevToUse = Writer.getDeclEnumAbbrev(); @@ -542,18 +544,11 @@ void ASTDeclWriter::VisitRecordDecl(RecordDecl *D) { if (!isa<CXXRecordDecl>(D)) Record.push_back(D->getODRHash()); - if (D->getDeclContext() == D->getLexicalDeclContext() && - !D->hasAttrs() && - !D->isImplicit() && - !D->isUsed(false) && - !D->hasExtInfo() && + if (D->getDeclContext() == D->getLexicalDeclContext() && !D->hasAttrs() && + !D->isImplicit() && !D->isInvalidDecl() && !D->hasExtInfo() && !D->getTypedefNameForAnonDecl() && D->getFirstDecl() == D->getMostRecentDecl() && - !D->isInvalidDecl() && - !D->isReferenced() && !D->isTopLevelDeclInObjCContainer() && - D->getAccess() == AS_none && - !D->isModulePrivate() && !CXXRecordDecl::classofKind(D->getKind()) && !needsAnonymousDeclarationNumber(D) && D->getDeclName().getNameKind() == DeclarationName::Identifier) @@ -674,11 +669,16 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) { Record.AddDeclarationNameLoc(D->DNLoc, D->getDeclName()); Record.push_back(D->getIdentifierNamespace()); + // The order matters here. It will be better to put the bit with higher + // probability to be 0 in the end of the bits. See the comments in VisitDecl + // for details. BitsPacker FunctionDeclBits; // FIXME: stable encoding + FunctionDeclBits.addBits(llvm::to_underlying(D->getLinkageInternal()), 3); FunctionDeclBits.addBits((uint32_t)D->getStorageClass(), /*BitWidth=*/3); FunctionDeclBits.addBit(D->isInlineSpecified()); FunctionDeclBits.addBit(D->isInlined()); + FunctionDeclBits.addBit(D->hasSkippedBody()); FunctionDeclBits.addBit(D->isVirtualAsWritten()); FunctionDeclBits.addBit(D->isPure()); FunctionDeclBits.addBit(D->hasInheritedPrototype()); @@ -689,14 +689,12 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) { FunctionDeclBits.addBit(D->isDefaulted()); FunctionDeclBits.addBit(D->isExplicitlyDefaulted()); FunctionDeclBits.addBit(D->isIneligibleOrNotSelected()); - FunctionDeclBits.addBit(D->hasImplicitReturnZero()); FunctionDeclBits.addBits((uint64_t)(D->getConstexprKind()), /*BitWidth=*/2); - FunctionDeclBits.addBit(D->usesSEHTry()); - FunctionDeclBits.addBit(D->hasSkippedBody()); + FunctionDeclBits.addBit(D->hasImplicitReturnZero()); FunctionDeclBits.addBit(D->isMultiVersion()); FunctionDeclBits.addBit(D->isLateTemplateParsed()); FunctionDeclBits.addBit(D->FriendConstraintRefersToEnclosingTemplate()); - FunctionDeclBits.addBits(llvm::to_underlying(D->getLinkageInternal()), 3); + FunctionDeclBits.addBit(D->usesSEHTry()); Record.push_back(FunctionDeclBits); Record.AddSourceLocation(D->getEndLoc()); @@ -1060,7 +1058,28 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) { VisitRedeclarable(D); VisitDeclaratorDecl(D); + // The order matters here. It will be better to put the bit with higher + // probability to be 0 in the end of the bits. See the comments in VisitDecl + // for details. BitsPacker VarDeclBits; + VarDeclBits.addBits(llvm::to_underlying(D->getLinkageInternal()), + /*BitWidth=*/3); + + bool ModulesCodegen = false; + if (Writer.WritingModule && D->getStorageDuration() == SD_Static && + !D->getDescribedVarTemplate()) { + // When building a C++20 module interface unit or a partition unit, a + // strong definition in the module interface is provided by the + // compilation of that unit, not by its users. (Inline variables are still + // emitted in module users.) + ModulesCodegen = + (Writer.WritingModule->isInterfaceOrPartition() || + (D->hasAttr<DLLExportAttr>() && + Writer.Context->getLangOpts().BuildingPCHWithObjectFile)) && + Writer.Context->GetGVALinkageForVariable(D) >= GVA_StrongExternal; + } + VarDeclBits.addBit(ModulesCodegen); + VarDeclBits.addBits(D->getStorageClass(), /*BitWidth=*/3); VarDeclBits.addBits(D->getTSCSpec(), /*BitWidth=*/2); VarDeclBits.addBits(D->getInitStyle(), /*BitWidth=*/2); @@ -1072,41 +1091,26 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) { VarDeclBits.addBit(D->isExceptionVariable()); VarDeclBits.addBit(D->isNRVOVariable()); VarDeclBits.addBit(D->isCXXForRangeDecl()); - VarDeclBits.addBit(D->isObjCForDecl()); + VarDeclBits.addBit(D->isInline()); VarDeclBits.addBit(D->isInlineSpecified()); VarDeclBits.addBit(D->isConstexpr()); VarDeclBits.addBit(D->isInitCapture()); VarDeclBits.addBit(D->isPreviousDeclInSameBlockScope()); + VarDeclBits.addBit(D->isEscapingByref()); + HasDeducedType = D->getType()->getContainedDeducedType(); + VarDeclBits.addBit(HasDeducedType); + if (const auto *IPD = dyn_cast<ImplicitParamDecl>(D)) VarDeclBits.addBits(llvm::to_underlying(IPD->getParameterKind()), /*Width=*/3); else VarDeclBits.addBits(0, /*Width=*/3); - VarDeclBits.addBit(D->isEscapingByref()); - HasDeducedType = D->getType()->getContainedDeducedType(); - VarDeclBits.addBit(HasDeducedType); - } - - VarDeclBits.addBits(llvm::to_underlying(D->getLinkageInternal()), /*BitWidth=*/3); - - bool ModulesCodegen = false; - if (Writer.WritingModule && D->getStorageDuration() == SD_Static && - !D->getDescribedVarTemplate()) { - // When building a C++20 module interface unit or a partition unit, a - // strong definition in the module interface is provided by the - // compilation of that unit, not by its users. (Inline variables are still - // emitted in module users.) - ModulesCodegen = - (Writer.WritingModule->isInterfaceOrPartition() || - (D->hasAttr<DLLExportAttr>() && - Writer.Context->getLangOpts().BuildingPCHWithObjectFile)) && - Writer.Context->GetGVALinkageForVariable(D) >= GVA_StrongExternal; + VarDeclBits.addBit(D->isObjCForDecl()); } - VarDeclBits.addBit(ModulesCodegen); Record.push_back(VarDeclBits); if (ModulesCodegen) @@ -1135,29 +1139,17 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) { Record.push_back(VarNotTemplate); } - if (D->getDeclContext() == D->getLexicalDeclContext() && - !D->hasAttrs() && - !D->isImplicit() && - !D->isUsed(false) && - !D->isInvalidDecl() && - !D->isReferenced() && + if (D->getDeclContext() == D->getLexicalDeclContext() && !D->hasAttrs() && !D->isTopLevelDeclInObjCContainer() && - D->getAccess() == AS_none && - !D->isModulePrivate() && !needsAnonymousDeclarationNumber(D) && D->getDeclName().getNameKind() == DeclarationName::Identifier && - !D->hasExtInfo() && - D->getFirstDecl() == D->getMostRecentDecl() && - D->getKind() == Decl::Var && - !D->isInline() && - !D->isConstexpr() && - !D->isInitCapture() && - !D->isPreviousDeclInSameBlockScope() && - !D->isEscapingByref() && - !HasDeducedType && - D->getStorageDuration() != SD_Static && - !D->getDescribedVarTemplate() && - !D->getMemberSpecializationInfo()) + !D->hasExtInfo() && D->getFirstDecl() == D->getMostRecentDecl() && + D->getKind() == Decl::Var && !D->isInline() && !D->isConstexpr() && + !D->isInitCapture() && !D->isPreviousDeclInSameBlockScope() && + !D->isEscapingByref() && !HasDeducedType && + D->getStorageDuration() != SD_Static && !D->getDescribedVarTemplate() && + !D->getMemberSpecializationInfo() && !D->isObjCForDecl() && + !isa<ImplicitParamDecl>(D) && !D->isEscapingByref()) AbbrevToUse = Writer.getDeclVarAbbrev(); Code = serialization::DECL_VAR; @@ -1193,14 +1185,10 @@ void ASTDeclWriter::VisitParmVarDecl(ParmVarDecl *D) { // we dynamically check for the properties that we optimize for, but don't // know are true of all PARM_VAR_DECLs. if (D->getDeclContext() == D->getLexicalDeclContext() && !D->hasAttrs() && - !D->hasExtInfo() && !D->isImplicit() && !D->isUsed(false) && - !D->isInvalidDecl() && !D->isReferenced() && D->getAccess() == AS_none && - !D->isModulePrivate() && D->getStorageClass() == 0 && + !D->hasExtInfo() && D->getStorageClass() == 0 && !D->isInvalidDecl() && + !D->isTopLevelDeclInObjCContainer() && D->getInitStyle() == VarDecl::CInit && // Can params have anything else? - D->getFunctionScopeDepth() == 0 && D->getObjCDeclQualifier() == 0 && - !D->isKNRPromoted() && !D->isExplicitObjectParameter() && - !D->hasInheritedDefaultArg() && D->getInit() == nullptr && - !D->hasUninstantiatedDefaultArg()) // No default expr. + D->getInit() == nullptr) // No default expr. AbbrevToUse = Writer.getDeclParmVarAbbrev(); // Check things we know are true of *every* PARM_VAR_DECL, which is more than @@ -1403,6 +1391,13 @@ void ASTDeclWriter::VisitUsingShadowDecl(UsingShadowDecl *D) { Record.push_back(D->getIdentifierNamespace()); Record.AddDeclRef(D->UsingOrNextShadow); Record.AddDeclRef(Context.getInstantiatedFromUsingShadowDecl(D)); + + if (D->getDeclContext() == D->getLexicalDeclContext() && + D->getFirstDecl() == D->getMostRecentDecl() && !D->hasAttrs() && + !needsAnonymousDeclarationNumber(D) && + D->getDeclName().getNameKind() == DeclarationName::Identifier) + AbbrevToUse = Writer.getDeclUsingShadowAbbrev(); + Code = serialization::DECL_USING_SHADOW; } @@ -1507,10 +1502,32 @@ void ASTDeclWriter::VisitCXXMethodDecl(CXXMethodDecl *D) { D->getFirstDecl() == D->getMostRecentDecl() && !D->isInvalidDecl() && !D->hasAttrs() && !D->isTopLevelDeclInObjCContainer() && D->getDeclName().getNameKind() == DeclarationName::Identifier && - !D->hasExtInfo() && !D->hasInheritedPrototype() && - D->hasWrittenPrototype() && - D->getTemplatedKind() == FunctionDecl::TK_NonTemplate) - AbbrevToUse = Writer.getDeclCXXMethodAbbrev(); + !D->hasExtInfo() && !D->isExplicitlyDefaulted()) { + if (D->getTemplatedKind() == FunctionDecl::TK_NonTemplate || + D->getTemplatedKind() == FunctionDecl::TK_FunctionTemplate || + D->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization || + D->getTemplatedKind() == FunctionDecl::TK_DependentNonTemplate) + AbbrevToUse = Writer.getDeclCXXMethodAbbrev(D->getTemplatedKind()); + else if (D->getTemplatedKind() == + FunctionDecl::TK_FunctionTemplateSpecialization) { + FunctionTemplateSpecializationInfo *FTSInfo = + D->getTemplateSpecializationInfo(); + + if (FTSInfo->TemplateArguments->size() == 1) { + const TemplateArgument &TA = FTSInfo->TemplateArguments->get(0); + if (TA.getKind() == TemplateArgument::Type && + !FTSInfo->TemplateArgumentsAsWritten && + !FTSInfo->getMemberSpecializationInfo()) + AbbrevToUse = Writer.getDeclCXXMethodAbbrev(D->getTemplatedKind()); + } + } else if (D->getTemplatedKind() == + FunctionDecl::TK_DependentFunctionTemplateSpecialization) { + DependentFunctionTemplateSpecializationInfo *DFTSInfo = + D->getDependentSpecializationInfo(); + if (!DFTSInfo->TemplateArgumentsAsWritten) + AbbrevToUse = Writer.getDeclCXXMethodAbbrev(D->getTemplatedKind()); + } + } Code = serialization::DECL_CXX_METHOD; } @@ -1782,7 +1799,7 @@ void ASTDeclWriter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) { Record.push_back(D->wasDeclaredWithTypename()); const TypeConstraint *TC = D->getTypeConstraint(); - Record.push_back(TC != nullptr); + assert((bool)TC == D->hasTypeConstraint()); if (TC) { auto *CR = TC->getConceptReference(); Record.push_back(CR != nullptr); @@ -1800,6 +1817,13 @@ void ASTDeclWriter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) { if (OwnsDefaultArg) Record.AddTypeSourceInfo(D->getDefaultArgumentInfo()); + if (!TC && !OwnsDefaultArg && + D->getDeclContext() == D->getLexicalDeclContext() && + !D->isInvalidDecl() && !D->hasAttrs() && + !D->isTopLevelDeclInObjCContainer() && !D->isImplicit() && + D->getDeclName().getNameKind() == DeclarationName::Identifier) + AbbrevToUse = Writer.getDeclTemplateTypeParmAbbrev(); + Code = serialization::DECL_TEMPLATE_TYPE_PARM; } @@ -2031,6 +2055,106 @@ void ASTDeclWriter::VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D) { // ASTWriter Implementation //===----------------------------------------------------------------------===// +namespace { +template <FunctionDecl::TemplatedKind Kind> +std::shared_ptr<llvm::BitCodeAbbrev> +getFunctionDeclAbbrev(serialization::DeclCode Code) { + using namespace llvm; + + auto Abv = std::make_shared<BitCodeAbbrev>(); + Abv->Add(BitCodeAbbrevOp(Code)); + // RedeclarableDecl + Abv->Add(BitCodeAbbrevOp(0)); // CanonicalDecl + Abv->Add(BitCodeAbbrevOp(Kind)); + if constexpr (Kind == FunctionDecl::TK_NonTemplate) { + + } else if constexpr (Kind == FunctionDecl::TK_FunctionTemplate) { + // DescribedFunctionTemplate + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); + } else if constexpr (Kind == FunctionDecl::TK_DependentNonTemplate) { + // Instantiated From Decl + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); + } else if constexpr (Kind == FunctionDecl::TK_MemberSpecialization) { + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // InstantiatedFrom + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, + 3)); // TemplateSpecializationKind + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Specialized Location + } else if constexpr (Kind == + FunctionDecl::TK_FunctionTemplateSpecialization) { + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Template + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, + 3)); // TemplateSpecializationKind + Abv->Add(BitCodeAbbrevOp(1)); // Template Argument Size + Abv->Add(BitCodeAbbrevOp(TemplateArgument::Type)); // Template Argument Kind + Abv->Add( + BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Template Argument Type + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Is Defaulted + Abv->Add(BitCodeAbbrevOp(0)); // TemplateArgumentsAsWritten + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SourceLocation + Abv->Add(BitCodeAbbrevOp(0)); + Abv->Add( + BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Canonical Decl of template + } else if constexpr (Kind == FunctionDecl:: + TK_DependentFunctionTemplateSpecialization) { + // Candidates of specialization + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); + Abv->Add(BitCodeAbbrevOp(0)); // TemplateArgumentsAsWritten + } else { + llvm_unreachable("Unknown templated kind?"); + } + // Decl + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, + 8)); // Packed DeclBits: ModuleOwnershipKind, + // isUsed, isReferenced, AccessSpecifier, + // isImplicit + // + // The following bits should be 0: + // HasStandaloneLexicalDC, HasAttrs, + // TopLevelDeclInObjCContainer, + // isInvalidDecl + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID + // NamedDecl + Abv->Add(BitCodeAbbrevOp(DeclarationName::Identifier)); // NameKind + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Identifier + Abv->Add(BitCodeAbbrevOp(0)); // AnonDeclNumber + // ValueDecl + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type + // DeclaratorDecl + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // InnerLocStart + Abv->Add(BitCodeAbbrevOp(0)); // HasExtInfo + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TSIType + // FunctionDecl + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 11)); // IDNS + Abv->Add(BitCodeAbbrevOp( + BitCodeAbbrevOp::Fixed, + 27)); // Packed Function Bits: StorageClass, Inline, InlineSpecified, + // VirtualAsWritten, Pure, HasInheritedProto, HasWrittenProto, + // Deleted, Trivial, TrivialForCall, Defaulted, ExplicitlyDefaulted, + // IsIneligibleOrNotSelected, ImplicitReturnZero, Constexpr, + // UsesSEHTry, SkippedBody, MultiVersion, LateParsed, + // FriendConstraintRefersToEnclosingTemplate, Linkage + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LocEnd + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // ODRHash + // This Array slurps the rest of the record. Fortunately we want to encode + // (nearly) all the remaining (variable number of) fields in the same way. + // + // This is: + // NumParams and Params[] from FunctionDecl, and + // NumOverriddenMethods, OverriddenMethods[] from CXXMethodDecl. + // + // Add an AbbrevOp for 'size then elements' and use it here. + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); + return Abv; +} + +template <FunctionDecl::TemplatedKind Kind> +std::shared_ptr<llvm::BitCodeAbbrev> getCXXMethodAbbrev() { + return getFunctionDeclAbbrev<Kind>(serialization::DECL_CXX_METHOD); +} +} // namespace + void ASTWriter::WriteDeclAbbrevs() { using namespace llvm; @@ -2041,10 +2165,13 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(serialization::DECL_FIELD)); // Decl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, - 12)); // Packed DeclBits: HasStandaloneLexicalDC, - // isInvalidDecl, HasAttrs, isImplicit, isUsed, - // isReferenced, TopLevelDeclInObjCContainer, - // AccessSpecifier, ModuleOwnershipKind + 7)); // Packed DeclBits: ModuleOwnershipKind, + // isUsed, isReferenced, AccessSpecifier, + // + // The following bits should be 0: + // isImplicit, HasStandaloneLexicalDC, HasAttrs, + // TopLevelDeclInObjCContainer, + // isInvalidDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID // NamedDecl @@ -2104,10 +2231,13 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration // Decl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, - 12)); // Packed DeclBits: HasStandaloneLexicalDC, - // isInvalidDecl, HasAttrs, isImplicit, isUsed, - // isReferenced, TopLevelDeclInObjCContainer, - // AccessSpecifier, ModuleOwnershipKind + 7)); // Packed DeclBits: ModuleOwnershipKind, + // isUsed, isReferenced, AccessSpecifier, + // + // The following bits should be 0: + // isImplicit, HasStandaloneLexicalDC, HasAttrs, + // TopLevelDeclInObjCContainer, + // isInvalidDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID // NamedDecl @@ -2145,10 +2275,13 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration // Decl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, - 12)); // Packed DeclBits: HasStandaloneLexicalDC, - // isInvalidDecl, HasAttrs, isImplicit, isUsed, - // isReferenced, TopLevelDeclInObjCContainer, - // AccessSpecifier, ModuleOwnershipKind + 7)); // Packed DeclBits: ModuleOwnershipKind, + // isUsed, isReferenced, AccessSpecifier, + // + // The following bits should be 0: + // isImplicit, HasStandaloneLexicalDC, HasAttrs, + // TopLevelDeclInObjCContainer, + // isInvalidDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID // NamedDecl @@ -2193,10 +2326,11 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration // Decl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, - 12)); // Packed DeclBits: HasStandaloneLexicalDC, - // isInvalidDecl, HasAttrs, isImplicit, isUsed, - // isReferenced, TopLevelDeclInObjCContainer, - // AccessSpecifier, ModuleOwnershipKind + 8)); // Packed DeclBits: ModuleOwnershipKind, isUsed, + // isReferenced, AccessSpecifier, + // HasStandaloneLexicalDC, HasAttrs, isImplicit, + // TopLevelDeclInObjCContainer, + // isInvalidDecl, Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID // NamedDecl @@ -2233,10 +2367,11 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration // Decl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, - 12)); // Packed DeclBits: HasStandaloneLexicalDC, - // isInvalidDecl, HasAttrs, isImplicit, isUsed, - // isReferenced, TopLevelDeclInObjCContainer, - // AccessSpecifier, ModuleOwnershipKind + 7)); // Packed DeclBits: ModuleOwnershipKind, + // isReferenced, isUsed, AccessSpecifier. Other + // higher bits should be 0: isImplicit, + // HasStandaloneLexicalDC, HasAttrs, + // TopLevelDeclInObjCContainer, isInvalidDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID // NamedDecl @@ -2277,12 +2412,13 @@ void ASTWriter::WriteDeclAbbrevs() { // VarDecl Abv->Add(BitCodeAbbrevOp( BitCodeAbbrevOp::Fixed, - 27)); // Packed Var Decl bits: SClass, TSCSpec, InitStyle, + 21)); // Packed Var Decl bits: Linkage, ModulesCodegen, + // SClass, TSCSpec, InitStyle, // isARCPseudoStrong, IsThisDeclarationADemotedDefinition, // isExceptionVariable, isNRVOVariable, isCXXForRangeDecl, - // isObjCForDecl, isInline, isInlineSpecified, isConstexpr, - // isInitCapture, isPrevDeclInSameScope, ImplicitParamKind, - // EscapingByref, HasDeducedType, Linkage, ModulesCodegen + // isInline, isInlineSpecified, isConstexpr, + // isInitCapture, isPrevDeclInSameScope, + // EscapingByref, HasDeducedType, ImplicitParamKind, isObjCForDecl Abv->Add(BitCodeAbbrevOp(0)); // VarKind (local enum) // Type Source Info Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); @@ -2290,71 +2426,84 @@ void ASTWriter::WriteDeclAbbrevs() { DeclVarAbbrev = Stream.EmitAbbrev(std::move(Abv)); // Abbreviation for DECL_CXX_METHOD + DeclCXXMethodAbbrev = + Stream.EmitAbbrev(getCXXMethodAbbrev<FunctionDecl::TK_NonTemplate>()); + DeclTemplateCXXMethodAbbrev = Stream.EmitAbbrev( + getCXXMethodAbbrev<FunctionDecl::TK_FunctionTemplate>()); + DeclDependentNonTemplateCXXMethodAbbrev = Stream.EmitAbbrev( + getCXXMethodAbbrev<FunctionDecl::TK_DependentNonTemplate>()); + DeclMemberSpecializedCXXMethodAbbrev = Stream.EmitAbbrev( + getCXXMethodAbbrev<FunctionDecl::TK_MemberSpecialization>()); + DeclTemplateSpecializedCXXMethodAbbrev = Stream.EmitAbbrev( + getCXXMethodAbbrev<FunctionDecl::TK_FunctionTemplateSpecialization>()); + DeclDependentSpecializationCXXMethodAbbrev = Stream.EmitAbbrev( + getCXXMethodAbbrev< + FunctionDecl::TK_DependentFunctionTemplateSpecialization>()); + + // Abbreviation for DECL_TEMPLATE_TYPE_PARM Abv = std::make_shared<BitCodeAbbrev>(); - Abv->Add(BitCodeAbbrevOp(serialization::DECL_CXX_METHOD)); - // RedeclarableDecl - Abv->Add(BitCodeAbbrevOp(0)); // CanonicalDecl - // FIXME: Implement abbreviation for other template kinds. - Abv->Add(BitCodeAbbrevOp(FunctionDecl::TK_NonTemplate)); // TemplateKind + Abv->Add(BitCodeAbbrevOp(serialization::DECL_TEMPLATE_TYPE_PARM)); + Abv->Add(BitCodeAbbrevOp(0)); // hasTypeConstraint + // Decl + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, + 7)); // Packed DeclBits: ModuleOwnershipKind, + // isReferenced, isUsed, AccessSpecifier. Other + // higher bits should be 0: isImplicit, + // HasStandaloneLexicalDC, HasAttrs, + // TopLevelDeclInObjCContainer, isInvalidDecl + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID + // NamedDecl + Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name + Abv->Add(BitCodeAbbrevOp(0)); + // TypeDecl + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type Ref + // TemplateTypeParmDecl + Abv->Add( + BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // wasDeclaredWithTypename + Abv->Add(BitCodeAbbrevOp(0)); // OwnsDefaultArg + DeclTemplateTypeParmAbbrev = Stream.EmitAbbrev(std::move(Abv)); + + // Abbreviation for DECL_USING_SHADOW + Abv = std::make_shared<BitCodeAbbrev>(); + Abv->Add(BitCodeAbbrevOp(serialization::DECL_USING_SHADOW)); + // Redeclarable + Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration // Decl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 12)); // Packed DeclBits: HasStandaloneLexicalDC, // isInvalidDecl, HasAttrs, isImplicit, isUsed, // isReferenced, TopLevelDeclInObjCContainer, // AccessSpecifier, ModuleOwnershipKind - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID // NamedDecl - Abv->Add(BitCodeAbbrevOp(DeclarationName::Identifier)); // NameKind - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Identifier - Abv->Add(BitCodeAbbrevOp(0)); // AnonDeclNumber - // ValueDecl - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type - // DeclaratorDecl - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // InnerLocStart - Abv->Add(BitCodeAbbrevOp(0)); // HasExtInfo - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TSIType - // FunctionDecl + Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name + Abv->Add(BitCodeAbbrevOp(0)); + // UsingShadowDecl + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TargetDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 11)); // IDNS - Abv->Add(BitCodeAbbrevOp( - BitCodeAbbrevOp::Fixed, - 27)); // Packed Function Bits: StorageClass, Inline, InlineSpecified, - // VirtualAsWritten, Pure, HasInheritedProto, HasWrittenProto, - // Deleted, Trivial, TrivialForCall, Defaulted, ExplicitlyDefaulted, - // IsIneligibleOrNotSelected, ImplicitReturnZero, Constexpr, - // UsesSEHTry, SkippedBody, MultiVersion, LateParsed, - // FriendConstraintRefersToEnclosingTemplate, Linkage - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LocEnd - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Default - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // ODRHash - // This Array slurps the rest of the record. Fortunately we want to encode - // (nearly) all the remaining (variable number of) fields in the same way. - // - // This is: - // NumParams and Params[] from FunctionDecl, and - // NumOverriddenMethods, OverriddenMethods[] from CXXMethodDecl. - // - // Add an AbbrevOp for 'size then elements' and use it here. - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); - DeclCXXMethodAbbrev = Stream.EmitAbbrev(std::move(Abv)); + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // UsingOrNextShadow + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, + 6)); // InstantiatedFromUsingShadowDecl + DeclUsingShadowAbbrev = Stream.EmitAbbrev(std::move(Abv)); // Abbreviation for EXPR_DECL_REF Abv = std::make_shared<BitCodeAbbrev>(); Abv->Add(BitCodeAbbrevOp(serialization::EXPR_DECL_REF)); - //Stmt - // Expr + // Stmt + // Expr + // PackingBits: DependenceKind, ValueKind. ObjectKind should be 0. + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 7)); Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type - // DependenceKind, ValueKind, ObjectKind - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); - //DeclRefExpr - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //HasQualifier - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //GetDeclFound - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //ExplicitTemplateArgs - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //HadMultipleCandidates - Abv->Add(BitCodeAbbrevOp(0)); // RefersToEnclosingVariableOrCapture - Abv->Add(BitCodeAbbrevOp(0)); // NonOdrUseReason - Abv->Add(BitCodeAbbrevOp(0)); // IsImmediateEscalating + // DeclRefExpr + // Packing Bits: , HadMultipleCandidates, RefersToEnclosingVariableOrCapture, + // IsImmediateEscalating, NonOdrUseReason. + // GetDeclFound, HasQualifier and ExplicitTemplateArgs should be 0. + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 5)); Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclRef Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Location DeclRefExprAbbrev = Stream.EmitAbbrev(std::move(Abv)); @@ -2364,10 +2513,10 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(serialization::EXPR_INTEGER_LITERAL)); //Stmt // Expr - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type // DependenceKind, ValueKind, ObjectKind Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); - //Integer Literal + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type + // Integer Literal Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Location Abv->Add(BitCodeAbbrevOp(32)); // Bit Width Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Value @@ -2378,10 +2527,10 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(serialization::EXPR_CHARACTER_LITERAL)); //Stmt // Expr - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type // DependenceKind, ValueKind, ObjectKind Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); - //Character Literal + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type + // Character Literal Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // getValue Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Location Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // getKind @@ -2392,17 +2541,108 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(serialization::EXPR_IMPLICIT_CAST)); // Stmt // Expr - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type - // DependenceKind, ValueKind, ObjectKind + // Packing Bits: DependenceKind, ValueKind, ObjectKind, Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type // CastExpr Abv->Add(BitCodeAbbrevOp(0)); // PathSize - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // HasFPFeatures - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 6)); // CastKind - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // PartOfExplicitCast + // Packing Bits: CastKind, StoredFPFeatures, isPartOfExplicitCast + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 9)); // ImplicitCastExpr ExprImplicitCastAbbrev = Stream.EmitAbbrev(std::move(Abv)); + // Abbreviation for EXPR_BINARY_OPERATOR + Abv = std::make_shared<BitCodeAbbrev>(); + Abv->Add(BitCodeAbbrevOp(serialization::EXPR_BINARY_OPERATOR)); + // Stmt + // Expr + // Packing Bits: DependenceKind. ValueKind and ObjectKind should + // be 0 in this case. + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 5)); + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type + // BinaryOperator + Abv->Add( + BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // OpCode and HasFPFeatures + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location + BinaryOperatorAbbrev = Stream.EmitAbbrev(std::move(Abv)); + + // Abbreviation for EXPR_COMPOUND_ASSIGN_OPERATOR + Abv = std::make_shared<BitCodeAbbrev>(); + Abv->Add(BitCodeAbbrevOp(serialization::EXPR_COMPOUND_ASSIGN_OPERATOR)); + // Stmt + // Expr + // Packing Bits: DependenceKind. ValueKind and ObjectKind should + // be 0 in this case. + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 5)); + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type + // BinaryOperator + // Packing Bits: OpCode. The HasFPFeatures bit should be 0 + Abv->Add( + BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // OpCode and HasFPFeatures + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location + // CompoundAssignOperator + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LHSType + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Result Type + CompoundAssignOperatorAbbrev = Stream.EmitAbbrev(std::move(Abv)); + + // Abbreviation for EXPR_CALL + Abv = std::make_shared<BitCodeAbbrev>(); + Abv->Add(BitCodeAbbrevOp(serialization::EXPR_CALL)); + // Stmt + // Expr + // Packing Bits: DependenceKind, ValueKind, ObjectKind, + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type + // CallExpr + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // NumArgs + Abv->Add(BitCodeAbbrevOp(0)); // ADLCallKind + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location + CallExprAbbrev = Stream.EmitAbbrev(std::move(Abv)); + + // Abbreviation for EXPR_CXX_OPERATOR_CALL + Abv = std::make_shared<BitCodeAbbrev>(); + Abv->Add(BitCodeAbbrevOp(serialization::EXPR_CXX_OPERATOR_CALL)); + // Stmt + // Expr + // Packing Bits: DependenceKind, ValueKind, ObjectKind, + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type + // CallExpr + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // NumArgs + Abv->Add(BitCodeAbbrevOp(0)); // ADLCallKind + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location + // CXXOperatorCallExpr + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Operator Kind + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location + CXXOperatorCallExprAbbrev = Stream.EmitAbbrev(std::move(Abv)); + + // Abbreviation for EXPR_CXX_MEMBER_CALL + Abv = std::make_shared<BitCodeAbbrev>(); + Abv->Add(BitCodeAbbrevOp(serialization::EXPR_CXX_MEMBER_CALL)); + // Stmt + // Expr + // Packing Bits: DependenceKind, ValueKind, ObjectKind, + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type + // CallExpr + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // NumArgs + Abv->Add(BitCodeAbbrevOp(0)); // ADLCallKind + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location + // CXXMemberCallExpr + CXXMemberCallExprAbbrev = Stream.EmitAbbrev(std::move(Abv)); + + // Abbreviation for STMT_COMPOUND + Abv = std::make_shared<BitCodeAbbrev>(); + Abv->Add(BitCodeAbbrevOp(serialization::STMT_COMPOUND)); + // Stmt + // CompoundStmt + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Num Stmts + Abv->Add(BitCodeAbbrevOp(0)); // hasStoredFPFeatures + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location + CompoundStmtAbbrev = Stream.EmitAbbrev(std::move(Abv)); + Abv = std::make_shared<BitCodeAbbrev>(); Abv->Add(BitCodeAbbrevOp(serialization::DECL_CONTEXT_LEXICAL)); Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); diff --git a/contrib/llvm-project/clang/lib/Serialization/ASTWriterStmt.cpp b/contrib/llvm-project/clang/lib/Serialization/ASTWriterStmt.cpp index 8524484ea8a0..7f888e44dde1 100644 --- a/contrib/llvm-project/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/contrib/llvm-project/clang/lib/Serialization/ASTWriterStmt.cpp @@ -37,15 +37,70 @@ namespace clang { serialization::StmtCode Code; unsigned AbbrevToUse; + /// A helper that can help us to write a packed bit across function + /// calls. For example, we may write seperate bits in seperate functions: + /// + /// void VisitA(A* a) { + /// Record.push_back(a->isSomething()); + /// } + /// + /// void Visitb(B *b) { + /// VisitA(b); + /// Record.push_back(b->isAnother()); + /// } + /// + /// In such cases, it'll be better if we can pack these 2 bits. We achieve + /// this by writing a zero value in `VisitA` and recorded that first and add + /// the new bit to the recorded value. + class PakedBitsWriter { + public: + PakedBitsWriter(ASTRecordWriter &Record) : RecordRef(Record) {} + ~PakedBitsWriter() { assert(!CurrentIndex); } + + void addBit(bool Value) { + assert(CurrentIndex && "Writing Bits without recording first!"); + PackingBits.addBit(Value); + } + void addBits(uint32_t Value, uint32_t BitsWidth) { + assert(CurrentIndex && "Writing Bits without recording first!"); + PackingBits.addBits(Value, BitsWidth); + } + + void writeBits() { + if (!CurrentIndex) + return; + + RecordRef[*CurrentIndex] = (uint32_t)PackingBits; + CurrentIndex = std::nullopt; + PackingBits.reset(0); + } + + void updateBits() { + writeBits(); + + CurrentIndex = RecordRef.size(); + RecordRef.push_back(0); + } + + private: + BitsPacker PackingBits; + ASTRecordWriter &RecordRef; + std::optional<unsigned> CurrentIndex; + }; + + PakedBitsWriter CurrentPackingBits; + public: ASTStmtWriter(ASTWriter &Writer, ASTWriter::RecordData &Record) : Writer(Writer), Record(Writer, Record), - Code(serialization::STMT_NULL_PTR), AbbrevToUse(0) {} + Code(serialization::STMT_NULL_PTR), AbbrevToUse(0), + CurrentPackingBits(this->Record) {} ASTStmtWriter(const ASTStmtWriter&) = delete; ASTStmtWriter &operator=(const ASTStmtWriter &) = delete; uint64_t Emit() { + CurrentPackingBits.writeBits(); assert(Code != serialization::STMT_NULL_PTR && "unhandled sub-statement writing AST file"); return Record.EmitStmt(Code, AbbrevToUse); @@ -82,14 +137,20 @@ void ASTStmtWriter::VisitNullStmt(NullStmt *S) { void ASTStmtWriter::VisitCompoundStmt(CompoundStmt *S) { VisitStmt(S); + Record.push_back(S->size()); Record.push_back(S->hasStoredFPFeatures()); + for (auto *CS : S->body()) Record.AddStmt(CS); if (S->hasStoredFPFeatures()) Record.push_back(S->getStoredFPFeatures().getAsOpaqueInt()); Record.AddSourceLocation(S->getLBracLoc()); Record.AddSourceLocation(S->getRBracLoc()); + + if (!S->hasStoredFPFeatures()) + AbbrevToUse = Writer.getCompoundStmtAbbrev(); + Code = serialization::STMT_COMPOUND; } @@ -143,9 +204,11 @@ void ASTStmtWriter::VisitIfStmt(IfStmt *S) { bool HasVar = S->getConditionVariableDeclStmt() != nullptr; bool HasInit = S->getInit() != nullptr; - Record.push_back(HasElse); - Record.push_back(HasVar); - Record.push_back(HasInit); + CurrentPackingBits.updateBits(); + + CurrentPackingBits.addBit(HasElse); + CurrentPackingBits.addBit(HasVar); + CurrentPackingBits.addBit(HasInit); Record.push_back(static_cast<uint64_t>(S->getStatementKind())); Record.AddStmt(S->getCond()); Record.AddStmt(S->getThen()); @@ -548,15 +611,13 @@ void ASTStmtWriter::VisitCapturedStmt(CapturedStmt *S) { void ASTStmtWriter::VisitExpr(Expr *E) { VisitStmt(E); - Record.AddTypeRef(E->getType()); - BitsPacker ExprBits; + CurrentPackingBits.updateBits(); + CurrentPackingBits.addBits(E->getDependence(), /*BitsWidth=*/5); + CurrentPackingBits.addBits(E->getValueKind(), /*BitsWidth=*/2); + CurrentPackingBits.addBits(E->getObjectKind(), /*BitsWidth=*/3); - ExprBits.addBits(E->getDependence(), /*BitsWidth=*/5); - ExprBits.addBits(E->getValueKind(), /*BitsWidth=*/2); - ExprBits.addBits(E->getObjectKind(), /*BitsWidth=*/3); - - Record.push_back(ExprBits); + Record.AddTypeRef(E->getType()); } void ASTStmtWriter::VisitConstantExpr(ConstantExpr *E) { @@ -612,13 +673,15 @@ void ASTStmtWriter::VisitPredefinedExpr(PredefinedExpr *E) { void ASTStmtWriter::VisitDeclRefExpr(DeclRefExpr *E) { VisitExpr(E); - Record.push_back(E->hasQualifier()); - Record.push_back(E->getDecl() != E->getFoundDecl()); - Record.push_back(E->hasTemplateKWAndArgsInfo()); - Record.push_back(E->hadMultipleCandidates()); - Record.push_back(E->refersToEnclosingVariableOrCapture()); - Record.push_back(E->isNonOdrUse()); - Record.push_back(E->isImmediateEscalating()); + CurrentPackingBits.updateBits(); + + CurrentPackingBits.addBit(E->hadMultipleCandidates()); + CurrentPackingBits.addBit(E->refersToEnclosingVariableOrCapture()); + CurrentPackingBits.addBits(E->isNonOdrUse(), /*Width=*/2); + CurrentPackingBits.addBit(E->isImmediateEscalating()); + CurrentPackingBits.addBit(E->getDecl() != E->getFoundDecl()); + CurrentPackingBits.addBit(E->hasQualifier()); + CurrentPackingBits.addBit(E->hasTemplateKWAndArgsInfo()); if (E->hasTemplateKWAndArgsInfo()) { unsigned NumTemplateArgs = E->getNumTemplateArgs(); @@ -629,9 +692,7 @@ void ASTStmtWriter::VisitDeclRefExpr(DeclRefExpr *E) { if ((!E->hasTemplateKWAndArgsInfo()) && (!E->hasQualifier()) && (E->getDecl() == E->getFoundDecl()) && - nk == DeclarationName::Identifier && - !E->refersToEnclosingVariableOrCapture() && !E->isNonOdrUse() && - !E->isImmediateEscalating()) { + nk == DeclarationName::Identifier && E->getObjectKind() == OK_Ordinary) { AbbrevToUse = Writer.getDeclRefExprAbbrev(); } @@ -742,11 +803,13 @@ void ASTStmtWriter::VisitUnaryOperator(UnaryOperator *E) { bool HasFPFeatures = E->hasStoredFPFeatures(); // Write this first for easy access when deserializing, as they affect the // size of the UnaryOperator. - Record.push_back(HasFPFeatures); + CurrentPackingBits.addBit(HasFPFeatures); Record.AddStmt(E->getSubExpr()); - Record.push_back(E->getOpcode()); // FIXME: stable encoding + CurrentPackingBits.addBits(E->getOpcode(), + /*Width=*/5); // FIXME: stable encoding Record.AddSourceLocation(E->getOperatorLoc()); - Record.push_back(E->canOverflow()); + CurrentPackingBits.addBit(E->canOverflow()); + if (HasFPFeatures) Record.push_back(E->getStoredFPFeatures().getAsOpaqueInt()); Code = serialization::EXPR_UNARY_OPERATOR; @@ -872,12 +935,10 @@ void ASTStmtWriter::VisitOMPIteratorExpr(OMPIteratorExpr *E) { void ASTStmtWriter::VisitCallExpr(CallExpr *E) { VisitExpr(E); - BitsPacker CallExprBits; - // 16 bits should be sufficient to store the number args; - CallExprBits.addBits(E->getNumArgs(), /*BitsWidth=*/16); - CallExprBits.addBit(E->hasStoredFPFeatures()); - CallExprBits.addBit(static_cast<bool>(E->getADLCallKind())); - Record.push_back(CallExprBits); + Record.push_back(E->getNumArgs()); + CurrentPackingBits.updateBits(); + CurrentPackingBits.addBit(static_cast<bool>(E->getADLCallKind())); + CurrentPackingBits.addBit(E->hasStoredFPFeatures()); Record.AddSourceLocation(E->getRParenLoc()); Record.AddStmt(E->getCallee()); @@ -887,6 +948,11 @@ void ASTStmtWriter::VisitCallExpr(CallExpr *E) { if (E->hasStoredFPFeatures()) Record.push_back(E->getFPFeatures().getAsOpaqueInt()); + + if (!E->hasStoredFPFeatures() && !static_cast<bool>(E->getADLCallKind()) && + E->getStmtClass() == Stmt::CallExprClass) + AbbrevToUse = Writer.getCallExprAbbrev(); + Code = serialization::EXPR_CALL; } @@ -913,9 +979,10 @@ void ASTStmtWriter::VisitMemberExpr(MemberExpr *E) { // Write these first for easy access when deserializing, as they affect the // size of the MemberExpr. - Record.push_back(HasQualifier); - Record.push_back(HasFoundDecl); - Record.push_back(HasTemplateInfo); + CurrentPackingBits.updateBits(); + CurrentPackingBits.addBit(HasQualifier); + CurrentPackingBits.addBit(HasFoundDecl); + CurrentPackingBits.addBit(HasTemplateInfo); Record.push_back(NumTemplateArgs); Record.AddStmt(E->getBase()); @@ -923,15 +990,15 @@ void ASTStmtWriter::VisitMemberExpr(MemberExpr *E) { Record.AddDeclarationNameLoc(E->MemberDNLoc, E->getMemberDecl()->getDeclName()); Record.AddSourceLocation(E->getMemberLoc()); - Record.push_back(E->isArrow()); - Record.push_back(E->hadMultipleCandidates()); - Record.push_back(E->isNonOdrUse()); + CurrentPackingBits.addBit(E->isArrow()); + CurrentPackingBits.addBit(E->hadMultipleCandidates()); + CurrentPackingBits.addBits(E->isNonOdrUse(), /*Width=*/2); Record.AddSourceLocation(E->getOperatorLoc()); if (HasFoundDecl) { DeclAccessPair FoundDecl = E->getFoundDecl(); Record.AddDeclRef(FoundDecl.getDecl()); - Record.push_back(FoundDecl.getAccess()); + CurrentPackingBits.addBits(FoundDecl.getAccess(), /*BitWidth=*/2); } if (HasQualifier) @@ -971,10 +1038,13 @@ void ASTStmtWriter::VisitObjCBridgedCastExpr(ObjCBridgedCastExpr *E) { void ASTStmtWriter::VisitCastExpr(CastExpr *E) { VisitExpr(E); + Record.push_back(E->path_size()); - Record.push_back(E->hasStoredFPFeatures()); + CurrentPackingBits.updateBits(); + // 7 bits should be enough to store the casting kinds. + CurrentPackingBits.addBits(E->getCastKind(), /*Width=*/7); + CurrentPackingBits.addBit(E->hasStoredFPFeatures()); Record.AddStmt(E->getSubExpr()); - Record.push_back(E->getCastKind()); // FIXME: stable encoding for (CastExpr::path_iterator PI = E->path_begin(), PE = E->path_end(); PI != PE; ++PI) @@ -986,16 +1056,23 @@ void ASTStmtWriter::VisitCastExpr(CastExpr *E) { void ASTStmtWriter::VisitBinaryOperator(BinaryOperator *E) { VisitExpr(E); - bool HasFPFeatures = E->hasStoredFPFeatures(); + // Write this first for easy access when deserializing, as they affect the // size of the UnaryOperator. - Record.push_back(HasFPFeatures); - Record.push_back(E->getOpcode()); // FIXME: stable encoding + CurrentPackingBits.updateBits(); + CurrentPackingBits.addBits(E->getOpcode(), /*Width=*/6); + bool HasFPFeatures = E->hasStoredFPFeatures(); + CurrentPackingBits.addBit(HasFPFeatures); Record.AddStmt(E->getLHS()); Record.AddStmt(E->getRHS()); Record.AddSourceLocation(E->getOperatorLoc()); if (HasFPFeatures) Record.push_back(E->getStoredFPFeatures().getAsOpaqueInt()); + + if (!HasFPFeatures && E->getValueKind() == VK_PRValue && + E->getObjectKind() == OK_Ordinary) + AbbrevToUse = Writer.getBinaryOperatorAbbrev(); + Code = serialization::EXPR_BINARY_OPERATOR; } @@ -1003,6 +1080,11 @@ void ASTStmtWriter::VisitCompoundAssignOperator(CompoundAssignOperator *E) { VisitBinaryOperator(E); Record.AddTypeRef(E->getComputationLHSType()); Record.AddTypeRef(E->getComputationResultType()); + + if (!E->hasStoredFPFeatures() && E->getValueKind() == VK_PRValue && + E->getObjectKind() == OK_Ordinary) + AbbrevToUse = Writer.getCompoundAssignOperatorAbbrev(); + Code = serialization::EXPR_COMPOUND_ASSIGN_OPERATOR; } @@ -1031,7 +1113,7 @@ ASTStmtWriter::VisitBinaryConditionalOperator(BinaryConditionalOperator *E) { void ASTStmtWriter::VisitImplicitCastExpr(ImplicitCastExpr *E) { VisitCastExpr(E); - Record.push_back(E->isPartOfExplicitCast()); + CurrentPackingBits.addBit(E->isPartOfExplicitCast()); if (E->path_size() == 0 && !E->hasStoredFPFeatures()) AbbrevToUse = Writer.getExprImplicitCastAbbrev(); @@ -1588,11 +1670,19 @@ void ASTStmtWriter::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) { VisitCallExpr(E); Record.push_back(E->getOperator()); Record.AddSourceRange(E->Range); + + if (!E->hasStoredFPFeatures() && !static_cast<bool>(E->getADLCallKind())) + AbbrevToUse = Writer.getCXXOperatorCallExprAbbrev(); + Code = serialization::EXPR_CXX_OPERATOR_CALL; } void ASTStmtWriter::VisitCXXMemberCallExpr(CXXMemberCallExpr *E) { VisitCallExpr(E); + + if (!E->hasStoredFPFeatures() && !static_cast<bool>(E->getADLCallKind())) + AbbrevToUse = Writer.getCXXMemberCallExprAbbrev(); + Code = serialization::EXPR_CXX_MEMBER_CALL; } @@ -1673,7 +1763,9 @@ void ASTStmtWriter::VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E) void ASTStmtWriter::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) { VisitExplicitCastExpr(E); Record.AddSourceRange(SourceRange(E->getOperatorLoc(), E->getRParenLoc())); - Record.AddSourceRange(E->getAngleBrackets()); + CurrentPackingBits.addBit(E->getAngleBrackets().isValid()); + if (E->getAngleBrackets().isValid()) + Record.AddSourceRange(E->getAngleBrackets()); } void ASTStmtWriter::VisitCXXStaticCastExpr(CXXStaticCastExpr *E) { @@ -1750,6 +1842,7 @@ void ASTStmtWriter::VisitCXXThisExpr(CXXThisExpr *E) { VisitExpr(E); Record.AddSourceLocation(E->getLocation()); Record.push_back(E->isImplicit()); + Code = serialization::EXPR_CXX_THIS; } @@ -1883,10 +1976,10 @@ void ASTStmtWriter::VisitCXXDependentScopeMemberExpr( // Don't emit anything here (or if you do you will have to update // the corresponding deserialization function). - - Record.push_back(E->hasTemplateKWAndArgsInfo()); Record.push_back(E->getNumTemplateArgs()); - Record.push_back(E->hasFirstQualifierFoundInScope()); + CurrentPackingBits.updateBits(); + CurrentPackingBits.addBit(E->hasTemplateKWAndArgsInfo()); + CurrentPackingBits.addBit(E->hasFirstQualifierFoundInScope()); if (E->hasTemplateKWAndArgsInfo()) { const ASTTemplateKWAndArgsInfo &ArgInfo = @@ -1895,14 +1988,15 @@ void ASTStmtWriter::VisitCXXDependentScopeMemberExpr( E->getTrailingObjects<TemplateArgumentLoc>()); } - Record.push_back(E->isArrow()); - Record.AddSourceLocation(E->getOperatorLoc()); + CurrentPackingBits.addBit(E->isArrow()); + Record.AddTypeRef(E->getBaseType()); Record.AddNestedNameSpecifierLoc(E->getQualifierLoc()); + CurrentPackingBits.addBit(!E->isImplicitAccess()); if (!E->isImplicitAccess()) Record.AddStmt(E->getBase()); - else - Record.AddStmt(nullptr); + + Record.AddSourceLocation(E->getOperatorLoc()); if (E->hasFirstQualifierFoundInScope()) Record.AddDeclRef(E->getFirstQualifierFoundInScope()); @@ -1917,12 +2011,14 @@ ASTStmtWriter::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) { // Don't emit anything here, HasTemplateKWAndArgsInfo must be // emitted first. + CurrentPackingBits.addBit( + E->DependentScopeDeclRefExprBits.HasTemplateKWAndArgsInfo); - Record.push_back(E->DependentScopeDeclRefExprBits.HasTemplateKWAndArgsInfo); if (E->DependentScopeDeclRefExprBits.HasTemplateKWAndArgsInfo) { const ASTTemplateKWAndArgsInfo &ArgInfo = *E->getTrailingObjects<ASTTemplateKWAndArgsInfo>(); - Record.push_back(ArgInfo.NumTemplateArgs); + // 16 bits should be enought to store the number of args + CurrentPackingBits.addBits(ArgInfo.NumTemplateArgs, /*Width=*/16); AddTemplateKWAndArgsInfo(ArgInfo, E->getTrailingObjects<TemplateArgumentLoc>()); } @@ -1949,19 +2045,16 @@ ASTStmtWriter::VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E) { void ASTStmtWriter::VisitOverloadExpr(OverloadExpr *E) { VisitExpr(E); - BitsPacker OverloadExprBits; - // 14 Bits should enough to store the number of decls. - OverloadExprBits.addBits(E->getNumDecls(), /*BitWidth=*/14); - OverloadExprBits.addBit(E->hasTemplateKWAndArgsInfo()); + Record.push_back(E->getNumDecls()); + + CurrentPackingBits.updateBits(); + CurrentPackingBits.addBit(E->hasTemplateKWAndArgsInfo()); if (E->hasTemplateKWAndArgsInfo()) { const ASTTemplateKWAndArgsInfo &ArgInfo = *E->getTrailingASTTemplateKWAndArgsInfo(); - // 14 Bits should enough to store the number of template args. - OverloadExprBits.addBits(ArgInfo.NumTemplateArgs, /*BitWidth=*/14); - Record.push_back(OverloadExprBits); + Record.push_back(ArgInfo.NumTemplateArgs); AddTemplateKWAndArgsInfo(ArgInfo, E->getTrailingTemplateArgumentLoc()); - } else - Record.push_back(OverloadExprBits); + } for (OverloadExpr::decls_iterator OvI = E->decls_begin(), OvE = E->decls_end(); @@ -1976,18 +2069,22 @@ void ASTStmtWriter::VisitOverloadExpr(OverloadExpr *E) { void ASTStmtWriter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E) { VisitOverloadExpr(E); - Record.push_back(E->isArrow()); - Record.push_back(E->hasUnresolvedUsing()); - Record.AddStmt(!E->isImplicitAccess() ? E->getBase() : nullptr); - Record.AddTypeRef(E->getBaseType()); + CurrentPackingBits.addBit(E->isArrow()); + CurrentPackingBits.addBit(E->hasUnresolvedUsing()); + CurrentPackingBits.addBit(!E->isImplicitAccess()); + if (!E->isImplicitAccess()) + Record.AddStmt(E->getBase()); + Record.AddSourceLocation(E->getOperatorLoc()); + + Record.AddTypeRef(E->getBaseType()); Code = serialization::EXPR_CXX_UNRESOLVED_MEMBER; } void ASTStmtWriter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) { VisitOverloadExpr(E); - Record.push_back(E->requiresADL()); - Record.push_back(E->isOverloaded()); + CurrentPackingBits.addBit(E->requiresADL()); + CurrentPackingBits.addBit(E->isOverloaded()); Record.AddDeclRef(E->getNamingClass()); Code = serialization::EXPR_CXX_UNRESOLVED_LOOKUP; } @@ -2059,12 +2156,12 @@ void ASTStmtWriter::VisitSubstNonTypeTemplateParmExpr( SubstNonTypeTemplateParmExpr *E) { VisitExpr(E); Record.AddDeclRef(E->getAssociatedDecl()); - Record.push_back(E->isReferenceParameter()); - Record.push_back(E->getIndex()); + CurrentPackingBits.addBit(E->isReferenceParameter()); + CurrentPackingBits.addBits(E->getIndex(), /*Width=*/12); + CurrentPackingBits.addBit((bool)E->getPackIndex()); if (auto PackIndex = E->getPackIndex()) Record.push_back(*PackIndex + 1); - else - Record.push_back(0); + Record.AddSourceLocation(E->getNameLoc()); Record.AddStmt(E->getReplacement()); Code = serialization::EXPR_SUBST_NON_TYPE_TEMPLATE_PARM; diff --git a/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp b/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp index 925fc90e3554..254b36ed0396 100644 --- a/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp +++ b/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp @@ -266,6 +266,8 @@ private: {&StreamChecker::preFseek, &StreamChecker::evalFseek, 0}}, {{{"ftell"}, 1}, {&StreamChecker::preDefault, &StreamChecker::evalFtell, 0}}, + {{{"fflush"}, 1}, + {&StreamChecker::preFflush, &StreamChecker::evalFflush, 0}}, {{{"rewind"}, 1}, {&StreamChecker::preDefault, &StreamChecker::evalRewind, 0}}, {{{"fgetpos"}, 2}, @@ -360,6 +362,12 @@ private: CheckerContext &C, const StreamErrorState &ErrorKind) const; + void preFflush(const FnDescription *Desc, const CallEvent &Call, + CheckerContext &C) const; + + void evalFflush(const FnDescription *Desc, const CallEvent &Call, + CheckerContext &C) const; + /// Check that the stream (in StreamVal) is not NULL. /// If it can only be NULL a fatal error is emitted and nullptr returned. /// Otherwise the return value is a new state where the stream is constrained @@ -1191,6 +1199,84 @@ void StreamChecker::evalSetFeofFerror(const FnDescription *Desc, C.addTransition(State); } +void StreamChecker::preFflush(const FnDescription *Desc, const CallEvent &Call, + CheckerContext &C) const { + ProgramStateRef State = C.getState(); + SVal StreamVal = getStreamArg(Desc, Call); + std::optional<DefinedSVal> Stream = StreamVal.getAs<DefinedSVal>(); + if (!Stream) + return; + + ProgramStateRef StateNotNull, StateNull; + std::tie(StateNotNull, StateNull) = + C.getConstraintManager().assumeDual(State, *Stream); + if (StateNotNull && !StateNull) + ensureStreamOpened(StreamVal, C, StateNotNull); +} + +void StreamChecker::evalFflush(const FnDescription *Desc, const CallEvent &Call, + CheckerContext &C) const { + ProgramStateRef State = C.getState(); + SVal StreamVal = getStreamArg(Desc, Call); + std::optional<DefinedSVal> Stream = StreamVal.getAs<DefinedSVal>(); + if (!Stream) + return; + + // Skip if the stream can be both NULL and non-NULL. + ProgramStateRef StateNotNull, StateNull; + std::tie(StateNotNull, StateNull) = + C.getConstraintManager().assumeDual(State, *Stream); + if (StateNotNull && StateNull) + return; + if (StateNotNull && !StateNull) + State = StateNotNull; + else + State = StateNull; + + const CallExpr *CE = dyn_cast_or_null<CallExpr>(Call.getOriginExpr()); + if (!CE) + return; + + // `fflush` returns EOF on failure, otherwise returns 0. + ProgramStateRef StateFailed = bindInt(*EofVal, State, C, CE); + ProgramStateRef StateNotFailed = bindInt(0, State, C, CE); + + // Clear error states if `fflush` returns 0, but retain their EOF flags. + auto ClearErrorInNotFailed = [&StateNotFailed, Desc](SymbolRef Sym, + const StreamState *SS) { + if (SS->ErrorState & ErrorFError) { + StreamErrorState NewES = + (SS->ErrorState & ErrorFEof) ? ErrorFEof : ErrorNone; + StreamState NewSS = StreamState::getOpened(Desc, NewES, false); + StateNotFailed = StateNotFailed->set<StreamMap>(Sym, NewSS); + } + }; + + if (StateNotNull && !StateNull) { + // Skip if the input stream's state is unknown, open-failed or closed. + if (SymbolRef StreamSym = StreamVal.getAsSymbol()) { + const StreamState *SS = State->get<StreamMap>(StreamSym); + if (SS) { + assert(SS->isOpened() && "Stream is expected to be opened"); + ClearErrorInNotFailed(StreamSym, SS); + } else + return; + } + } else { + // Clear error states for all streams. + const StreamMapTy &Map = StateNotFailed->get<StreamMap>(); + for (const auto &I : Map) { + SymbolRef Sym = I.first; + const StreamState &SS = I.second; + if (SS.isOpened()) + ClearErrorInNotFailed(Sym, &SS); + } + } + + C.addTransition(StateNotFailed); + C.addTransition(StateFailed); +} + ProgramStateRef StreamChecker::ensureStreamNonNull(SVal StreamVal, const Expr *StreamE, CheckerContext &C, diff --git a/contrib/llvm-project/clang/lib/Support/RISCVVIntrinsicUtils.cpp b/contrib/llvm-project/clang/lib/Support/RISCVVIntrinsicUtils.cpp index bb9f7dc7e7e3..bf47461b59e0 100644 --- a/contrib/llvm-project/clang/lib/Support/RISCVVIntrinsicUtils.cpp +++ b/contrib/llvm-project/clang/lib/Support/RISCVVIntrinsicUtils.cpp @@ -1217,7 +1217,7 @@ raw_ostream &operator<<(raw_ostream &OS, const RVVIntrinsicRecord &Record) { OS << (int)Record.PrototypeLength << ","; OS << (int)Record.SuffixLength << ","; OS << (int)Record.OverloadedSuffixSize << ","; - OS << (int)Record.RequiredExtensions << ","; + OS << Record.RequiredExtensions << ","; OS << (int)Record.TypeRangeMask << ","; OS << (int)Record.Log2LMULMask << ","; OS << (int)Record.NF << ","; |