diff options
Diffstat (limited to 'contrib/llvm-project/clang/lib/AST/Decl.cpp')
-rw-r--r-- | contrib/llvm-project/clang/lib/AST/Decl.cpp | 1048 |
1 files changed, 796 insertions, 252 deletions
diff --git a/contrib/llvm-project/clang/lib/AST/Decl.cpp b/contrib/llvm-project/clang/lib/AST/Decl.cpp index 959a7c415c58..1ee33fd7576d 100644 --- a/contrib/llvm-project/clang/lib/AST/Decl.cpp +++ b/contrib/llvm-project/clang/lib/AST/Decl.cpp @@ -30,6 +30,8 @@ #include "clang/AST/ODRHash.h" #include "clang/AST/PrettyDeclStackTrace.h" #include "clang/AST/PrettyPrinter.h" +#include "clang/AST/Randstruct.h" +#include "clang/AST/RecordLayout.h" #include "clang/AST/Redeclarable.h" #include "clang/AST/Stmt.h" #include "clang/AST/TemplateBase.h" @@ -52,21 +54,20 @@ #include "clang/Basic/Visibility.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/None.h" -#include "llvm/ADT/Optional.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" -#include "llvm/ADT/Triple.h" #include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/TargetParser/Triple.h" #include <algorithm> #include <cassert> #include <cstddef> #include <cstring> #include <memory> +#include <optional> #include <string> #include <tuple> #include <type_traits> @@ -86,7 +87,7 @@ void PrettyDeclStackTraceEntry::print(raw_ostream &OS) const { } OS << Message; - if (auto *ND = dyn_cast_or_null<NamedDecl>(TheDecl)) { + if (auto *ND = dyn_cast_if_present<NamedDecl>(TheDecl)) { OS << " '"; ND->getNameForDiagnostic(OS, Context.getPrintingPolicy(), true); OS << "'"; @@ -168,8 +169,8 @@ withExplicitVisibilityAlready(LVComputationKind Kind) { return Kind; } -static Optional<Visibility> getExplicitVisibility(const NamedDecl *D, - LVComputationKind kind) { +static std::optional<Visibility> getExplicitVisibility(const NamedDecl *D, + LVComputationKind kind) { assert(!kind.IgnoreExplicitVisibility && "asking for explicit visibility when we shouldn't be"); return D->getExplicitVisibility(kind.getExplicitVisibilityKind()); @@ -185,8 +186,8 @@ static bool usesTypeVisibility(const NamedDecl *D) { /// Does the given declaration have member specialization information, /// and if so, is it an explicit specialization? -template <class T> static typename -std::enable_if<!std::is_base_of<RedeclarableTemplateDecl, T>::value, bool>::type +template <class T> +static std::enable_if_t<!std::is_base_of_v<RedeclarableTemplateDecl, T>, bool> isExplicitMemberSpecialization(const T *D) { if (const MemberSpecializationInfo *member = D->getMemberSpecializationInfo()) { @@ -218,8 +219,8 @@ static Visibility getVisibilityFromAttr(const T *attr) { } /// Return the explicit visibility of the given declaration. -static Optional<Visibility> getVisibilityOf(const NamedDecl *D, - NamedDecl::ExplicitVisibilityKind kind) { +static std::optional<Visibility> +getVisibilityOf(const NamedDecl *D, NamedDecl::ExplicitVisibilityKind kind) { // If we're ultimately computing the visibility of a type, look for // a 'type_visibility' attribute before looking for 'visibility'. if (kind == NamedDecl::VisibilityForType) { @@ -233,7 +234,7 @@ static Optional<Visibility> getVisibilityOf(const NamedDecl *D, return getVisibilityFromAttr(A); } - return None; + return std::nullopt; } LinkageInfo LinkageComputer::getLVForType(const Type &T, @@ -342,6 +343,10 @@ LinkageComputer::getLVForTemplateArgumentList(ArrayRef<TemplateArgument> Args, LV.merge(getTypeLinkageAndVisibility(Arg.getNullPtrType())); continue; + case TemplateArgument::StructuralValue: + LV.merge(getLVForValue(Arg.getAsStructuralValue(), computation)); + continue; + case TemplateArgument::Template: case TemplateArgument::TemplateExpansion: if (TemplateDecl *Template = @@ -391,11 +396,17 @@ void LinkageComputer::mergeTemplateLV( bool considerVisibility = shouldConsiderTemplateVisibility(fn, specInfo); - // Merge information from the template parameters. FunctionTemplateDecl *temp = specInfo->getTemplate(); - LinkageInfo tempLV = - getLVForTemplateParameterList(temp->getTemplateParameters(), computation); - LV.mergeMaybeWithVisibility(tempLV, considerVisibility); + // Merge information from the template declaration. + LinkageInfo tempLV = getLVForDecl(temp, computation); + // The linkage of the specialization should be consistent with the + // template declaration. + LV.setLinkage(tempLV.getLinkage()); + + // Merge information from the template parameters. + LinkageInfo paramsLV = + getLVForTemplateParameterList(temp->getTemplateParameters(), computation); + LV.mergeMaybeWithVisibility(paramsLV, considerVisibility); // Merge information from the template arguments. const TemplateArgumentList &templateArgs = *specInfo->TemplateArguments; @@ -459,11 +470,16 @@ void LinkageComputer::mergeTemplateLV( // Merge information from the template parameters, but ignore // visibility if we're only considering template arguments. - ClassTemplateDecl *temp = spec->getSpecializedTemplate(); - LinkageInfo tempLV = + // Merge information from the template declaration. + LinkageInfo tempLV = getLVForDecl(temp, computation); + // The linkage of the specialization should be consistent with the + // template declaration. + LV.setLinkage(tempLV.getLinkage()); + + LinkageInfo paramsLV = getLVForTemplateParameterList(temp->getTemplateParameters(), computation); - LV.mergeMaybeWithVisibility(tempLV, + LV.mergeMaybeWithVisibility(paramsLV, considerVisibility && !hasExplicitVisibilityAlready(computation)); // Merge information from the template arguments. We ignore @@ -511,7 +527,6 @@ void LinkageComputer::mergeTemplateLV(LinkageInfo &LV, // Merge information from the template parameters, but ignore // visibility if we're only considering template arguments. - VarTemplateDecl *temp = spec->getSpecializedTemplate(); LinkageInfo tempLV = getLVForTemplateParameterList(temp->getTemplateParameters(), computation); @@ -568,46 +583,13 @@ static bool isSingleLineLanguageLinkage(const Decl &D) { return false; } -/// Determine whether D is declared in the purview of a named module. -static bool isInModulePurview(const NamedDecl *D) { +static bool isDeclaredInModuleInterfaceOrPartition(const NamedDecl *D) { if (auto *M = D->getOwningModule()) - return M->isModulePurview(); + return M->isInterfaceOrPartition(); return false; } -static bool isExportedFromModuleInterfaceUnit(const NamedDecl *D) { - // FIXME: Handle isModulePrivate. - switch (D->getModuleOwnershipKind()) { - case Decl::ModuleOwnershipKind::Unowned: - case Decl::ModuleOwnershipKind::ModulePrivate: - return false; - case Decl::ModuleOwnershipKind::Visible: - case Decl::ModuleOwnershipKind::VisibleWhenImported: - return isInModulePurview(D); - } - llvm_unreachable("unexpected module ownership kind"); -} - -static LinkageInfo getInternalLinkageFor(const NamedDecl *D) { - // Internal linkage declarations within a module interface unit are modeled - // as "module-internal linkage", which means that they have internal linkage - // formally but can be indirectly accessed from outside the module via inline - // functions and templates defined within the module. - if (isInModulePurview(D)) - return LinkageInfo(ModuleInternalLinkage, DefaultVisibility, false); - - return LinkageInfo::internal(); -} - static LinkageInfo getExternalLinkageFor(const NamedDecl *D) { - // C++ Modules TS [basic.link]/6.8: - // - A name declared at namespace scope that does not have internal linkage - // by the previous rules and that is introduced by a non-exported - // declaration has module linkage. - if (isInModulePurview(D) && !isExportedFromModuleInterfaceUnit( - cast<NamedDecl>(D->getCanonicalDecl()))) - return LinkageInfo(ModuleLinkage, DefaultVisibility, false); - return LinkageInfo::external(); } @@ -639,21 +621,21 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D, // - a variable, variable template, function, or function template // that is explicitly declared static; or // (This bullet corresponds to C99 6.2.2p3.) - return getInternalLinkageFor(D); + return LinkageInfo::internal(); } if (const auto *Var = dyn_cast<VarDecl>(D)) { // - a non-template variable of non-volatile const-qualified type, unless // - it is explicitly declared extern, or - // - it is inline or exported, or + // - it is declared in the purview of a module interface unit + // (outside the private-module-fragment, if any) or module partition, or + // - it is inline, or // - it was previously declared and the prior declaration did not have // internal linkage // (There is no equivalent in C99.) - if (Context.getLangOpts().CPlusPlus && - Var->getType().isConstQualified() && - !Var->getType().isVolatileQualified() && - !Var->isInline() && - !isExportedFromModuleInterfaceUnit(Var) && + if (Context.getLangOpts().CPlusPlus && Var->getType().isConstQualified() && + !Var->getType().isVolatileQualified() && !Var->isInline() && + !isDeclaredInModuleInterfaceOrPartition(Var) && !isa<VarTemplateSpecializationDecl>(Var) && !Var->getDescribedVarTemplate()) { const VarDecl *PrevVar = Var->getPreviousDecl(); @@ -663,7 +645,7 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D, if (Var->getStorageClass() != SC_Extern && Var->getStorageClass() != SC_PrivateExtern && !isSingleLineLanguageLinkage(*Var)) - return getInternalLinkageFor(Var); + return LinkageInfo::internal(); } for (const VarDecl *PrevVar = Var->getPreviousDecl(); PrevVar; @@ -673,7 +655,7 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D, return getDeclLinkageAndVisibility(PrevVar); // Explicitly declared static. if (PrevVar->getStorageClass() == SC_Static) - return getInternalLinkageFor(Var); + return LinkageInfo::internal(); } } else if (const auto *IFD = dyn_cast<IndirectFieldDecl>(D)) { // - a data member of an anonymous union. @@ -697,7 +679,7 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D, // within an unnamed namespace has internal linkage. if ((!Var || !isFirstInExternCContext(Var)) && (!Func || !isFirstInExternCContext(Func))) - return getInternalLinkageFor(D); + return LinkageInfo::internal(); } // Set up the defaults. @@ -709,7 +691,7 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D, LinkageInfo LV = getExternalLinkageFor(D); if (!hasExplicitVisibilityAlready(computation)) { - if (Optional<Visibility> Vis = getExplicitVisibility(D, computation)) { + if (std::optional<Visibility> Vis = getExplicitVisibility(D, computation)) { LV.mergeVisibility(*Vis, true); } else { // If we're declared in a namespace with a visibility attribute, @@ -719,7 +701,8 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D, DC = DC->getParent()) { const auto *ND = dyn_cast<NamespaceDecl>(DC); if (!ND) continue; - if (Optional<Visibility> Vis = getExplicitVisibility(ND, computation)) { + if (std::optional<Visibility> Vis = + getExplicitVisibility(ND, computation)) { LV.mergeVisibility(*Vis, true); break; } @@ -780,6 +763,7 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D, // // Note that we don't want to make the variable non-external // because of this, but unique-external linkage suits us. + if (Context.getLangOpts().CPlusPlus && !isFirstInExternCContext(Var) && !IgnoreVarTypeLinkage) { LinkageInfo TypeLV = getLVForType(*Var->getType(), computation); @@ -813,6 +797,16 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D, if (Function->getStorageClass() == SC_PrivateExtern) LV.mergeVisibility(HiddenVisibility, true); + // OpenMP target declare device functions are not callable from the host so + // they should not be exported from the device image. This applies to all + // functions as the host-callable kernel functions are emitted at codegen. + if (Context.getLangOpts().OpenMP && + Context.getLangOpts().OpenMPIsTargetDevice && + ((Context.getTargetInfo().getTriple().isAMDGPU() || + Context.getTargetInfo().getTriple().isNVPTX()) || + OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(Function))) + LV.mergeVisibility(HiddenVisibility, /*newExplicit=*/false); + // Note that Sema::MergeCompatibleFunctionDecls already takes care of // merging storage classes and visibility attributes, so we don't have to // look at previous decls in here. @@ -906,10 +900,6 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D, if (!isExternallyVisible(LV.getLinkage())) return LinkageInfo(LV.getLinkage(), DefaultVisibility, false); - // Mark the symbols as hidden when compiling for the device. - if (Context.getLangOpts().OpenMP && Context.getLangOpts().OpenMPIsDevice) - LV.mergeVisibility(HiddenVisibility, /*newExplicit=*/false); - return LV; } @@ -939,7 +929,7 @@ LinkageComputer::getLVForClassMember(const NamedDecl *D, // If we have an explicit visibility attribute, merge that in. if (!hasExplicitVisibilityAlready(computation)) { - if (Optional<Visibility> Vis = getExplicitVisibility(D, computation)) + if (std::optional<Visibility> Vis = getExplicitVisibility(D, computation)) LV.mergeVisibility(*Vis, true); // If we're paying attention to global visibility, apply // -finline-visibility-hidden if this is an inline method. @@ -995,6 +985,17 @@ LinkageComputer::getLVForClassMember(const NamedDecl *D, explicitSpecSuppressor = MD; } + // OpenMP target declare device functions are not callable from the host so + // they should not be exported from the device image. This applies to all + // functions as the host-callable kernel functions are emitted at codegen. + ASTContext &Context = D->getASTContext(); + if (Context.getLangOpts().OpenMP && + Context.getLangOpts().OpenMPIsTargetDevice && + ((Context.getTargetInfo().getTriple().isAMDGPU() || + Context.getTargetInfo().getTriple().isNVPTX()) || + OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(MD))) + LV.mergeVisibility(HiddenVisibility, /*newExplicit=*/false); + } else if (const auto *RD = dyn_cast<CXXRecordDecl>(D)) { if (const auto *spec = dyn_cast<ClassTemplateSpecializationDecl>(RD)) { mergeTemplateLV(LV, spec, computation); @@ -1078,6 +1079,42 @@ bool NamedDecl::isLinkageValid() const { return L == getCachedLinkage(); } +bool NamedDecl::isPlaceholderVar(const LangOptions &LangOpts) const { + // [C++2c] [basic.scope.scope]/p5 + // A declaration is name-independent if its name is _ and it declares + // - a variable with automatic storage duration, + // - a structured binding not inhabiting a namespace scope, + // - the variable introduced by an init-capture + // - or a non-static data member. + + if (!LangOpts.CPlusPlus || !getIdentifier() || + !getIdentifier()->isPlaceholder()) + return false; + if (isa<FieldDecl>(this)) + return true; + if (const auto *IFD = dyn_cast<IndirectFieldDecl>(this)) { + if (!getDeclContext()->isFunctionOrMethod() && + !getDeclContext()->isRecord()) + return false; + const VarDecl *VD = IFD->getVarDecl(); + return !VD || VD->getStorageDuration() == SD_Automatic; + } + // and it declares a variable with automatic storage duration + if (const auto *VD = dyn_cast<VarDecl>(this)) { + if (isa<ParmVarDecl>(VD)) + return false; + if (VD->isInitCapture()) + return true; + return VD->getStorageDuration() == StorageDuration::SD_Automatic; + } + if (const auto *BD = dyn_cast<BindingDecl>(this); + BD && getDeclContext()->isFunctionOrMethod()) { + const VarDecl *VD = BD->getHoldingVar(); + return !VD || VD->getStorageDuration() == StorageDuration::SD_Automatic; + } + return false; +} + ReservedIdentifierStatus NamedDecl::isReserved(const LangOptions &LangOpts) const { const IdentifierInfo *II = getIdentifier(); @@ -1088,13 +1125,29 @@ NamedDecl::isReserved(const LangOptions &LangOpts) const { return ReservedIdentifierStatus::NotReserved; ReservedIdentifierStatus Status = II->isReserved(LangOpts); - if (Status == ReservedIdentifierStatus::StartsWithUnderscoreAtGlobalScope) { - // Check if we're at TU level or not. + if (isReservedAtGlobalScope(Status) && !isReservedInAllContexts(Status)) { + // This name is only reserved at global scope. Check if this declaration + // conflicts with a global scope declaration. if (isa<ParmVarDecl>(this) || isTemplateParameter()) return ReservedIdentifierStatus::NotReserved; + + // C++ [dcl.link]/7: + // Two declarations [conflict] if [...] one declares a function or + // variable with C language linkage, and the other declares [...] a + // variable that belongs to the global scope. + // + // Therefore names that are reserved at global scope are also reserved as + // names of variables and functions with C language linkage. const DeclContext *DC = getDeclContext()->getRedeclContext(); - if (!DC->isTranslationUnit()) - return ReservedIdentifierStatus::NotReserved; + if (DC->isTranslationUnit()) + return Status; + if (auto *VD = dyn_cast<VarDecl>(this)) + if (VD->isExternC()) + return ReservedIdentifierStatus::StartsWithUnderscoreAndIsExternC; + if (auto *FD = dyn_cast<FunctionDecl>(this)) + if (FD->isExternC()) + return ReservedIdentifierStatus::StartsWithUnderscoreAndIsExternC; + return ReservedIdentifierStatus::NotReserved; } return Status; @@ -1121,18 +1174,61 @@ Linkage NamedDecl::getLinkageInternal() const { .getLinkage(); } +/// Determine whether D is attached to a named module. +static bool isInNamedModule(const NamedDecl *D) { + if (auto *M = D->getOwningModule()) + return M->isNamedModule(); + return false; +} + +static bool isExportedFromModuleInterfaceUnit(const NamedDecl *D) { + // FIXME: Handle isModulePrivate. + switch (D->getModuleOwnershipKind()) { + case Decl::ModuleOwnershipKind::Unowned: + case Decl::ModuleOwnershipKind::ReachableWhenImported: + case Decl::ModuleOwnershipKind::ModulePrivate: + return false; + case Decl::ModuleOwnershipKind::Visible: + case Decl::ModuleOwnershipKind::VisibleWhenImported: + return isInNamedModule(D); + } + llvm_unreachable("unexpected module ownership kind"); +} + +/// Get the linkage from a semantic point of view. Entities in +/// anonymous namespaces are external (in c++98). +Linkage NamedDecl::getFormalLinkage() const { + Linkage InternalLinkage = getLinkageInternal(); + + // C++ [basic.link]p4.8: + // - if the declaration of the name is attached to a named module and is not + // exported + // the name has module linkage; + // + // [basic.namespace.general]/p2 + // A namespace is never attached to a named module and never has a name with + // module linkage. + if (isInNamedModule(this) && InternalLinkage == Linkage::External && + !isExportedFromModuleInterfaceUnit( + cast<NamedDecl>(this->getCanonicalDecl())) && + !isa<NamespaceDecl>(this)) + InternalLinkage = Linkage::Module; + + return clang::getFormalLinkage(InternalLinkage); +} + LinkageInfo NamedDecl::getLinkageAndVisibility() const { return LinkageComputer{}.getDeclLinkageAndVisibility(this); } -static Optional<Visibility> +static std::optional<Visibility> getExplicitVisibilityAux(const NamedDecl *ND, NamedDecl::ExplicitVisibilityKind kind, bool IsMostRecent) { assert(!IsMostRecent || ND == ND->getMostRecentDecl()); // Check the declaration itself first. - if (Optional<Visibility> V = getVisibilityOf(ND, kind)) + if (std::optional<Visibility> V = getVisibilityOf(ND, kind)) return V; // If this is a member class of a specialization of a class template @@ -1152,11 +1248,11 @@ getExplicitVisibilityAux(const NamedDecl *ND, const auto *TD = spec->getSpecializedTemplate()->getTemplatedDecl(); while (TD != nullptr) { auto Vis = getVisibilityOf(TD, kind); - if (Vis != None) + if (Vis != std::nullopt) return Vis; TD = TD->getPreviousDecl(); } - return None; + return std::nullopt; } // Use the most recent declaration. @@ -1177,7 +1273,7 @@ getExplicitVisibilityAux(const NamedDecl *ND, return getVisibilityOf(VTSD->getSpecializedTemplate()->getTemplatedDecl(), kind); - return None; + return std::nullopt; } // Also handle function template specializations. if (const auto *fn = dyn_cast<FunctionDecl>(ND)) { @@ -1194,17 +1290,17 @@ getExplicitVisibilityAux(const NamedDecl *ND, if (InstantiatedFrom) return getVisibilityOf(InstantiatedFrom, kind); - return None; + return std::nullopt; } // The visibility of a template is stored in the templated decl. if (const auto *TD = dyn_cast<TemplateDecl>(ND)) return getVisibilityOf(TD->getTemplatedDecl(), kind); - return None; + return std::nullopt; } -Optional<Visibility> +std::optional<Visibility> NamedDecl::getExplicitVisibility(ExplicitVisibilityKind kind) const { return getExplicitVisibilityAux(this, kind, false); } @@ -1219,8 +1315,13 @@ LinkageInfo LinkageComputer::getLVForClosure(const DeclContext *DC, else if (isa<ParmVarDecl>(ContextDecl)) Owner = dyn_cast<NamedDecl>(ContextDecl->getDeclContext()->getRedeclContext()); - else + else if (isa<ImplicitConceptSpecializationDecl>(ContextDecl)) { + // Replace with the concept's owning decl, which is either a namespace or a + // TU, so this needs a dyn_cast. + Owner = dyn_cast<NamedDecl>(ContextDecl->getDeclContext()); + } else { Owner = cast<NamedDecl>(ContextDecl); + } if (!Owner) return LinkageInfo::none(); @@ -1239,7 +1340,7 @@ LinkageInfo LinkageComputer::getLVForClosure(const DeclContext *DC, // visible, then the lambda is too. We apply the same rules to blocks. if (!isExternallyVisible(OwnerLV.getLinkage())) return LinkageInfo::none(); - return LinkageInfo(VisibleNoLinkage, OwnerLV.getVisibility(), + return LinkageInfo(Linkage::VisibleNone, OwnerLV.getVisibility(), OwnerLV.isVisibilityExplicit()); } @@ -1248,15 +1349,15 @@ LinkageInfo LinkageComputer::getLVForLocalDecl(const NamedDecl *D, if (const auto *Function = dyn_cast<FunctionDecl>(D)) { if (Function->isInAnonymousNamespace() && !isFirstInExternCContext(Function)) - return getInternalLinkageFor(Function); + return LinkageInfo::internal(); // This is a "void f();" which got merged with a file static. if (Function->getCanonicalDecl()->getStorageClass() == SC_Static) - return getInternalLinkageFor(Function); + return LinkageInfo::internal(); LinkageInfo LV; if (!hasExplicitVisibilityAlready(computation)) { - if (Optional<Visibility> Vis = + if (std::optional<Visibility> Vis = getExplicitVisibility(Function, computation)) LV.mergeVisibility(*Vis, true); } @@ -1271,19 +1372,20 @@ LinkageInfo LinkageComputer::getLVForLocalDecl(const NamedDecl *D, if (const auto *Var = dyn_cast<VarDecl>(D)) { if (Var->hasExternalStorage()) { if (Var->isInAnonymousNamespace() && !isFirstInExternCContext(Var)) - return getInternalLinkageFor(Var); + return LinkageInfo::internal(); LinkageInfo LV; if (Var->getStorageClass() == SC_PrivateExtern) LV.mergeVisibility(HiddenVisibility, true); else if (!hasExplicitVisibilityAlready(computation)) { - if (Optional<Visibility> Vis = getExplicitVisibility(Var, computation)) + if (std::optional<Visibility> Vis = + getExplicitVisibility(Var, computation)) LV.mergeVisibility(*Vis, true); } if (const VarDecl *Prev = Var->getPreviousDecl()) { LinkageInfo PrevLV = getLVForDecl(Prev, computation); - if (PrevLV.getLinkage()) + if (PrevLV.getLinkage() != Linkage::Invalid) LV.setLinkage(PrevLV.getLinkage()); LV.mergeVisibility(PrevLV); } @@ -1334,14 +1436,14 @@ LinkageInfo LinkageComputer::getLVForLocalDecl(const NamedDecl *D, computation.isValueVisibility() ? Context.getLangOpts().getValueVisibilityMode() : Context.getLangOpts().getTypeVisibilityMode(); - return LinkageInfo(VisibleNoLinkage, globalVisibility, + return LinkageInfo(Linkage::VisibleNone, globalVisibility, /*visibilityExplicit=*/false); } } } if (!isExternallyVisible(LV.getLinkage())) return LinkageInfo::none(); - return LinkageInfo(VisibleNoLinkage, LV.getVisibility(), + return LinkageInfo(Linkage::VisibleNone, LV.getVisibility(), LV.isVisibilityExplicit()); } @@ -1350,7 +1452,7 @@ LinkageInfo LinkageComputer::computeLVForDecl(const NamedDecl *D, bool IgnoreVarTypeLinkage) { // Internal_linkage attribute overrides other considerations. if (D->hasAttr<InternalLinkageAttr>()) - return getInternalLinkageFor(D); + return LinkageInfo::internal(); // Objective-C: treat all Objective-C declarations as having external // linkage. @@ -1408,7 +1510,7 @@ LinkageInfo LinkageComputer::computeLVForDecl(const NamedDecl *D, if (Record->hasKnownLambdaInternalLinkage() || !Record->getLambdaManglingNumber()) { // This lambda has no mangling number, so it's internal. - return getInternalLinkageFor(D); + return LinkageInfo::internal(); } return getLVForClosure( @@ -1467,12 +1569,12 @@ LinkageInfo LinkageComputer::getLVForDecl(const NamedDecl *D, LVComputationKind computation) { // Internal_linkage attribute overrides other considerations. if (D->hasAttr<InternalLinkageAttr>()) - return getInternalLinkageFor(D); + return LinkageInfo::internal(); if (computation.IgnoreAllVisibility && D->hasCachedLinkage()) return LinkageInfo(D->getCachedLinkage(), DefaultVisibility, false); - if (llvm::Optional<LinkageInfo> LI = lookup(D, computation)) + if (std::optional<LinkageInfo> LI = lookup(D, computation)) return *LI; LinkageInfo LV = computeLVForDecl(D, computation); @@ -1494,7 +1596,7 @@ LinkageInfo LinkageComputer::getLVForDecl(const NamedDecl *D, // that all other computed linkages match, check that the one we just // computed also does. NamedDecl *Old = nullptr; - for (auto I : D->redecls()) { + for (auto *I : D->redecls()) { auto *T = cast<NamedDecl>(I); if (T == D) continue; @@ -1520,6 +1622,11 @@ LinkageInfo LinkageComputer::getDeclLinkageAndVisibility(const NamedDecl *D) { } Module *Decl::getOwningModuleForLinkage(bool IgnoreLinkage) const { + if (isa<NamespaceDecl>(this)) + // Namespaces never have module linkage. It is the entities within them + // that [may] do. + return nullptr; + Module *M = getOwningModule(); if (!M) return nullptr; @@ -1530,24 +1637,30 @@ Module *Decl::getOwningModuleForLinkage(bool IgnoreLinkage) const { return nullptr; case Module::ModuleInterfaceUnit: + case Module::ModuleImplementationUnit: + case Module::ModulePartitionInterface: + case Module::ModulePartitionImplementation: return M; - case Module::GlobalModuleFragment: { + case Module::ModuleHeaderUnit: + case Module::ExplicitGlobalModuleFragment: + case Module::ImplicitGlobalModuleFragment: { // External linkage declarations in the global module have no owning module // for linkage purposes. But internal linkage declarations in the global // module fragment of a particular module are owned by that module for // linkage purposes. + // FIXME: p1815 removes the need for this distinction -- there are no + // internal linkage declarations that need to be referred to from outside + // this TU. if (IgnoreLinkage) return nullptr; bool InternalLinkage; if (auto *ND = dyn_cast<NamedDecl>(this)) InternalLinkage = !ND->hasExternalFormalLinkage(); - else { - auto *NSD = dyn_cast<NamespaceDecl>(this); - InternalLinkage = (NSD && NSD->isAnonymousNamespace()) || - isInAnonymousNamespace(); - } - return InternalLinkage ? M->Parent : nullptr; + else + InternalLinkage = isInAnonymousNamespace(); + return InternalLinkage ? M->Kind == Module::ModuleHeaderUnit ? M : M->Parent + : nullptr; } case Module::PrivateModuleFragment: @@ -1559,15 +1672,19 @@ Module *Decl::getOwningModuleForLinkage(bool IgnoreLinkage) const { llvm_unreachable("unknown module kind"); } -void NamedDecl::printName(raw_ostream &os) const { - os << Name; +void NamedDecl::printName(raw_ostream &OS, const PrintingPolicy &Policy) const { + Name.print(OS, Policy); +} + +void NamedDecl::printName(raw_ostream &OS) const { + printName(OS, getASTContext().getPrintingPolicy()); } std::string NamedDecl::getQualifiedNameAsString() const { std::string QualName; llvm::raw_string_ostream OS(QualName); printQualifiedName(OS, getASTContext().getPrintingPolicy()); - return OS.str(); + return QualName; } void NamedDecl::printQualifiedName(raw_ostream &OS) const { @@ -1578,7 +1695,7 @@ void NamedDecl::printQualifiedName(raw_ostream &OS, const PrintingPolicy &P) const { if (getDeclContext()->isFunctionOrMethod()) { // We do not print '(anonymous)' for function parameters without name. - printName(OS); + printName(OS, P); return; } printNestedNameSpecifier(OS, P); @@ -1589,7 +1706,7 @@ void NamedDecl::printQualifiedName(raw_ostream &OS, // fall back to "(anonymous)". SmallString<64> NameBuffer; llvm::raw_svector_ostream NameOS(NameBuffer); - printName(NameOS); + printName(NameOS, P); if (NameBuffer.empty()) OS << "(anonymous)"; else @@ -1647,8 +1764,7 @@ void NamedDecl::printNestedNameSpecifier(raw_ostream &OS, NameInScope = ND->getDeclName(); } - for (unsigned I = Contexts.size(); I != 0; --I) { - const DeclContext *DC = Contexts[I - 1]; + for (const DeclContext *DC : llvm::reverse(Contexts)) { if (const auto *Spec = dyn_cast<ClassTemplateSpecializationDecl>(DC)) { OS << Spec->getName(); const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); @@ -1713,7 +1829,7 @@ void NamedDecl::getNameForDiagnostic(raw_ostream &OS, if (Qualified) printQualifiedName(OS, Policy); else - printName(OS); + printName(OS, Policy); } template<typename T> static bool isRedeclarableImpl(Redeclarable<T> *) { @@ -1731,7 +1847,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 @@ -1761,13 +1878,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( @@ -1784,7 +1901,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; @@ -1808,12 +1925,26 @@ bool NamedDecl::declarationReplaces(NamedDecl *OldD, bool IsKnownNewer) const { } bool NamedDecl::hasLinkage() const { - return getFormalLinkage() != NoLinkage; + switch (getFormalLinkage()) { + case Linkage::Invalid: + llvm_unreachable("Linkage hasn't been computed!"); + case Linkage::None: + return false; + case Linkage::Internal: + return true; + case Linkage::UniqueExternal: + case Linkage::VisibleNone: + llvm_unreachable("Non-formal linkage is not allowed here!"); + case Linkage::Module: + case Linkage::External: + return true; + } + llvm_unreachable("Unhandled Linkage enum"); } NamedDecl *NamedDecl::getUnderlyingDeclImpl() { NamedDecl *ND = this; - while (auto *UD = dyn_cast<UsingShadowDecl>(ND)) + if (auto *UD = dyn_cast<UsingShadowDecl>(ND)) ND = UD->getTargetDecl(); if (auto *AD = dyn_cast<ObjCCompatibleAliasDecl>(ND)) @@ -1835,7 +1966,7 @@ bool NamedDecl::isCXXInstanceMember() const { if (isa<FieldDecl>(D) || isa<IndirectFieldDecl>(D) || isa<MSPropertyDecl>(D)) return true; - if (const auto *MD = dyn_cast_or_null<CXXMethodDecl>(D->getAsFunction())) + if (const auto *MD = dyn_cast_if_present<CXXMethodDecl>(D->getAsFunction())) return MD->isInstance(); return false; } @@ -1999,7 +2130,7 @@ const char *VarDecl::getStorageClassSpecifierString(StorageClass SC) { VarDecl::VarDecl(Kind DK, ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, - IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, + const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass SC) : DeclaratorDecl(DK, DC, IdLoc, Id, T, TInfo, StartLoc), redeclarable_base(C) { @@ -2014,10 +2145,9 @@ VarDecl::VarDecl(Kind DK, ASTContext &C, DeclContext *DC, // Everything else is implicitly initialized to false. } -VarDecl *VarDecl::Create(ASTContext &C, DeclContext *DC, - SourceLocation StartL, SourceLocation IdL, - IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, - StorageClass S) { +VarDecl *VarDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation StartL, + SourceLocation IdL, const IdentifierInfo *Id, + QualType T, TypeSourceInfo *TInfo, StorageClass S) { return new (C, DC) VarDecl(Var, C, DC, StartL, IdL, Id, T, TInfo, S); } @@ -2074,8 +2204,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 @@ -2216,20 +2345,24 @@ VarDecl *VarDecl::getActingDefinition() { return nullptr; VarDecl *LastTentative = nullptr; - VarDecl *First = getFirstDecl(); - for (auto I : First->redecls()) { - Kind = I->isThisDeclarationADefinition(); + + // Loop through the declaration chain, starting with the most recent. + for (VarDecl *Decl = getMostRecentDecl(); Decl; + Decl = Decl->getPreviousDecl()) { + Kind = Decl->isThisDeclarationADefinition(); if (Kind == Definition) return nullptr; - if (Kind == TentativeDefinition) - LastTentative = I; + // Record the first (most recent) TentativeDefinition that is encountered. + if (Kind == TentativeDefinition && !LastTentative) + LastTentative = Decl; } + return LastTentative; } VarDecl *VarDecl::getDefinition(ASTContext &C) { VarDecl *First = getFirstDecl(); - for (auto I : First->redecls()) { + for (auto *I : First->redecls()) { if (I->isThisDeclarationADefinition(C) == Definition) return I; } @@ -2240,7 +2373,7 @@ VarDecl::DefinitionKind VarDecl::hasDefinition(ASTContext &C) const { DefinitionKind Kind = DeclarationOnly; const VarDecl *First = getFirstDecl(); - for (auto I : First->redecls()) { + for (auto *I : First->redecls()) { Kind = std::max(Kind, I->isThisDeclarationADefinition(C)); if (Kind == Definition) break; @@ -2250,7 +2383,7 @@ VarDecl::DefinitionKind VarDecl::hasDefinition(ASTContext &C) const { } const Expr *VarDecl::getAnyInitializer(const VarDecl *&D) const { - for (auto I : redecls()) { + for (auto *I : redecls()) { if (auto Expr = I->getInit()) { D = I; return Expr; @@ -2274,19 +2407,22 @@ Expr *VarDecl::getInit() { if (auto *S = Init.dyn_cast<Stmt *>()) return cast<Expr>(S); - return cast_or_null<Expr>(Init.get<EvaluatedStmt *>()->Value); + auto *Eval = getEvaluatedStmt(); + return cast<Expr>(Eval->Value.isOffset() + ? Eval->Value.get(getASTContext().getExternalSource()) + : Eval->Value.get(nullptr)); } Stmt **VarDecl::getInitAddress() { if (auto *ES = Init.dyn_cast<EvaluatedStmt *>()) - return &ES->Value; + return ES->Value.getAddressOfPointer(getASTContext().getExternalSource()); return Init.getAddrOfPtr1(); } VarDecl *VarDecl::getInitializingDeclaration() { VarDecl *Def = nullptr; - for (auto I : redecls()) { + for (auto *I : redecls()) { if (I->hasInit()) return I; @@ -2409,14 +2545,14 @@ EvaluatedStmt *VarDecl::getEvaluatedStmt() const { APValue *VarDecl::evaluateValue() const { SmallVector<PartialDiagnosticAt, 8> Notes; - return evaluateValue(Notes); + return evaluateValueImpl(Notes, hasConstantInitialization()); } -APValue *VarDecl::evaluateValue( - SmallVectorImpl<PartialDiagnosticAt> &Notes) const { +APValue *VarDecl::evaluateValueImpl(SmallVectorImpl<PartialDiagnosticAt> &Notes, + bool IsConstantInitialization) const { EvaluatedStmt *Eval = ensureEvaluatedStmt(); - const auto *Init = cast<Expr>(Eval->Value); + const auto *Init = getInit(); assert(!Init->isValueDependent()); // We only produce notes indicating why an initializer is non-constant the @@ -2432,8 +2568,16 @@ APValue *VarDecl::evaluateValue( Eval->IsEvaluating = true; - bool Result = Init->EvaluateAsInitializer(Eval->Evaluated, getASTContext(), - this, Notes); + ASTContext &Ctx = getASTContext(); + bool Result = Init->EvaluateAsInitializer(Eval->Evaluated, Ctx, this, Notes, + IsConstantInitialization); + + // In C++, this isn't a constant initializer if we produced notes. In that + // case, we can't keep the result, because it may only be correct under the + // assumption that the initializer is a constant context. + if (IsConstantInitialization && Ctx.getLangOpts().CPlusPlus && + !Notes.empty()) + Result = false; // Ensure the computed APValue is cleaned up later if evaluation succeeded, // or that it's empty (so that there's nothing to clean up) if evaluation @@ -2441,7 +2585,7 @@ APValue *VarDecl::evaluateValue( if (!Result) Eval->Evaluated = APValue(); else if (Eval->Evaluated.needsCleanup()) - getASTContext().addDestruction(&Eval->Evaluated); + Ctx.addDestruction(&Eval->Evaluated); Eval->IsEvaluating = false; Eval->WasEvaluated = true; @@ -2492,10 +2636,17 @@ bool VarDecl::checkForConstantInitialization( "already evaluated var value before checking for constant init"); assert(getASTContext().getLangOpts().CPlusPlus && "only meaningful in C++"); - assert(!cast<Expr>(Eval->Value)->isValueDependent()); + assert(!getInit()->isValueDependent()); // Evaluate the initializer to check whether it's a constant expression. - Eval->HasConstantInitialization = evaluateValue(Notes) && Notes.empty(); + Eval->HasConstantInitialization = + evaluateValueImpl(Notes, true) && Notes.empty(); + + // If evaluation as a constant initializer failed, allow re-evaluation as a + // non-constant initializer if we later find we want the value. + if (!Eval->HasConstantInitialization) + Eval->WasEvaluated = false; + return Eval->HasConstantInitialization; } @@ -2521,7 +2672,7 @@ bool VarDecl::isNonEscapingByref() const { bool VarDecl::hasDependentAlignment() const { QualType T = getType(); - return T->isDependentType() || T->isUndeducedAutoType() || + return T->isDependentType() || T->isUndeducedType() || llvm::any_of(specific_attrs<AlignedAttr>(), [](const AlignedAttr *AA) { return AA->isAlignmentDependent(); }); @@ -2667,6 +2818,42 @@ VarDecl::needsDestruction(const ASTContext &Ctx) const { return getType().isDestructedType(); } +bool VarDecl::hasFlexibleArrayInit(const ASTContext &Ctx) const { + assert(hasInit() && "Expect initializer to check for flexible array init"); + auto *Ty = getType()->getAs<RecordType>(); + if (!Ty || !Ty->getDecl()->hasFlexibleArrayMember()) + return false; + auto *List = dyn_cast<InitListExpr>(getInit()->IgnoreParens()); + if (!List) + return false; + const Expr *FlexibleInit = List->getInit(List->getNumInits() - 1); + auto InitTy = Ctx.getAsConstantArrayType(FlexibleInit->getType()); + if (!InitTy) + return false; + return InitTy->getSize() != 0; +} + +CharUnits VarDecl::getFlexibleArrayInitChars(const ASTContext &Ctx) const { + assert(hasInit() && "Expect initializer to check for flexible array init"); + auto *Ty = getType()->getAs<RecordType>(); + if (!Ty || !Ty->getDecl()->hasFlexibleArrayMember()) + return CharUnits::Zero(); + auto *List = dyn_cast<InitListExpr>(getInit()->IgnoreParens()); + if (!List || List->getNumInits() == 0) + return CharUnits::Zero(); + const Expr *FlexibleInit = List->getInit(List->getNumInits() - 1); + auto InitTy = Ctx.getAsConstantArrayType(FlexibleInit->getType()); + if (!InitTy) + return CharUnits::Zero(); + CharUnits FlexibleArraySize = Ctx.getTypeSizeInChars(InitTy); + const ASTRecordLayout &RL = Ctx.getASTRecordLayout(Ty->getDecl()); + CharUnits FlexibleArrayOffset = + Ctx.toCharUnitsFromBits(RL.getFieldOffset(RL.getFieldCount() - 1)); + if (FlexibleArrayOffset + FlexibleArraySize < RL.getSize()) + return CharUnits::Zero(); + return FlexibleArrayOffset + FlexibleArraySize - RL.getSize(); +} + MemberSpecializationInfo *VarDecl::getMemberSpecializationInfo() const { if (isStaticDataMember()) // FIXME: Remove ? @@ -2754,11 +2941,15 @@ SourceRange ParmVarDecl::getSourceRange() const { } bool ParmVarDecl::isDestroyedInCallee() const { + // ns_consumed only affects code generation in ARC if (hasAttr<NSConsumedAttr>()) - return true; + return getASTContext().getLangOpts().ObjCAutoRefCount; - auto *RT = getType()->getAs<RecordType>(); - if (RT && RT->getDecl()->isParamDestroyedInCallee()) + // FIXME: isParamDestroyedInCallee() should probably imply + // isDestructedType() + const auto *RT = getType()->getAs<RecordType>(); + if (RT && RT->getDecl()->isParamDestroyedInCallee() && + getType().isDestructedType()) return true; return false; @@ -2770,7 +2961,7 @@ Expr *ParmVarDecl::getDefaultArg() { "Default argument is not yet instantiated!"); Expr *Arg = getInit(); - if (auto *E = dyn_cast_or_null<FullExpr>(Arg)) + if (auto *E = dyn_cast_if_present<FullExpr>(Arg)) return E->getSubExpr(); return Arg; @@ -2809,7 +3000,7 @@ void ParmVarDecl::setUninstantiatedDefaultArg(Expr *arg) { Expr *ParmVarDecl::getUninstantiatedDefaultArg() { assert(hasUninstantiatedDefaultArg() && "Wrong kind of initialization expression!"); - return cast_or_null<Expr>(Init.get<Stmt *>()); + return cast_if_present<Expr>(Init.get<Stmt *>()); } bool ParmVarDecl::hasDefaultArg() const { @@ -2837,7 +3028,7 @@ FunctionDecl::FunctionDecl(Kind DK, ASTContext &C, DeclContext *DC, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, StorageClass S, - bool isInlineSpecified, + bool UsesFPIntrin, bool isInlineSpecified, ConstexprSpecKind ConstexprKind, Expr *TrailingRequiresClause) : DeclaratorDecl(DK, DC, NameInfo.getLoc(), NameInfo.getName(), T, TInfo, @@ -2849,7 +3040,7 @@ FunctionDecl::FunctionDecl(Kind DK, ASTContext &C, DeclContext *DC, FunctionDeclBits.IsInline = isInlineSpecified; FunctionDeclBits.IsInlineSpecified = isInlineSpecified; FunctionDeclBits.IsVirtualAsWritten = false; - FunctionDeclBits.IsPure = false; + FunctionDeclBits.IsPureVirtual = false; FunctionDeclBits.HasInheritedPrototype = false; FunctionDeclBits.HasWrittenPrototype = true; FunctionDeclBits.IsDeleted = false; @@ -2858,17 +3049,21 @@ FunctionDecl::FunctionDecl(Kind DK, ASTContext &C, DeclContext *DC, FunctionDeclBits.IsDefaulted = false; FunctionDeclBits.IsExplicitlyDefaulted = false; FunctionDeclBits.HasDefaultedFunctionInfo = false; + FunctionDeclBits.IsIneligibleOrNotSelected = false; FunctionDeclBits.HasImplicitReturnZero = false; FunctionDeclBits.IsLateTemplateParsed = false; FunctionDeclBits.ConstexprKind = static_cast<uint64_t>(ConstexprKind); + FunctionDeclBits.BodyContainsImmediateEscalatingExpression = false; FunctionDeclBits.InstantiationIsPending = false; FunctionDeclBits.UsesSEHTry = false; - FunctionDeclBits.UsesFPIntrin = false; + FunctionDeclBits.UsesFPIntrin = UsesFPIntrin; FunctionDeclBits.HasSkippedBody = false; FunctionDeclBits.WillHaveBody = false; FunctionDeclBits.IsMultiVersion = false; - FunctionDeclBits.IsCopyDeductionCandidate = false; + FunctionDeclBits.DeductionCandidateKind = + static_cast<unsigned char>(DeductionCandidate::Normal); FunctionDeclBits.HasODRHash = false; + FunctionDeclBits.FriendConstraintRefersToEnclosingTemplate = false; if (TrailingRequiresClause) setTrailingRequiresClause(TrailingRequiresClause); } @@ -2914,7 +3109,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; @@ -2925,7 +3120,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. @@ -3012,8 +3207,8 @@ void FunctionDecl::setBody(Stmt *B) { EndRangeLoc = B->getEndLoc(); } -void FunctionDecl::setPure(bool P) { - FunctionDeclBits.IsPure = P; +void FunctionDecl::setIsPureVirtual(bool P) { + FunctionDeclBits.IsPureVirtual = P; if (P) if (auto *Parent = dyn_cast<CXXRecordDecl>(getDeclContext())) Parent->markedVirtualFunctionPure(); @@ -3021,10 +3216,48 @@ 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); } +bool FunctionDecl::isImmediateEscalating() const { + // C++23 [expr.const]/p17 + // An immediate-escalating function is + // - the call operator of a lambda that is not declared with the consteval + // specifier, + if (isLambdaCallOperator(this) && !isConsteval()) + return true; + // - a defaulted special member function that is not declared with the + // consteval specifier, + if (isDefaulted() && !isConsteval()) + return true; + // - a function that results from the instantiation of a templated entity + // defined with the constexpr specifier. + TemplatedKind TK = getTemplatedKind(); + if (TK != TK_NonTemplate && TK != TK_DependentNonTemplate && + isConstexprSpecified()) + return true; + return false; +} + +bool FunctionDecl::isImmediateFunction() const { + // C++23 [expr.const]/p18 + // An immediate function is a function or constructor that is + // - declared with the consteval specifier + if (isConsteval()) + return true; + // - an immediate-escalating function F whose function body contains an + // immediate-escalating expression + if (isImmediateEscalating() && BodyContainsImmediateEscalatingExpressions()) + return true; + + if (const auto *MD = dyn_cast<CXXMethodDecl>(this); + MD && MD->isLambdaStaticInvoker()) + return MD->getParent()->getLambdaCallOperator()->isImmediateFunction(); + + return false; +} + bool FunctionDecl::isMain() const { const TranslationUnitDecl *tunit = dyn_cast<TranslationUnitDecl>(getDeclContext()->getRedeclContext()); @@ -3061,11 +3294,13 @@ bool FunctionDecl::isMSVCRTEntryPoint() const { } bool FunctionDecl::isReservedGlobalPlacementOperator() const { - assert(getDeclName().getNameKind() == DeclarationName::CXXOperatorName); - assert(getDeclName().getCXXOverloadedOperator() == OO_New || - getDeclName().getCXXOverloadedOperator() == OO_Delete || - getDeclName().getCXXOverloadedOperator() == OO_Array_New || - getDeclName().getCXXOverloadedOperator() == OO_Array_Delete); + if (getDeclName().getNameKind() != DeclarationName::CXXOperatorName) + return false; + if (getDeclName().getCXXOverloadedOperator() != OO_New && + getDeclName().getCXXOverloadedOperator() != OO_Delete && + getDeclName().getCXXOverloadedOperator() != OO_Array_New && + getDeclName().getCXXOverloadedOperator() != OO_Array_Delete) + return false; if (!getDeclContext()->getRedeclContext()->isTranslationUnit()) return false; @@ -3074,9 +3309,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*. @@ -3084,7 +3319,7 @@ bool FunctionDecl::isReservedGlobalPlacementOperator() const { } bool FunctionDecl::isReplaceableGlobalAllocationFunction( - Optional<unsigned> *AlignmentParam, bool *IsNothrow) const { + std::optional<unsigned> *AlignmentParam, bool *IsNothrow) const { if (getDeclName().getNameKind() != DeclarationName::CXXOperatorName) return false; if (getDeclName().getCXXOverloadedOperator() != OO_New && @@ -3101,7 +3336,7 @@ bool FunctionDecl::isReplaceableGlobalAllocationFunction( return false; const auto *FPT = getType()->castAs<FunctionProtoType>(); - if (FPT->getNumParams() == 0 || FPT->getNumParams() > 3 || FPT->isVariadic()) + if (FPT->getNumParams() == 0 || FPT->getNumParams() > 4 || FPT->isVariadic()) return false; // If this is a single-parameter function, it must be a replaceable global @@ -3111,7 +3346,7 @@ bool FunctionDecl::isReplaceableGlobalAllocationFunction( unsigned Params = 1; QualType Ty = FPT->getParamType(Params); - ASTContext &Ctx = getASTContext(); + const ASTContext &Ctx = getASTContext(); auto Consume = [&] { ++Params; @@ -3136,8 +3371,8 @@ bool FunctionDecl::isReplaceableGlobalAllocationFunction( *AlignmentParam = Params; } - // Finally, if this is not a sized delete, the final parameter can - // be a 'const std::nothrow_t&'. + // If this is not a sized delete, the next parameter can be a + // 'const std::nothrow_t&'. if (!IsSizedDelete && !Ty.isNull() && Ty->isReferenceType()) { Ty = Ty->getPointeeType(); if (Ty.getCVRQualifiers() != Qualifiers::Const) @@ -3149,6 +3384,20 @@ bool FunctionDecl::isReplaceableGlobalAllocationFunction( } } + // Finally, recognize the not yet standard versions of new that take a + // hot/cold allocation hint (__hot_cold_t). These are currently supported by + // tcmalloc (see + // https://github.com/google/tcmalloc/blob/220043886d4e2efff7a5702d5172cb8065253664/tcmalloc/malloc_extension.h#L53). + if (!IsSizedDelete && !Ty.isNull() && Ty->isEnumeralType()) { + QualType T = Ty; + while (const auto *TD = T->getAs<TypedefType>()) + T = TD->getDecl()->getUnderlyingType(); + const IdentifierInfo *II = + T->castAs<EnumType>()->getDecl()->getIdentifier(); + if (II && II->isStr("__hot_cold_t")) + Consume(); + } + return Params == FPT->getNumParams(); } @@ -3157,7 +3406,24 @@ bool FunctionDecl::isInlineBuiltinDeclaration() const { return false; const FunctionDecl *Definition; - return hasBody(Definition) && Definition->isInlineSpecified(); + if (!hasBody(Definition)) + return false; + + if (!Definition->isInlineSpecified() || + !Definition->hasAttr<AlwaysInlineAttr>()) + return false; + + ASTContext &Context = getASTContext(); + switch (Context.GetGVALinkageForFunction(Definition)) { + case GVA_Internal: + case GVA_DiscardableODR: + case GVA_StrongODR: + return false; + case GVA_AvailableExternally: + case GVA_StrongExternal: + return true; + } + llvm_unreachable("Unknown GVALinkage"); } bool FunctionDecl::isDestroyingOperatorDelete() const { @@ -3205,7 +3471,6 @@ bool FunctionDecl::isGlobal() const { if (const auto *Namespace = cast<NamespaceDecl>(DC)) { if (!Namespace->getDeclName()) return false; - break; } } @@ -3223,14 +3488,39 @@ bool FunctionDecl::isNoReturn() const { return false; } +bool FunctionDecl::isMemberLikeConstrainedFriend() const { + // C++20 [temp.friend]p9: + // A non-template friend declaration with a requires-clause [or] + // a friend function template with a constraint that depends on a template + // parameter from an enclosing template [...] does not declare the same + // function or function template as a declaration in any other scope. + + // If this isn't a friend then it's not a member-like constrained friend. + if (!getFriendObjectKind()) { + return false; + } + + if (!getDescribedFunctionTemplate()) { + // If these friends don't have constraints, they aren't constrained, and + // thus don't fall under temp.friend p9. Else the simple presence of a + // constraint makes them unique. + return getTrailingRequiresClause(); + } + + return FriendConstraintRefersToEnclosingTemplate(); +} MultiVersionKind FunctionDecl::getMultiVersionKind() const { if (hasAttr<TargetAttr>()) return MultiVersionKind::Target; + if (hasAttr<TargetVersionAttr>()) + return MultiVersionKind::TargetVersion; if (hasAttr<CPUDispatchAttr>()) return MultiVersionKind::CPUDispatch; if (hasAttr<CPUSpecificAttr>()) return MultiVersionKind::CPUSpecific; + if (hasAttr<TargetClonesAttr>()) + return MultiVersionKind::TargetClones; return MultiVersionKind::None; } @@ -3243,7 +3533,12 @@ bool FunctionDecl::isCPUSpecificMultiVersion() const { } bool FunctionDecl::isTargetMultiVersion() const { - return isMultiVersion() && hasAttr<TargetAttr>(); + return isMultiVersion() && + (hasAttr<TargetAttr>() || hasAttr<TargetVersionAttr>()); +} + +bool FunctionDecl::isTargetClonesMultiVersion() const { + return isMultiVersion() && hasAttr<TargetClonesAttr>(); } void @@ -3296,7 +3591,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; @@ -3325,7 +3620,7 @@ unsigned FunctionDecl::getBuiltinID(bool ConsiderWrapperFunctions) const { // library, none of the predefined library functions except printf and malloc // should be treated as a builtin i.e. 0 should be returned for them. if (Context.getTargetInfo().getTriple().isAMDGCN() && - Context.getLangOpts().OpenMPIsDevice && + Context.getLangOpts().OpenMPIsTargetDevice && Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID) && !(BuiltinID == Builtin::BIprintf || BuiltinID == Builtin::BImalloc)) return 0; @@ -3375,11 +3670,25 @@ unsigned FunctionDecl::getMinRequiredArguments() const { return NumRequiredArgs; } +bool FunctionDecl::hasCXXExplicitFunctionObjectParameter() const { + return getNumParams() != 0 && getParamDecl(0)->isExplicitObjectParameter(); +} + +unsigned FunctionDecl::getNumNonObjectParams() const { + return getNumParams() - + static_cast<unsigned>(hasCXXExplicitFunctionObjectParameter()); +} + +unsigned FunctionDecl::getMinRequiredExplicitArguments() const { + return getMinRequiredArguments() - + static_cast<unsigned>(hasCXXExplicitFunctionObjectParameter()); +} + bool FunctionDecl::hasOneParamOrDefaultArgs() const { return getNumParams() == 1 || (getNumParams() > 1 && - std::all_of(param_begin() + 1, param_end(), - [](ParmVarDecl *P) { return P->hasDefaultArg(); })); + llvm::all_of(llvm::drop_begin(parameters()), + [](ParmVarDecl *P) { return P->hasDefaultArg(); })); } /// The combination of the extern and inline keywords under MSVC forces @@ -3441,7 +3750,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; @@ -3578,7 +3887,7 @@ bool FunctionDecl::isInlineDefinitionExternallyVisible() const { // If any declaration is 'inline' but not 'extern', then this definition // is externally visible. - for (auto Redecl : redecls()) { + for (auto *Redecl : redecls()) { if (Redecl->isInlineSpecified() && Redecl->getStorageClass() != SC_Extern) return true; @@ -3595,7 +3904,7 @@ bool FunctionDecl::isInlineDefinitionExternallyVisible() const { // [...] If all of the file scope declarations for a function in a // translation unit include the inline function specifier without extern, // then the definition in that translation unit is an inline definition. - for (auto Redecl : redecls()) { + for (auto *Redecl : redecls()) { if (RedeclForcesDefC99(Redecl)) return true; } @@ -3626,8 +3935,13 @@ const IdentifierInfo *FunctionDecl::getLiteralIdentifier() const { FunctionDecl::TemplatedKind FunctionDecl::getTemplatedKind() const { if (TemplateOrSpecialization.isNull()) return TK_NonTemplate; - if (TemplateOrSpecialization.is<FunctionTemplateDecl *>()) + if (const auto *ND = TemplateOrSpecialization.dyn_cast<NamedDecl *>()) { + if (isa<FunctionDecl>(ND)) + return TK_DependentNonTemplate; + assert(isa<FunctionTemplateDecl>(ND) && + "No other valid types in NamedDecl"); return TK_FunctionTemplate; + } if (TemplateOrSpecialization.is<MemberSpecializationInfo *>()) return TK_MemberSpecialization; if (TemplateOrSpecialization.is<FunctionTemplateSpecializationInfo *>()) @@ -3668,15 +3982,34 @@ FunctionDecl::setInstantiationOfMemberFunction(ASTContext &C, } FunctionTemplateDecl *FunctionDecl::getDescribedFunctionTemplate() const { - return TemplateOrSpecialization.dyn_cast<FunctionTemplateDecl *>(); + return dyn_cast_if_present<FunctionTemplateDecl>( + TemplateOrSpecialization.dyn_cast<NamedDecl *>()); } -void FunctionDecl::setDescribedFunctionTemplate(FunctionTemplateDecl *Template) { +void FunctionDecl::setDescribedFunctionTemplate( + FunctionTemplateDecl *Template) { assert(TemplateOrSpecialization.isNull() && "Member function is already a specialization"); TemplateOrSpecialization = Template; } +bool FunctionDecl::isFunctionTemplateSpecialization() const { + return TemplateOrSpecialization.is<FunctionTemplateSpecializationInfo *>() || + TemplateOrSpecialization + .is<DependentFunctionTemplateSpecializationInfo *>(); +} + +void FunctionDecl::setInstantiatedFromDecl(FunctionDecl *FD) { + assert(TemplateOrSpecialization.isNull() && + "Function is already a specialization"); + TemplateOrSpecialization = FD; +} + +FunctionDecl *FunctionDecl::getInstantiatedFromDecl() const { + return dyn_cast_if_present<FunctionDecl>( + TemplateOrSpecialization.dyn_cast<NamedDecl *>()); +} + bool FunctionDecl::isImplicitlyInstantiable() const { // If the function is invalid, it can't be implicitly instantiated. if (isInvalidDecl()) @@ -3800,6 +4133,11 @@ FunctionDecl::getTemplateSpecializationArgsAsWritten() const { .dyn_cast<FunctionTemplateSpecializationInfo*>()) { return Info->TemplateArgumentsAsWritten; } + if (DependentFunctionTemplateSpecializationInfo *Info = + TemplateOrSpecialization + .dyn_cast<DependentFunctionTemplateSpecializationInfo *>()) { + return Info->TemplateArgumentsAsWritten; + } return nullptr; } @@ -3817,6 +4155,7 @@ FunctionDecl::setFunctionTemplateSpecialization(ASTContext &C, assert(TSK != TSK_Undeclared && "Must specify the type of function template specialization"); assert((TemplateOrSpecialization.isNull() || + getFriendObjectKind() != FOK_None || TSK == TSK_ExplicitSpecialization) && "Member specialization must be an explicit specialization"); FunctionTemplateSpecializationInfo *Info = @@ -3828,10 +4167,9 @@ FunctionDecl::setFunctionTemplateSpecialization(ASTContext &C, Template->addSpecialization(Info, InsertPos); } -void -FunctionDecl::setDependentTemplateSpecialization(ASTContext &Context, - const UnresolvedSetImpl &Templates, - const TemplateArgumentListInfo &TemplateArgs) { +void FunctionDecl::setDependentTemplateSpecialization( + ASTContext &Context, const UnresolvedSetImpl &Templates, + const TemplateArgumentListInfo *TemplateArgs) { assert(TemplateOrSpecialization.isNull()); DependentFunctionTemplateSpecializationInfo *Info = DependentFunctionTemplateSpecializationInfo::Create(Context, Templates, @@ -3847,28 +4185,26 @@ FunctionDecl::getDependentSpecializationInfo() const { DependentFunctionTemplateSpecializationInfo * DependentFunctionTemplateSpecializationInfo::Create( - ASTContext &Context, const UnresolvedSetImpl &Ts, - const TemplateArgumentListInfo &TArgs) { - void *Buffer = Context.Allocate( - totalSizeToAlloc<TemplateArgumentLoc, FunctionTemplateDecl *>( - TArgs.size(), Ts.size())); - return new (Buffer) DependentFunctionTemplateSpecializationInfo(Ts, TArgs); + ASTContext &Context, const UnresolvedSetImpl &Candidates, + const TemplateArgumentListInfo *TArgs) { + const auto *TArgsWritten = + TArgs ? ASTTemplateArgumentListInfo::Create(Context, *TArgs) : nullptr; + return new (Context.Allocate( + totalSizeToAlloc<FunctionTemplateDecl *>(Candidates.size()))) + DependentFunctionTemplateSpecializationInfo(Candidates, TArgsWritten); } DependentFunctionTemplateSpecializationInfo:: -DependentFunctionTemplateSpecializationInfo(const UnresolvedSetImpl &Ts, - const TemplateArgumentListInfo &TArgs) - : AngleLocs(TArgs.getLAngleLoc(), TArgs.getRAngleLoc()) { - NumTemplates = Ts.size(); - NumArgs = TArgs.size(); - - FunctionTemplateDecl **TsArray = getTrailingObjects<FunctionTemplateDecl *>(); - for (unsigned I = 0, E = Ts.size(); I != E; ++I) - TsArray[I] = cast<FunctionTemplateDecl>(Ts[I]->getUnderlyingDecl()); - - TemplateArgumentLoc *ArgsArray = getTrailingObjects<TemplateArgumentLoc>(); - for (unsigned I = 0, E = TArgs.size(); I != E; ++I) - new (&ArgsArray[I]) TemplateArgumentLoc(TArgs[I]); + DependentFunctionTemplateSpecializationInfo( + const UnresolvedSetImpl &Candidates, + const ASTTemplateArgumentListInfo *TemplateArgsWritten) + : NumCandidates(Candidates.size()), + TemplateArgumentsAsWritten(TemplateArgsWritten) { + std::transform(Candidates.begin(), Candidates.end(), + getTrailingObjects<FunctionTemplateDecl *>(), + [](NamedDecl *ND) { + return cast<FunctionTemplateDecl>(ND->getUnderlyingDecl()); + }); } TemplateSpecializationKind FunctionDecl::getTemplateSpecializationKind() const { @@ -3883,6 +4219,13 @@ TemplateSpecializationKind FunctionDecl::getTemplateSpecializationKind() const { TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo *>()) return MSInfo->getTemplateSpecializationKind(); + // A dependent function template specialization is an explicit specialization, + // except when it's a friend declaration. + if (TemplateOrSpecialization + .is<DependentFunctionTemplateSpecializationInfo *>() && + getFriendObjectKind() == FOK_None) + return TSK_ExplicitSpecialization; + return TSK_Undeclared; } @@ -3897,6 +4240,11 @@ FunctionDecl::getTemplateSpecializationKindForInstantiation() const { // template<> void f<int>() {} // }; // + // Within the templated CXXRecordDecl, A<T>::f<int> is a dependent function + // template specialization; both getTemplateSpecializationKind() and + // getTemplateSpecializationKindForInstantiation() will return + // TSK_ExplicitSpecialization. + // // For A<int>::f<int>(): // * getTemplateSpecializationKind() will return TSK_ExplicitSpecialization // * getTemplateSpecializationKindForInstantiation() will return @@ -3917,6 +4265,11 @@ FunctionDecl::getTemplateSpecializationKindForInstantiation() const { TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo *>()) return MSInfo->getTemplateSpecializationKind(); + if (TemplateOrSpecialization + .is<DependentFunctionTemplateSpecializationInfo *>() && + getFriendObjectKind() == FOK_None) + return TSK_ExplicitSpecialization; + return TSK_Undeclared; } @@ -4061,6 +4414,10 @@ unsigned FunctionDecl::getMemoryFunctionKind() const { case Builtin::BIbzero: return Builtin::BIbzero; + case Builtin::BI__builtin_bcopy: + case Builtin::BIbcopy: + return Builtin::BIbcopy; + case Builtin::BIfree: return Builtin::BIfree; @@ -4092,6 +4449,8 @@ unsigned FunctionDecl::getMemoryFunctionKind() const { return Builtin::BIstrlen; if (FnInfo->isStr("bzero")) return Builtin::BIbzero; + if (FnInfo->isStr("bcopy")) + return Builtin::BIbcopy; } else if (isInStdNamespace()) { if (FnInfo->isStr("free")) return Builtin::BIfree; @@ -4117,7 +4476,7 @@ unsigned FunctionDecl::getODRHash() { } class ODRHash Hash; - Hash.AddFunctionDecl(this); + Hash.AddFunctionDecl(this, /*SkipBody=*/shouldSkipCheckingODR()); setHasODRHash(true); ODRHash = Hash.CalculateHash(); return ODRHash; @@ -4152,6 +4511,28 @@ bool FieldDecl::isAnonymousStructOrUnion() const { return false; } +Expr *FieldDecl::getInClassInitializer() const { + if (!hasInClassInitializer()) + return nullptr; + + LazyDeclStmtPtr InitPtr = BitField ? InitAndBitWidth->Init : Init; + return cast_if_present<Expr>( + InitPtr.isOffset() ? InitPtr.get(getASTContext().getExternalSource()) + : InitPtr.get(nullptr)); +} + +void FieldDecl::setInClassInitializer(Expr *NewInit) { + setLazyInClassInitializer(LazyDeclStmtPtr(NewInit)); +} + +void FieldDecl::setLazyInClassInitializer(LazyDeclStmtPtr NewInit) { + assert(hasInClassInitializer() && !getInClassInitializer()); + if (BitField) + InitAndBitWidth->Init = NewInit; + else + Init = NewInit; +} + unsigned FieldDecl::getBitWidthValue(const ASTContext &Ctx) const { assert(isBitField() && "not a bitfield"); return getBitWidth()->EvaluateKnownConstInt(Ctx).getZExtValue(); @@ -4190,9 +4571,18 @@ bool FieldDecl::isZeroSize(const ASTContext &Ctx) const { // Otherwise, [...] the circumstances under which the object has zero size // are implementation-defined. - // FIXME: This might be Itanium ABI specific; we don't yet know what the MS - // ABI will do. - return true; + if (!Ctx.getTargetInfo().getCXXABI().isMicrosoft()) + return true; + + // MS ABI: has nonzero size if it is a class type with class type fields, + // whether or not they have nonzero size + return !llvm::any_of(CXXRD->fields(), [](const FieldDecl *Field) { + return Field->getType()->getAs<RecordType>(); + }); +} + +bool FieldDecl::isPotentiallyOverlapping() const { + return hasAttr<NoUniqueAddressAttr>() && getType()->getAsCXXRecordDecl(); } unsigned FieldDecl::getFieldIndex() const { @@ -4208,6 +4598,8 @@ unsigned FieldDecl::getFieldIndex() const { for (auto *Field : RD->fields()) { Field->getCanonicalDecl()->CachedFieldIndex = Index + 1; + assert(Field->getCanonicalDecl()->CachedFieldIndex == Index + 1 && + "overflow in field numbering"); ++Index; } @@ -4227,11 +4619,21 @@ SourceRange FieldDecl::getSourceRange() const { void FieldDecl::setCapturedVLAType(const VariableArrayType *VLAType) { assert((getParent()->isLambda() || getParent()->isCapturedRecord()) && "capturing type in non-lambda or captured record."); - assert(InitStorage.getInt() == ISK_NoInit && - InitStorage.getPointer() == nullptr && - "bit width, initializer or captured type already set"); - InitStorage.setPointerAndInt(const_cast<VariableArrayType *>(VLAType), - ISK_CapturedVLAType); + assert(StorageKind == ISK_NoInit && !BitField && + "bit-field or field with default member initializer cannot capture " + "VLA type"); + StorageKind = ISK_CapturedVLAType; + CapturedVLAType = VLAType; +} + +void FieldDecl::printName(raw_ostream &OS, const PrintingPolicy &Policy) const { + // Print unnamed members using name of their type. + if (isAnonymousStructOrUnion()) { + this->getType().print(OS, Policy); + return; + } + // Otherwise, do the normal printing. + DeclaratorDecl::printName(OS, Policy); } //===----------------------------------------------------------------------===// @@ -4243,8 +4645,8 @@ TagDecl::TagDecl(Kind DK, TagKind TK, const ASTContext &C, DeclContext *DC, SourceLocation StartL) : TypeDecl(DK, DC, L, Id, StartL), DeclContext(DK), redeclarable_base(C), TypedefNameDeclOrQualifier((TypedefNameDecl *)nullptr) { - assert((DK != Enum || TK == TTK_Enum) && - "EnumDecl not matched with TTK_Enum"); + assert((DK != Enum || TK == TagTypeKind::Enum) && + "EnumDecl not matched with TagTypeKind::Enum"); setPreviousDecl(PrevDecl); setTagKind(TK); setCompleteDefinition(false); @@ -4252,6 +4654,7 @@ TagDecl::TagDecl(Kind DK, TagKind TK, const ASTContext &C, DeclContext *DC, setEmbeddedInDeclarator(false); setFreeStanding(false); setCompleteDefinitionRequired(false); + TagDeclBits.IsThisDeclarationADemotedDefinition = false; } SourceLocation TagDecl::getOuterLocStart() const { @@ -4281,7 +4684,7 @@ void TagDecl::startDefinition() { if (auto *D = dyn_cast<CXXRecordDecl>(this)) { struct CXXRecordDecl::DefinitionData *Data = new (getASTContext()) struct CXXRecordDecl::DefinitionData(D); - for (auto I : redecls()) + for (auto *I : redecls()) cast<CXXRecordDecl>(I)->DefinitionData = Data; } } @@ -4314,7 +4717,7 @@ TagDecl *TagDecl::getDefinition() const { if (const auto *CXXRD = dyn_cast<CXXRecordDecl>(this)) return CXXRD->getDefinition(); - for (auto R : redecls()) + for (auto *R : redecls()) if (R->isCompleteDefinition()) return R; @@ -4341,6 +4744,23 @@ void TagDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) { } } +void TagDecl::printName(raw_ostream &OS, const PrintingPolicy &Policy) const { + DeclarationName Name = getDeclName(); + // If the name is supposed to have an identifier but does not have one, then + // the tag is anonymous and we should print it differently. + if (Name.isIdentifier() && !Name.getAsIdentifierInfo()) { + // If the caller wanted to print a qualified name, they've already printed + // the scope. And if the caller doesn't want that, the scope information + // is already printed as part of the type. + PrintingPolicy Copy(Policy); + Copy.SuppressScope = true; + getASTContext().getTagDeclType(this).print(OS, Copy); + return; + } + // Otherwise, do the normal printing. + Name.print(OS, Policy); +} + void TagDecl::setTemplateParameterListsInfo( ASTContext &Context, ArrayRef<TemplateParameterList *> TPLists) { assert(!TPLists.empty()); @@ -4359,7 +4779,7 @@ void TagDecl::setTemplateParameterListsInfo( EnumDecl::EnumDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, EnumDecl *PrevDecl, bool Scoped, bool ScopedUsingClassTag, bool Fixed) - : TagDecl(Enum, TTK_Enum, C, DC, IdLoc, Id, PrevDecl, StartLoc) { + : TagDecl(Enum, TagTypeKind::Enum, C, DC, IdLoc, Id, PrevDecl, StartLoc) { assert(Scoped || !ScopedUsingClassTag); IntegerType = nullptr; setNumPositiveBits(0); @@ -4483,6 +4903,32 @@ unsigned EnumDecl::getODRHash() { return ODRHash; } +SourceRange EnumDecl::getSourceRange() const { + auto Res = TagDecl::getSourceRange(); + // Set end-point to enum-base, e.g. enum foo : ^bar + if (auto *TSI = getIntegerTypeSourceInfo()) { + // TagDecl doesn't know about the enum base. + if (!getBraceRange().getEnd().isValid()) + Res.setEnd(TSI->getTypeLoc().getEndLoc()); + } + return Res; +} + +void EnumDecl::getValueRange(llvm::APInt &Max, llvm::APInt &Min) const { + unsigned Bitwidth = getASTContext().getIntWidth(getIntegerType()); + unsigned NumNegativeBits = getNumNegativeBits(); + unsigned NumPositiveBits = getNumPositiveBits(); + + if (NumNegativeBits) { + unsigned NumBits = std::max(NumNegativeBits, NumPositiveBits + 1); + Max = llvm::APInt(Bitwidth, 1) << (NumBits - 1); + Min = -Max; + } else { + Max = llvm::APInt(Bitwidth, 1) << NumPositiveBits; + Min = llvm::APInt::getZero(Bitwidth); + } +} + //===----------------------------------------------------------------------===// // RecordDecl Implementation //===----------------------------------------------------------------------===// @@ -4505,7 +4951,9 @@ RecordDecl::RecordDecl(Kind DK, TagKind TK, const ASTContext &C, setHasNonTrivialToPrimitiveDestructCUnion(false); setHasNonTrivialToPrimitiveCopyCUnion(false); setParamDestroyedInCallee(false); - setArgPassingRestrictions(APK_CanPassInRegs); + setArgPassingRestrictions(RecordArgPassingKind::CanPassInRegs); + setIsRandomized(false); + setODRHash(0); } RecordDecl *RecordDecl::Create(const ASTContext &C, TagKind TK, DeclContext *DC, @@ -4520,9 +4968,9 @@ RecordDecl *RecordDecl::Create(const ASTContext &C, TagKind TK, DeclContext *DC, } RecordDecl *RecordDecl::CreateDeserialized(const ASTContext &C, unsigned ID) { - RecordDecl *R = - new (C, ID) RecordDecl(Record, TTK_Struct, C, nullptr, SourceLocation(), - SourceLocation(), nullptr, nullptr); + RecordDecl *R = new (C, ID) + RecordDecl(Record, TagTypeKind::Struct, C, nullptr, SourceLocation(), + SourceLocation(), nullptr, nullptr); R->setMayHaveOutOfDateDef(C.getLangOpts().Modules); return R; } @@ -4564,7 +5012,10 @@ bool RecordDecl::isOrContainsUnion() const { RecordDecl::field_iterator RecordDecl::field_begin() const { if (hasExternalLexicalStorage() && !hasLoadedFieldsFromExternalStorage()) LoadFieldsFromExternalStorage(); - + // This is necessary for correctness for C++ with modules. + // FIXME: Come up with a test case that breaks without definition. + if (RecordDecl *D = getDefinition(); D && D != this) + return D->field_begin(); return field_iterator(decl_iterator(FirstDecl)); } @@ -4589,6 +5040,12 @@ bool RecordDecl::isMsStruct(const ASTContext &C) const { return hasAttr<MSStructAttr>() || C.getLangOpts().MSBitfields == 1; } +void RecordDecl::reorderDecls(const SmallVectorImpl<Decl *> &Decls) { + std::tie(FirstDecl, LastDecl) = DeclContext::BuildDeclChain(Decls, false); + LastDecl->NextInContextAndBits.setPointer(nullptr); + setIsRandomized(true); +} + void RecordDecl::LoadFieldsFromExternalStorage() const { ExternalASTSource *Source = getASTContext().getExternalSource(); assert(hasExternalLexicalStorage() && Source && "No external storage?"); @@ -4611,8 +5068,13 @@ void RecordDecl::LoadFieldsFromExternalStorage() const { if (Decls.empty()) return; - std::tie(FirstDecl, LastDecl) = BuildDeclChain(Decls, - /*FieldsAlreadyLoaded=*/false); + auto [ExternalFirst, ExternalLast] = + BuildDeclChain(Decls, + /*FieldsAlreadyLoaded=*/false); + ExternalLast->NextInContextAndBits.setPointer(FirstDecl); + FirstDecl = ExternalFirst; + if (!LastDecl) + LastDecl = ExternalLast; } bool RecordDecl::mayInsertExtraPadding(bool EmitRemark) const { @@ -4674,6 +5136,19 @@ const FieldDecl *RecordDecl::findFirstNamedDataMember() const { return nullptr; } +unsigned RecordDecl::getODRHash() { + if (hasODRHash()) + return RecordDeclBits.ODRHash; + + // Only calculate hash on first call of getODRHash per record. + ODRHash Hash; + Hash.AddRecordDecl(this); + // For RecordDecl the ODRHash is stored in the remaining 26 + // bit of RecordDeclBits, adjust the hash to accomodate. + setODRHash(Hash.CalculateHash() >> 6); + return RecordDeclBits.ODRHash; +} + //===----------------------------------------------------------------------===// // BlockDecl Implementation //===----------------------------------------------------------------------===// @@ -4823,6 +5298,12 @@ bool ValueDecl::isWeak() const { MostRecent->hasAttr<WeakRefAttr>() || isWeakImported(); } +bool ValueDecl::isInitCapture() const { + if (auto *Var = llvm::dyn_cast<VarDecl>(this)) + return Var->isInitCapture(); + return false; +} + void ImplicitParamDecl::anchor() {} ImplicitParamDecl *ImplicitParamDecl::Create(ASTContext &C, DeclContext *DC, @@ -4842,18 +5323,16 @@ ImplicitParamDecl *ImplicitParamDecl::CreateDeserialized(ASTContext &C, return new (C, ID) ImplicitParamDecl(C, QualType(), ImplicitParamKind::Other); } -FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC, - SourceLocation StartLoc, - const DeclarationNameInfo &NameInfo, - QualType T, TypeSourceInfo *TInfo, - StorageClass SC, bool isInlineSpecified, - bool hasWrittenPrototype, - ConstexprSpecKind ConstexprKind, - Expr *TrailingRequiresClause) { - FunctionDecl *New = - new (C, DC) FunctionDecl(Function, C, DC, StartLoc, NameInfo, T, TInfo, - SC, isInlineSpecified, ConstexprKind, - TrailingRequiresClause); +FunctionDecl * +FunctionDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, + const DeclarationNameInfo &NameInfo, QualType T, + TypeSourceInfo *TInfo, StorageClass SC, bool UsesFPIntrin, + bool isInlineSpecified, bool hasWrittenPrototype, + ConstexprSpecKind ConstexprKind, + Expr *TrailingRequiresClause) { + FunctionDecl *New = new (C, DC) FunctionDecl( + Function, C, DC, StartLoc, NameInfo, T, TInfo, SC, UsesFPIntrin, + isInlineSpecified, ConstexprKind, TrailingRequiresClause); New->setHasWrittenPrototype(hasWrittenPrototype); return New; } @@ -4861,7 +5340,7 @@ FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC, FunctionDecl *FunctionDecl::CreateDeserialized(ASTContext &C, unsigned ID) { return new (C, ID) FunctionDecl( Function, C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(), - nullptr, SC_None, false, ConstexprSpecKind::Unspecified, nullptr); + nullptr, SC_None, false, false, ConstexprSpecKind::Unspecified, nullptr); } BlockDecl *BlockDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L) { @@ -4894,16 +5373,23 @@ void CapturedDecl::setBody(Stmt *B) { BodyAndNothrow.setPointer(B); } bool CapturedDecl::isNothrow() const { return BodyAndNothrow.getInt(); } void CapturedDecl::setNothrow(bool Nothrow) { BodyAndNothrow.setInt(Nothrow); } +EnumConstantDecl::EnumConstantDecl(const ASTContext &C, DeclContext *DC, + SourceLocation L, IdentifierInfo *Id, + QualType T, Expr *E, const llvm::APSInt &V) + : ValueDecl(EnumConstant, DC, L, Id, T), Init((Stmt *)E) { + setInitVal(C, V); +} + EnumConstantDecl *EnumConstantDecl::Create(ASTContext &C, EnumDecl *CD, SourceLocation L, IdentifierInfo *Id, QualType T, Expr *E, const llvm::APSInt &V) { - return new (C, CD) EnumConstantDecl(CD, L, Id, T, E, V); + return new (C, CD) EnumConstantDecl(C, CD, L, Id, T, E, V); } EnumConstantDecl * EnumConstantDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - return new (C, ID) EnumConstantDecl(nullptr, SourceLocation(), nullptr, + return new (C, ID) EnumConstantDecl(C, nullptr, SourceLocation(), nullptr, QualType(), nullptr, llvm::APSInt()); } @@ -4930,8 +5416,9 @@ IndirectFieldDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, IndirectFieldDecl *IndirectFieldDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - return new (C, ID) IndirectFieldDecl(C, nullptr, SourceLocation(), - DeclarationName(), QualType(), None); + return new (C, ID) + IndirectFieldDecl(C, nullptr, SourceLocation(), DeclarationName(), + QualType(), std::nullopt); } SourceRange EnumConstantDecl::getSourceRange() const { @@ -5036,6 +5523,29 @@ FileScopeAsmDecl *FileScopeAsmDecl::CreateDeserialized(ASTContext &C, SourceLocation()); } +void TopLevelStmtDecl::anchor() {} + +TopLevelStmtDecl *TopLevelStmtDecl::Create(ASTContext &C, Stmt *Statement) { + assert(Statement); + assert(C.getLangOpts().IncrementalExtensions && + "Must be used only in incremental mode"); + + SourceLocation BeginLoc = Statement->getBeginLoc(); + DeclContext *DC = C.getTranslationUnitDecl(); + + return new (C, DC) TopLevelStmtDecl(DC, BeginLoc, Statement); +} + +TopLevelStmtDecl *TopLevelStmtDecl::CreateDeserialized(ASTContext &C, + unsigned ID) { + return new (C, ID) + TopLevelStmtDecl(/*DC=*/nullptr, SourceLocation(), /*S=*/nullptr); +} + +SourceRange TopLevelStmtDecl::getSourceRange() const { + return SourceRange(getLocation(), Statement->getEndLoc()); +} + void EmptyDecl::anchor() {} EmptyDecl *EmptyDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L) { @@ -5046,6 +5556,40 @@ EmptyDecl *EmptyDecl::CreateDeserialized(ASTContext &C, unsigned ID) { return new (C, ID) EmptyDecl(nullptr, SourceLocation()); } +HLSLBufferDecl::HLSLBufferDecl(DeclContext *DC, bool CBuffer, + SourceLocation KwLoc, IdentifierInfo *ID, + SourceLocation IDLoc, SourceLocation LBrace) + : NamedDecl(Decl::Kind::HLSLBuffer, DC, IDLoc, DeclarationName(ID)), + DeclContext(Decl::Kind::HLSLBuffer), LBraceLoc(LBrace), KwLoc(KwLoc), + IsCBuffer(CBuffer) {} + +HLSLBufferDecl *HLSLBufferDecl::Create(ASTContext &C, + DeclContext *LexicalParent, bool CBuffer, + SourceLocation KwLoc, IdentifierInfo *ID, + SourceLocation IDLoc, + SourceLocation LBrace) { + // For hlsl like this + // cbuffer A { + // cbuffer B { + // } + // } + // compiler should treat it as + // cbuffer A { + // } + // cbuffer B { + // } + // FIXME: support nested buffers if required for back-compat. + DeclContext *DC = LexicalParent; + HLSLBufferDecl *Result = + new (C, DC) HLSLBufferDecl(DC, CBuffer, KwLoc, ID, IDLoc, LBrace); + return Result; +} + +HLSLBufferDecl *HLSLBufferDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + return new (C, ID) HLSLBufferDecl(nullptr, false, SourceLocation(), nullptr, + SourceLocation(), SourceLocation()); +} + //===----------------------------------------------------------------------===// // ImportDecl Implementation //===----------------------------------------------------------------------===// @@ -5105,11 +5649,11 @@ ImportDecl *ImportDecl::CreateDeserialized(ASTContext &C, unsigned ID, ArrayRef<SourceLocation> ImportDecl::getIdentifierLocs() const { if (!isImportComplete()) - return None; + return std::nullopt; const auto *StoredLocs = getTrailingObjects<SourceLocation>(); - return llvm::makeArrayRef(StoredLocs, - getNumModuleIdentifiers(getImportedModule())); + return llvm::ArrayRef(StoredLocs, + getNumModuleIdentifiers(getImportedModule())); } SourceRange ImportDecl::getSourceRange() const { |