aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang/lib/AST/Decl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/clang/lib/AST/Decl.cpp')
-rw-r--r--contrib/llvm-project/clang/lib/AST/Decl.cpp1048
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 {