#include "clang/AST/Decl.h"
#include "Linkage.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTDiagnostic.h"
#include "clang/AST/ASTLambda.h"
#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/Attr.h"
#include "clang/AST/CanonicalType.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclOpenMP.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExternalASTSource.h"
#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"
#include "clang/AST/Type.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/Linkage.h"
#include "clang/Basic/Module.h"
#include "clang/Basic/NoSanitizeList.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/Sanitizers.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/Specifiers.h"
#include "clang/Basic/TargetCXXABI.h"
#include "clang/Basic/TargetInfo.h"
#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 <algorithm>
#include <cassert>
#include <cstddef>
#include <cstring>
#include <memory>
#include <string>
#include <tuple>
#include <type_traits>
using namespace clang;
Decl *clang::getPrimaryMergedDecl(Decl *D) {
return D->getASTContext().getPrimaryMergedDecl(D);
}
void PrettyDeclStackTraceEntry::print(raw_ostream &OS) const {
SourceLocation Loc = this->Loc;
if (!Loc.isValid() && TheDecl) Loc = TheDecl->getLocation();
if (Loc.isValid()) {
Loc.print(OS, Context.getSourceManager());
OS << ": ";
}
OS << Message;
if (auto *ND = dyn_cast_or_null<NamedDecl>(TheDecl)) {
OS << " '";
ND->getNameForDiagnostic(OS, Context.getPrintingPolicy(), true);
OS << "'";
}
OS << '\n';
}
bool Decl::isOutOfLine() const {
return !getLexicalDeclContext()->Equals(getDeclContext());
}
TranslationUnitDecl::TranslationUnitDecl(ASTContext &ctx)
: Decl(TranslationUnit, nullptr, SourceLocation()),
DeclContext(TranslationUnit), redeclarable_base(ctx), Ctx(ctx) {}
static bool hasExplicitVisibilityAlready(LVComputationKind computation) {
return computation.IgnoreExplicitVisibility;
}
static LVComputationKind
withExplicitVisibilityAlready(LVComputationKind Kind) {
Kind.IgnoreExplicitVisibility = true;
return Kind;
}
static 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());
}
static bool usesTypeVisibility(const NamedDecl *D) {
return isa<TypeDecl>(D) ||
isa<ClassTemplateDecl>(D) ||
isa<ObjCInterfaceDecl>(D);
}
template <class T> static typename
std::enable_if<!std::is_base_of<RedeclarableTemplateDecl, T>::value, bool>::type
isExplicitMemberSpecialization(const T *D) {
if (const MemberSpecializationInfo *member =
D->getMemberSpecializationInfo()) {
return member->isExplicitSpecialization();
}
return false;
}
static bool isExplicitMemberSpecialization(const RedeclarableTemplateDecl *D) {
return D->isMemberSpecialization();
}
template <class T>
static Visibility getVisibilityFromAttr(const T *attr) {
switch (attr->getVisibility()) {
case T::Default:
return DefaultVisibility;
case T::Hidden:
return HiddenVisibility;
case T::Protected:
return ProtectedVisibility;
}
llvm_unreachable("bad visibility kind");
}
static Optional<Visibility> getVisibilityOf(const NamedDecl *D,
NamedDecl::ExplicitVisibilityKind kind) {
if (kind == NamedDecl::VisibilityForType) {
if (const auto *A = D->getAttr<TypeVisibilityAttr>()) {
return getVisibilityFromAttr(A);
}
}
if (const auto *A = D->getAttr<VisibilityAttr>()) {
return getVisibilityFromAttr(A);
}
return None;
}
LinkageInfo LinkageComputer::getLVForType(const Type &T,
LVComputationKind computation) {
if (computation.IgnoreAllVisibility)
return LinkageInfo(T.getLinkage(), DefaultVisibility, true);
return getTypeLinkageAndVisibility(&T);
}
LinkageInfo LinkageComputer::getLVForTemplateParameterList(
const TemplateParameterList *Params, LVComputationKind computation) {
LinkageInfo LV;
for (const NamedDecl *P : *Params) {
if (isa<TemplateTypeParmDecl>(P))
continue;
if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P)) {
if (!NTTP->isExpandedParameterPack()) {
if (!NTTP->getType()->isDependentType()) {
LV.merge(getLVForType(*NTTP->getType(), computation));
}
continue;
}
for (unsigned i = 0, n = NTTP->getNumExpansionTypes(); i != n; ++i) {
QualType type = NTTP->getExpansionType(i);
if (!type->isDependentType())
LV.merge(getTypeLinkageAndVisibility(type));
}
continue;
}
const auto *TTP = cast<TemplateTemplateParmDecl>(P);
if (!TTP->isExpandedParameterPack()) {
LV.merge(getLVForTemplateParameterList(TTP->getTemplateParameters(),
computation));
continue;
}
for (unsigned i = 0, n = TTP->getNumExpansionTemplateParameters();
i != n; ++i) {
LV.merge(getLVForTemplateParameterList(
TTP->getExpansionTemplateParameters(i), computation));
}
}
return LV;
}
static const Decl *getOutermostFuncOrBlockContext(const Decl *D) {
const Decl *Ret = nullptr;
const DeclContext *DC = D->getDeclContext();
while (DC->getDeclKind() != Decl::TranslationUnit) {
if (isa<FunctionDecl>(DC) || isa<BlockDecl>(DC))
Ret = cast<Decl>(DC);
DC = DC->getParent();
}
return Ret;
}
LinkageInfo
LinkageComputer::getLVForTemplateArgumentList(ArrayRef<TemplateArgument> Args,
LVComputationKind computation) {
LinkageInfo LV;
for (const TemplateArgument &Arg : Args) {
switch (Arg.getKind()) {
case TemplateArgument::Null:
case TemplateArgument::Integral:
case TemplateArgument::Expression:
continue;
case TemplateArgument::Type:
LV.merge(getLVForType(*Arg.getAsType(), computation));
continue;
case TemplateArgument::Declaration: {
const NamedDecl *ND = Arg.getAsDecl();
assert(!usesTypeVisibility(ND));
LV.merge(getLVForDecl(ND, computation));
continue;
}
case TemplateArgument::NullPtr:
LV.merge(getTypeLinkageAndVisibility(Arg.getNullPtrType()));
continue;
case TemplateArgument::Template:
case TemplateArgument::TemplateExpansion:
if (TemplateDecl *Template =
Arg.getAsTemplateOrTemplatePattern().getAsTemplateDecl())
LV.merge(getLVForDecl(Template, computation));
continue;
case TemplateArgument::Pack:
LV.merge(getLVForTemplateArgumentList(Arg.getPackAsArray(), computation));
continue;
}
llvm_unreachable("bad template argument kind");
}
return LV;
}
LinkageInfo
LinkageComputer::getLVForTemplateArgumentList(const TemplateArgumentList &TArgs,
LVComputationKind computation) {
return getLVForTemplateArgumentList(TArgs.asArray(), computation);
}
static bool shouldConsiderTemplateVisibility(const FunctionDecl *fn,
const FunctionTemplateSpecializationInfo *specInfo) {
if (!specInfo->isExplicitInstantiationOrSpecialization())
return true;
return !fn->hasAttr<VisibilityAttr>();
}
void LinkageComputer::mergeTemplateLV(
LinkageInfo &LV, const FunctionDecl *fn,
const FunctionTemplateSpecializationInfo *specInfo,
LVComputationKind computation) {
bool considerVisibility =
shouldConsiderTemplateVisibility(fn, specInfo);
FunctionTemplateDecl *temp = specInfo->getTemplate();
LinkageInfo tempLV = getLVForDecl(temp, computation);
LV.setLinkage(tempLV.getLinkage());
LinkageInfo paramsLV =
getLVForTemplateParameterList(temp->getTemplateParameters(), computation);
LV.mergeMaybeWithVisibility(paramsLV, considerVisibility);
const TemplateArgumentList &templateArgs = *specInfo->TemplateArguments;
LinkageInfo argsLV = getLVForTemplateArgumentList(templateArgs, computation);
LV.mergeMaybeWithVisibility(argsLV, considerVisibility);
}
static bool hasDirectVisibilityAttribute(const NamedDecl *D,
LVComputationKind computation) {
if (computation.IgnoreAllVisibility)
return false;
return (computation.isTypeVisibility() && D->hasAttr<TypeVisibilityAttr>()) ||
D->hasAttr<VisibilityAttr>();
}
static bool shouldConsiderTemplateVisibility(
const ClassTemplateSpecializationDecl *spec,
LVComputationKind computation) {
if (!spec->isExplicitInstantiationOrSpecialization())
return true;
if (spec->isExplicitSpecialization() &&
hasExplicitVisibilityAlready(computation))
return false;
return !hasDirectVisibilityAttribute(spec, computation);
}
void LinkageComputer::mergeTemplateLV(
LinkageInfo &LV, const ClassTemplateSpecializationDecl *spec,
LVComputationKind computation) {
bool considerVisibility = shouldConsiderTemplateVisibility(spec, computation);
ClassTemplateDecl *temp = spec->getSpecializedTemplate();
LinkageInfo tempLV = getLVForDecl(temp, computation);
LV.setLinkage(tempLV.getLinkage());
LinkageInfo paramsLV =
getLVForTemplateParameterList(temp->getTemplateParameters(), computation);
LV.mergeMaybeWithVisibility(paramsLV,
considerVisibility && !hasExplicitVisibilityAlready(computation));
const TemplateArgumentList &templateArgs = spec->getTemplateArgs();
LinkageInfo argsLV = getLVForTemplateArgumentList(templateArgs, computation);
if (considerVisibility)
LV.mergeVisibility(argsLV);
LV.mergeExternalVisibility(argsLV);
}
static bool shouldConsiderTemplateVisibility(
const VarTemplateSpecializationDecl *spec,
LVComputationKind computation) {
if (!spec->isExplicitInstantiationOrSpecialization())
return true;
if (spec->isExplicitSpecialization() &&
hasExplicitVisibilityAlready(computation))
return false;
return !hasDirectVisibilityAttribute(spec, computation);
}
void LinkageComputer::mergeTemplateLV(LinkageInfo &LV,
const VarTemplateSpecializationDecl *spec,
LVComputationKind computation) {
bool considerVisibility = shouldConsiderTemplateVisibility(spec, computation);
VarTemplateDecl *temp = spec->getSpecializedTemplate();
LinkageInfo tempLV =
getLVForTemplateParameterList(temp->getTemplateParameters(), computation);
LV.mergeMaybeWithVisibility(tempLV,
considerVisibility && !hasExplicitVisibilityAlready(computation));
const TemplateArgumentList &templateArgs = spec->getTemplateArgs();
LinkageInfo argsLV = getLVForTemplateArgumentList(templateArgs, computation);
if (considerVisibility)
LV.mergeVisibility(argsLV);
LV.mergeExternalVisibility(argsLV);
}
static bool useInlineVisibilityHidden(const NamedDecl *D) {
const LangOptions &Opts = D->getASTContext().getLangOpts();
if (!Opts.CPlusPlus || !Opts.InlineVisibilityHidden)
return false;
const auto *FD = dyn_cast<FunctionDecl>(D);
if (!FD)
return false;
TemplateSpecializationKind TSK = TSK_Undeclared;
if (FunctionTemplateSpecializationInfo *spec
= FD->getTemplateSpecializationInfo()) {
TSK = spec->getTemplateSpecializationKind();
} else if (MemberSpecializationInfo *MSI =
FD->getMemberSpecializationInfo()) {
TSK = MSI->getTemplateSpecializationKind();
}
const FunctionDecl *Def = nullptr;
return TSK != TSK_ExplicitInstantiationDeclaration &&
TSK != TSK_ExplicitInstantiationDefinition &&
FD->hasBody(Def) && Def->isInlined() && !Def->hasAttr<GNUInlineAttr>();
}
template <typename T> static bool isFirstInExternCContext(T *D) {
const T *First = D->getFirstDecl();
return First->isInExternCContext();
}
static bool isSingleLineLanguageLinkage(const Decl &D) {
if (const auto *SD = dyn_cast<LinkageSpecDecl>(D.getDeclContext()))
if (!SD->hasBraces())
return true;
return false;
}
static bool isInModulePurview(const NamedDecl *D) {
if (auto *M = D->getOwningModule())
return M->isModulePurview();
return false;
}
static bool isExportedFromModuleInterfaceUnit(const NamedDecl *D) {
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 isInModulePurview(D);
}
llvm_unreachable("unexpected module ownership kind");
}
static LinkageInfo getInternalLinkageFor(const NamedDecl *D) {
if (isInModulePurview(D) && D->getASTContext().getLangOpts().ModulesTS)
return LinkageInfo(ModuleInternalLinkage, DefaultVisibility, false);
return LinkageInfo::internal();
}
static LinkageInfo getExternalLinkageFor(const NamedDecl *D) {
if (isInModulePurview(D) &&
!isExportedFromModuleInterfaceUnit(
cast<NamedDecl>(D->getCanonicalDecl())) &&
!isa<NamespaceDecl>(D))
return LinkageInfo(ModuleLinkage, DefaultVisibility, false);
return LinkageInfo::external();
}
static StorageClass getStorageClass(const Decl *D) {
if (auto *TD = dyn_cast<TemplateDecl>(D))
D = TD->getTemplatedDecl();
if (D) {
if (auto *VD = dyn_cast<VarDecl>(D))
return VD->getStorageClass();
if (auto *FD = dyn_cast<FunctionDecl>(D))
return FD->getStorageClass();
}
return SC_None;
}
LinkageInfo
LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D,
LVComputationKind computation,
bool IgnoreVarTypeLinkage) {
assert(D->getDeclContext()->getRedeclContext()->isFileContext() &&
"Not a name having namespace scope");
ASTContext &Context = D->getASTContext();
if (getStorageClass(D->getCanonicalDecl()) == SC_Static) {
return getInternalLinkageFor(D);
}
if (const auto *Var = dyn_cast<VarDecl>(D)) {
if (Context.getLangOpts().CPlusPlus &&
Var->getType().isConstQualified() &&
!Var->getType().isVolatileQualified() &&
!Var->isInline() &&
!isExportedFromModuleInterfaceUnit(Var) &&
!isa<VarTemplateSpecializationDecl>(Var) &&
!Var->getDescribedVarTemplate()) {
const VarDecl *PrevVar = Var->getPreviousDecl();
if (PrevVar)
return getLVForDecl(PrevVar, computation);
if (Var->getStorageClass() != SC_Extern &&
Var->getStorageClass() != SC_PrivateExtern &&
!isSingleLineLanguageLinkage(*Var))
return getInternalLinkageFor(Var);
}
for (const VarDecl *PrevVar = Var->getPreviousDecl(); PrevVar;
PrevVar = PrevVar->getPreviousDecl()) {
if (PrevVar->getStorageClass() == SC_PrivateExtern &&
Var->getStorageClass() == SC_None)
return getDeclLinkageAndVisibility(PrevVar);
if (PrevVar->getStorageClass() == SC_Static)
return getInternalLinkageFor(Var);
}
} else if (const auto *IFD = dyn_cast<IndirectFieldDecl>(D)) {
const VarDecl *VD = IFD->getVarDecl();
assert(VD && "Expected a VarDecl in this IndirectFieldDecl!");
return getLVForNamespaceScopeDecl(VD, computation, IgnoreVarTypeLinkage);
}
assert(!isa<FieldDecl>(D) && "Didn't expect a FieldDecl!");
if (D->isInAnonymousNamespace()) {
const auto *Var = dyn_cast<VarDecl>(D);
const auto *Func = dyn_cast<FunctionDecl>(D);
if ((!Var || !isFirstInExternCContext(Var)) &&
(!Func || !isFirstInExternCContext(Func)))
return getInternalLinkageFor(D);
}
LinkageInfo LV = getExternalLinkageFor(D);
if (!hasExplicitVisibilityAlready(computation)) {
if (Optional<Visibility> Vis = getExplicitVisibility(D, computation)) {
LV.mergeVisibility(*Vis, true);
} else {
for (const DeclContext *DC = D->getDeclContext();
!isa<TranslationUnitDecl>(DC);
DC = DC->getParent()) {
const auto *ND = dyn_cast<NamespaceDecl>(DC);
if (!ND) continue;
if (Optional<Visibility> Vis = getExplicitVisibility(ND, computation)) {
LV.mergeVisibility(*Vis, true);
break;
}
}
}
if (!LV.isVisibilityExplicit()) {
Visibility globalVisibility =
computation.isValueVisibility()
? Context.getLangOpts().getValueVisibilityMode()
: Context.getLangOpts().getTypeVisibilityMode();
LV.mergeVisibility(globalVisibility, false);
if (useInlineVisibilityHidden(D))
LV.mergeVisibility(HiddenVisibility, false);
}
}
if (const auto *Var = dyn_cast<VarDecl>(D)) {
if (Context.getLangOpts().CPlusPlus && !isFirstInExternCContext(Var) &&
!IgnoreVarTypeLinkage) {
LinkageInfo TypeLV = getLVForType(*Var->getType(), computation);
if (!isExternallyVisible(TypeLV.getLinkage()))
return LinkageInfo::uniqueExternal();
if (!LV.isVisibilityExplicit())
LV.mergeVisibility(TypeLV);
}
if (Var->getStorageClass() == SC_PrivateExtern)
LV.mergeVisibility(HiddenVisibility, true);
if (const auto *spec = dyn_cast<VarTemplateSpecializationDecl>(Var)) {
mergeTemplateLV(LV, spec, computation);
}
} else if (const auto *Function = dyn_cast<FunctionDecl>(D)) {
if (Function->getStorageClass() == SC_PrivateExtern)
LV.mergeVisibility(HiddenVisibility, true);
if (Context.getLangOpts().CPlusPlus && !isFirstInExternCContext(Function)) {
QualType TypeAsWritten = Function->getType();
if (TypeSourceInfo *TSI = Function->getTypeSourceInfo())
TypeAsWritten = TSI->getType();
if (!isExternallyVisible(TypeAsWritten->getLinkage()))
return LinkageInfo::uniqueExternal();
}
if (FunctionTemplateSpecializationInfo *specInfo
= Function->getTemplateSpecializationInfo()) {
mergeTemplateLV(LV, Function, specInfo, computation);
}
} else if (const auto *Tag = dyn_cast<TagDecl>(D)) {
if (!Tag->hasNameForLinkage())
return LinkageInfo::none();
if (const auto *spec = dyn_cast<ClassTemplateSpecializationDecl>(Tag)) {
mergeTemplateLV(LV, spec, computation);
}
} else if (isa<EnumConstantDecl>(D)) {
LinkageInfo EnumLV = getLVForDecl(cast<NamedDecl>(D->getDeclContext()),
computation);
if (!isExternalFormalLinkage(EnumLV.getLinkage()))
return LinkageInfo::none();
LV.merge(EnumLV);
} else if (const auto *temp = dyn_cast<TemplateDecl>(D)) {
bool considerVisibility = !hasExplicitVisibilityAlready(computation);
LinkageInfo tempLV =
getLVForTemplateParameterList(temp->getTemplateParameters(), computation);
LV.mergeMaybeWithVisibility(tempLV, considerVisibility);
} else if (isa<NamespaceDecl>(D)) {
return LV;
} else if (isa<ObjCInterfaceDecl>(D)) {
} else if (auto *TD = dyn_cast<TypedefNameDecl>(D)) {
if (!TD->getAnonDeclWithTypedefName(true))
return LinkageInfo::none();
} else if (isa<MSGuidDecl>(D)) {
} else {
return LinkageInfo::none();
}
if (!isExternallyVisible(LV.getLinkage()))
return LinkageInfo(LV.getLinkage(), DefaultVisibility, false);
return LV;
}
LinkageInfo
LinkageComputer::getLVForClassMember(const NamedDecl *D,
LVComputationKind computation,
bool IgnoreVarTypeLinkage) {
if (!(isa<CXXMethodDecl>(D) ||
isa<VarDecl>(D) ||
isa<FieldDecl>(D) ||
isa<IndirectFieldDecl>(D) ||
isa<TagDecl>(D) ||
isa<TemplateDecl>(D)))
return LinkageInfo::none();
LinkageInfo LV;
if (!hasExplicitVisibilityAlready(computation)) {
if (Optional<Visibility> Vis = getExplicitVisibility(D, computation))
LV.mergeVisibility(*Vis, true);
if (!LV.isVisibilityExplicit() && useInlineVisibilityHidden(D))
LV.mergeVisibility(HiddenVisibility, false);
}
LVComputationKind classComputation = computation;
if (LV.isVisibilityExplicit())
classComputation = withExplicitVisibilityAlready(computation);
LinkageInfo classLV =
getLVForDecl(cast<RecordDecl>(D->getDeclContext()), classComputation);
if (!isExternallyVisible(classLV.getLinkage()))
return classLV;
const NamedDecl *explicitSpecSuppressor = nullptr;
if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
QualType TypeAsWritten = MD->getType();
if (TypeSourceInfo *TSI = MD->getTypeSourceInfo())
TypeAsWritten = TSI->getType();
if (!isExternallyVisible(TypeAsWritten->getLinkage()))
return LinkageInfo::uniqueExternal();
if (FunctionTemplateSpecializationInfo *spec
= MD->getTemplateSpecializationInfo()) {
mergeTemplateLV(LV, MD, spec, computation);
if (spec->isExplicitSpecialization()) {
explicitSpecSuppressor = MD;
} else if (isExplicitMemberSpecialization(spec->getTemplate())) {
explicitSpecSuppressor = spec->getTemplate()->getTemplatedDecl();
}
} else if (isExplicitMemberSpecialization(MD)) {
explicitSpecSuppressor = MD;
}
} else if (const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
if (const auto *spec = dyn_cast<ClassTemplateSpecializationDecl>(RD)) {
mergeTemplateLV(LV, spec, computation);
if (spec->isExplicitSpecialization()) {
explicitSpecSuppressor = spec;
} else {
const ClassTemplateDecl *temp = spec->getSpecializedTemplate();
if (isExplicitMemberSpecialization(temp)) {
explicitSpecSuppressor = temp->getTemplatedDecl();
}
}
} else if (isExplicitMemberSpecialization(RD)) {
explicitSpecSuppressor = RD;
}
} else if (const auto *VD = dyn_cast<VarDecl>(D)) {
if (const auto *spec = dyn_cast<VarTemplateSpecializationDecl>(VD))
mergeTemplateLV(LV, spec, computation);
if (!IgnoreVarTypeLinkage) {
LinkageInfo typeLV = getLVForType(*VD->getType(), computation);
if (!LV.isVisibilityExplicit() && !classLV.isVisibilityExplicit())
LV.mergeVisibility(typeLV);
LV.mergeExternalVisibility(typeLV);
}
if (isExplicitMemberSpecialization(VD)) {
explicitSpecSuppressor = VD;
}
} else if (const auto *temp = dyn_cast<TemplateDecl>(D)) {
bool considerVisibility =
(!LV.isVisibilityExplicit() &&
!classLV.isVisibilityExplicit() &&
!hasExplicitVisibilityAlready(computation));
LinkageInfo tempLV =
getLVForTemplateParameterList(temp->getTemplateParameters(), computation);
LV.mergeMaybeWithVisibility(tempLV, considerVisibility);
if (const auto *redeclTemp = dyn_cast<RedeclarableTemplateDecl>(temp)) {
if (isExplicitMemberSpecialization(redeclTemp)) {
explicitSpecSuppressor = temp->getTemplatedDecl();
}
}
}
assert(!explicitSpecSuppressor || !isa<TemplateDecl>(explicitSpecSuppressor));
bool considerClassVisibility = true;
if (explicitSpecSuppressor &&
LV.isVisibilityExplicit() &&
classLV.getVisibility() != DefaultVisibility &&
hasDirectVisibilityAttribute(explicitSpecSuppressor, computation)) {
considerClassVisibility = false;
}
LV.mergeMaybeWithVisibility(classLV, considerClassVisibility);
return LV;
}
void NamedDecl::anchor() {}
bool NamedDecl::isLinkageValid() const {
if (!hasCachedLinkage())
return true;
Linkage L = LinkageComputer{}
.computeLVForDecl(this, LVComputationKind::forLinkageOnly())
.getLinkage();
return L == getCachedLinkage();
}
ReservedIdentifierStatus
NamedDecl::isReserved(const LangOptions &LangOpts) const {
const IdentifierInfo *II = getIdentifier();
if (!II)
return ReservedIdentifierStatus::NotReserved;
ReservedIdentifierStatus Status = II->isReserved(LangOpts);
if (isReservedAtGlobalScope(Status) && !isReservedInAllContexts(Status)) {
if (isa<ParmVarDecl>(this) || isTemplateParameter())
return ReservedIdentifierStatus::NotReserved;
const DeclContext *DC = getDeclContext()->getRedeclContext();
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;
}
ObjCStringFormatFamily NamedDecl::getObjCFStringFormattingFamily() const {
StringRef name = getName();
if (name.empty()) return SFF_None;
if (name.front() == 'C')
if (name == "CFStringCreateWithFormat" ||
name == "CFStringCreateWithFormatAndArguments" ||
name == "CFStringAppendFormat" ||
name == "CFStringAppendFormatAndArguments")
return SFF_CFString;
return SFF_None;
}
Linkage NamedDecl::getLinkageInternal() const {
return LinkageComputer{}
.getLVForDecl(this, LVComputationKind::forLinkageOnly())
.getLinkage();
}
LinkageInfo NamedDecl::getLinkageAndVisibility() const {
return LinkageComputer{}.getDeclLinkageAndVisibility(this);
}
static Optional<Visibility>
getExplicitVisibilityAux(const NamedDecl *ND,
NamedDecl::ExplicitVisibilityKind kind,
bool IsMostRecent) {
assert(!IsMostRecent || ND == ND->getMostRecentDecl());
if (Optional<Visibility> V = getVisibilityOf(ND, kind))
return V;
if (const auto *RD = dyn_cast<CXXRecordDecl>(ND)) {
CXXRecordDecl *InstantiatedFrom = RD->getInstantiatedFromMemberClass();
if (InstantiatedFrom)
return getVisibilityOf(InstantiatedFrom, kind);
}
if (const auto *spec = dyn_cast<ClassTemplateSpecializationDecl>(ND)) {
const auto *TD = spec->getSpecializedTemplate()->getTemplatedDecl();
while (TD != nullptr) {
auto Vis = getVisibilityOf(TD, kind);
if (Vis != None)
return Vis;
TD = TD->getPreviousDecl();
}
return None;
}
if (!IsMostRecent && !isa<NamespaceDecl>(ND)) {
const NamedDecl *MostRecent = ND->getMostRecentDecl();
if (MostRecent != ND)
return getExplicitVisibilityAux(MostRecent, kind, true);
}
if (const auto *Var = dyn_cast<VarDecl>(ND)) {
if (Var->isStaticDataMember()) {
VarDecl *InstantiatedFrom = Var->getInstantiatedFromStaticDataMember();
if (InstantiatedFrom)
return getVisibilityOf(InstantiatedFrom, kind);
}
if (const auto *VTSD = dyn_cast<VarTemplateSpecializationDecl>(Var))
return getVisibilityOf(VTSD->getSpecializedTemplate()->getTemplatedDecl(),
kind);
return None;
}
if (const auto *fn = dyn_cast<FunctionDecl>(ND)) {
if (FunctionTemplateSpecializationInfo *templateInfo
= fn->getTemplateSpecializationInfo())
return getVisibilityOf(templateInfo->getTemplate()->getTemplatedDecl(),
kind);
FunctionDecl *InstantiatedFrom = fn->getInstantiatedFromMemberFunction();
if (InstantiatedFrom)
return getVisibilityOf(InstantiatedFrom, kind);
return None;
}
if (const auto *TD = dyn_cast<TemplateDecl>(ND))
return getVisibilityOf(TD->getTemplatedDecl(), kind);
return None;
}
Optional<Visibility>
NamedDecl::getExplicitVisibility(ExplicitVisibilityKind kind) const {
return getExplicitVisibilityAux(this, kind, false);
}
LinkageInfo LinkageComputer::getLVForClosure(const DeclContext *DC,
Decl *ContextDecl,
LVComputationKind computation) {
const NamedDecl *Owner;
if (!ContextDecl)
Owner = dyn_cast<NamedDecl>(DC);
else if (isa<ParmVarDecl>(ContextDecl))
Owner =
dyn_cast<NamedDecl>(ContextDecl->getDeclContext()->getRedeclContext());
else
Owner = cast<NamedDecl>(ContextDecl);
if (!Owner)
return LinkageInfo::none();
auto *VD = dyn_cast<VarDecl>(Owner);
LinkageInfo OwnerLV =
VD && VD->getType()->getContainedDeducedType()
? computeLVForDecl(Owner, computation, true)
: getLVForDecl(Owner, computation);
if (!isExternallyVisible(OwnerLV.getLinkage()))
return LinkageInfo::none();
return LinkageInfo(VisibleNoLinkage, OwnerLV.getVisibility(),
OwnerLV.isVisibilityExplicit());
}
LinkageInfo LinkageComputer::getLVForLocalDecl(const NamedDecl *D,
LVComputationKind computation) {
if (const auto *Function = dyn_cast<FunctionDecl>(D)) {
if (Function->isInAnonymousNamespace() &&
!isFirstInExternCContext(Function))
return getInternalLinkageFor(Function);
if (Function->getCanonicalDecl()->getStorageClass() == SC_Static)
return getInternalLinkageFor(Function);
LinkageInfo LV;
if (!hasExplicitVisibilityAlready(computation)) {
if (Optional<Visibility> Vis =
getExplicitVisibility(Function, computation))
LV.mergeVisibility(*Vis, true);
}
return LV;
}
if (const auto *Var = dyn_cast<VarDecl>(D)) {
if (Var->hasExternalStorage()) {
if (Var->isInAnonymousNamespace() && !isFirstInExternCContext(Var))
return getInternalLinkageFor(Var);
LinkageInfo LV;
if (Var->getStorageClass() == SC_PrivateExtern)
LV.mergeVisibility(HiddenVisibility, true);
else if (!hasExplicitVisibilityAlready(computation)) {
if (Optional<Visibility> Vis = getExplicitVisibility(Var, computation))
LV.mergeVisibility(*Vis, true);
}
if (const VarDecl *Prev = Var->getPreviousDecl()) {
LinkageInfo PrevLV = getLVForDecl(Prev, computation);
if (PrevLV.getLinkage())
LV.setLinkage(PrevLV.getLinkage());
LV.mergeVisibility(PrevLV);
}
return LV;
}
if (!Var->isStaticLocal())
return LinkageInfo::none();
}
ASTContext &Context = D->getASTContext();
if (!Context.getLangOpts().CPlusPlus)
return LinkageInfo::none();
const Decl *OuterD = getOutermostFuncOrBlockContext(D);
if (!OuterD || OuterD->isInvalidDecl())
return LinkageInfo::none();
LinkageInfo LV;
if (const auto *BD = dyn_cast<BlockDecl>(OuterD)) {
if (!BD->getBlockManglingNumber())
return LinkageInfo::none();
LV = getLVForClosure(BD->getDeclContext()->getRedeclContext(),
BD->getBlockManglingContextDecl(), computation);
} else {
const auto *FD = cast<FunctionDecl>(OuterD);
if (!FD->isInlined() &&
!isTemplateInstantiation(FD->getTemplateSpecializationKind()))
return LinkageInfo::none();
LV = getLVForDecl(FD, computation);
if (isa<VarDecl>(D) && useInlineVisibilityHidden(FD) &&
!LV.isVisibilityExplicit() &&
!Context.getLangOpts().VisibilityInlinesHiddenStaticLocalVar) {
assert(cast<VarDecl>(D)->isStaticLocal());
if (const auto *MD = dyn_cast<CXXMethodDecl>(FD))
LV = getLVForDecl(MD->getParent(), computation);
if (!LV.isVisibilityExplicit()) {
Visibility globalVisibility =
computation.isValueVisibility()
? Context.getLangOpts().getValueVisibilityMode()
: Context.getLangOpts().getTypeVisibilityMode();
return LinkageInfo(VisibleNoLinkage, globalVisibility,
false);
}
}
}
if (!isExternallyVisible(LV.getLinkage()))
return LinkageInfo::none();
return LinkageInfo(VisibleNoLinkage, LV.getVisibility(),
LV.isVisibilityExplicit());
}
LinkageInfo LinkageComputer::computeLVForDecl(const NamedDecl *D,
LVComputationKind computation,
bool IgnoreVarTypeLinkage) {
if (D->hasAttr<InternalLinkageAttr>())
return getInternalLinkageFor(D);
switch (D->getKind()) {
default:
break;
case Decl::ImplicitParam:
case Decl::Label:
case Decl::NamespaceAlias:
case Decl::ParmVar:
case Decl::Using:
case Decl::UsingEnum:
case Decl::UsingShadow:
case Decl::UsingDirective:
return LinkageInfo::none();
case Decl::EnumConstant:
if (D->getASTContext().getLangOpts().CPlusPlus)
return getLVForDecl(cast<EnumDecl>(D->getDeclContext()), computation);
return LinkageInfo::visible_none();
case Decl::Typedef:
case Decl::TypeAlias:
if (!cast<TypedefNameDecl>(D)
->getAnonDeclWithTypedefName(true))
return LinkageInfo::none();
break;
case Decl::TemplateTemplateParm: case Decl::NonTypeTemplateParm:
case Decl::ObjCAtDefsField:
case Decl::ObjCCategory:
case Decl::ObjCCategoryImpl:
case Decl::ObjCCompatibleAlias:
case Decl::ObjCImplementation:
case Decl::ObjCMethod:
case Decl::ObjCProperty:
case Decl::ObjCPropertyImpl:
case Decl::ObjCProtocol:
return getExternalLinkageFor(D);
case Decl::CXXRecord: {
const auto *Record = cast<CXXRecordDecl>(D);
if (Record->isLambda()) {
if (Record->hasKnownLambdaInternalLinkage() ||
!Record->getLambdaManglingNumber()) {
return getInternalLinkageFor(D);
}
return getLVForClosure(
Record->getDeclContext()->getRedeclContext(),
Record->getLambdaContextDecl(), computation);
}
break;
}
case Decl::TemplateParamObject: {
auto *TPO = cast<TemplateParamObjectDecl>(D);
LinkageInfo LV = getLVForType(*TPO->getType(), computation);
LV.merge(getLVForValue(TPO->getValue(), computation));
return LV;
}
}
if (D->getDeclContext()->getRedeclContext()->isFileContext())
return getLVForNamespaceScopeDecl(D, computation, IgnoreVarTypeLinkage);
if (D->getDeclContext()->isRecord())
return getLVForClassMember(D, computation, IgnoreVarTypeLinkage);
if (D->getDeclContext()->isFunctionOrMethod())
return getLVForLocalDecl(D, computation);
return LinkageInfo::none();
}
LinkageInfo LinkageComputer::getLVForDecl(const NamedDecl *D,
LVComputationKind computation) {
if (D->hasAttr<InternalLinkageAttr>())
return getInternalLinkageFor(D);
if (computation.IgnoreAllVisibility && D->hasCachedLinkage())
return LinkageInfo(D->getCachedLinkage(), DefaultVisibility, false);
if (llvm::Optional<LinkageInfo> LI = lookup(D, computation))
return *LI;
LinkageInfo LV = computeLVForDecl(D, computation);
if (D->hasCachedLinkage())
assert(D->getCachedLinkage() == LV.getLinkage());
D->setCachedLinkage(LV.getLinkage());
cache(D, computation, LV);
#ifndef NDEBUG
const LangOptions &Opts = D->getASTContext().getLangOpts();
if (!Opts.CPlusPlus || Opts.MicrosoftExt)
return LV;
NamedDecl *Old = nullptr;
for (auto I : D->redecls()) {
auto *T = cast<NamedDecl>(I);
if (T == D)
continue;
if (!T->isInvalidDecl() && T->hasCachedLinkage()) {
Old = T;
break;
}
}
assert(!Old || Old->getCachedLinkage() == D->getCachedLinkage());
#endif
return LV;
}
LinkageInfo LinkageComputer::getDeclLinkageAndVisibility(const NamedDecl *D) {
NamedDecl::ExplicitVisibilityKind EK = usesTypeVisibility(D)
? NamedDecl::VisibilityForType
: NamedDecl::VisibilityForValue;
LVComputationKind CK(EK);
return getLVForDecl(D, D->getASTContext().getLangOpts().IgnoreXCOFFVisibility
? CK.forLinkageOnly()
: CK);
}
Module *Decl::getOwningModuleForLinkage(bool IgnoreLinkage) const {
if (isa<NamespaceDecl>(this))
return nullptr;
Module *M = getOwningModule();
if (!M)
return nullptr;
switch (M->Kind) {
case Module::ModuleMapModule:
return nullptr;
case Module::ModuleInterfaceUnit:
case Module::ModulePartitionInterface:
case Module::ModulePartitionImplementation:
return M;
case Module::ModuleHeaderUnit:
case Module::GlobalModuleFragment: {
if (IgnoreLinkage)
return nullptr;
bool InternalLinkage;
if (auto *ND = dyn_cast<NamedDecl>(this))
InternalLinkage = !ND->hasExternalFormalLinkage();
else
InternalLinkage = isInAnonymousNamespace();
return InternalLinkage ? M->Kind == Module::ModuleHeaderUnit ? M : M->Parent
: nullptr;
}
case Module::PrivateModuleFragment:
return M->Parent;
}
llvm_unreachable("unknown module kind");
}
void NamedDecl::printName(raw_ostream &os) const {
os << Name;
}
std::string NamedDecl::getQualifiedNameAsString() const {
std::string QualName;
llvm::raw_string_ostream OS(QualName);
printQualifiedName(OS, getASTContext().getPrintingPolicy());
return QualName;
}
void NamedDecl::printQualifiedName(raw_ostream &OS) const {
printQualifiedName(OS, getASTContext().getPrintingPolicy());
}
void NamedDecl::printQualifiedName(raw_ostream &OS,
const PrintingPolicy &P) const {
if (getDeclContext()->isFunctionOrMethod()) {
printName(OS);
return;
}
printNestedNameSpecifier(OS, P);
if (getDeclName())
OS << *this;
else {
SmallString<64> NameBuffer;
llvm::raw_svector_ostream NameOS(NameBuffer);
printName(NameOS);
if (NameBuffer.empty())
OS << "(anonymous)";
else
OS << NameBuffer;
}
}
void NamedDecl::printNestedNameSpecifier(raw_ostream &OS) const {
printNestedNameSpecifier(OS, getASTContext().getPrintingPolicy());
}
void NamedDecl::printNestedNameSpecifier(raw_ostream &OS,
const PrintingPolicy &P) const {
const DeclContext *Ctx = getDeclContext();
if (auto *MD = dyn_cast<ObjCMethodDecl>(this)) {
if (auto *ID = MD->getClassInterface())
Ctx = ID;
} else if (auto *PD = dyn_cast<ObjCPropertyDecl>(this)) {
if (auto *MD = PD->getGetterMethodDecl())
if (auto *ID = MD->getClassInterface())
Ctx = ID;
} else if (auto *ID = dyn_cast<ObjCIvarDecl>(this)) {
if (auto *CI = ID->getContainingInterface())
Ctx = CI;
}
if (Ctx->isFunctionOrMethod())
return;
using ContextsTy = SmallVector<const DeclContext *, 8>;
ContextsTy Contexts;
DeclarationName NameInScope = getDeclName();
for (; Ctx; Ctx = Ctx->getParent()) {
if (P.SuppressUnwrittenScope && isa<NamespaceDecl>(Ctx) &&
cast<NamespaceDecl>(Ctx)->isAnonymousNamespace())
continue;
if (P.SuppressInlineNamespace && Ctx->isInlineNamespace() && NameInScope &&
cast<NamespaceDecl>(Ctx)->isRedundantInlineQualifierFor(NameInScope))
continue;
const NamedDecl *ND = dyn_cast<NamedDecl>(Ctx);
if (!ND)
continue;
Contexts.push_back(Ctx);
NameInScope = ND->getDeclName();
}
for (const DeclContext *DC : llvm::reverse(Contexts)) {
if (const auto *Spec = dyn_cast<ClassTemplateSpecializationDecl>(DC)) {
OS << Spec->getName();
const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
printTemplateArgumentList(
OS, TemplateArgs.asArray(), P,
Spec->getSpecializedTemplate()->getTemplateParameters());
} else if (const auto *ND = dyn_cast<NamespaceDecl>(DC)) {
if (ND->isAnonymousNamespace()) {
OS << (P.MSVCFormatting ? "`anonymous namespace\'"
: "(anonymous namespace)");
}
else
OS << *ND;
} else if (const auto *RD = dyn_cast<RecordDecl>(DC)) {
if (!RD->getIdentifier())
OS << "(anonymous " << RD->getKindName() << ')';
else
OS << *RD;
} else if (const auto *FD = dyn_cast<FunctionDecl>(DC)) {
const FunctionProtoType *FT = nullptr;
if (FD->hasWrittenPrototype())
FT = dyn_cast<FunctionProtoType>(FD->getType()->castAs<FunctionType>());
OS << *FD << '(';
if (FT) {
unsigned NumParams = FD->getNumParams();
for (unsigned i = 0; i < NumParams; ++i) {
if (i)
OS << ", ";
OS << FD->getParamDecl(i)->getType().stream(P);
}
if (FT->isVariadic()) {
if (NumParams > 0)
OS << ", ";
OS << "...";
}
}
OS << ')';
} else if (const auto *ED = dyn_cast<EnumDecl>(DC)) {
if (ED->isScoped())
OS << *ED;
else
continue;
} else {
OS << *cast<NamedDecl>(DC);
}
OS << "::";
}
}
void NamedDecl::getNameForDiagnostic(raw_ostream &OS,
const PrintingPolicy &Policy,
bool Qualified) const {
if (Qualified)
printQualifiedName(OS, Policy);
else
printName(OS);
}
template<typename T> static bool isRedeclarableImpl(Redeclarable<T> *) {
return true;
}
static bool isRedeclarableImpl(...) { return false; }
static bool isRedeclarable(Decl::Kind K) {
switch (K) {
#define DECL(Type, Base) \
case Decl::Type: \
return isRedeclarableImpl((Type##Decl *)nullptr);
#define ABSTRACT_DECL(DECL)
#include "clang/AST/DeclNodes.inc"
}
llvm_unreachable("unknown decl kind");
}
bool NamedDecl::declarationReplaces(NamedDecl *OldD, bool IsKnownNewer) const {
assert(getDeclName() == OldD->getDeclName() && "Declaration name mismatch");
if (OldD->isFromASTFile() && isFromASTFile())
return false;
if (OldD->getKind() != getKind())
return false;
if (isa<ObjCMethodDecl>(this))
return false;
if (isa<ParmVarDecl>(this))
return true;
if (!this->getDeclContext()->getRedeclContext()->Equals(
OldD->getDeclContext()->getRedeclContext()))
return false;
if (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)) {
ASTContext &Context = getASTContext();
return Context.getCanonicalNestedNameSpecifier(UUVD->getQualifier()) ==
Context.getCanonicalNestedNameSpecifier(
cast<UnresolvedUsingValueDecl>(OldD)->getQualifier());
}
if (isRedeclarable(getKind())) {
if (getCanonicalDecl() != OldD->getCanonicalDecl())
return false;
if (IsKnownNewer)
return true;
for (auto D : redecls()) {
if (D == OldD)
break;
if (D->isCanonicalDecl())
return false;
}
return true;
}
return false;
}
bool NamedDecl::hasLinkage() const {
return getFormalLinkage() != NoLinkage;
}
NamedDecl *NamedDecl::getUnderlyingDeclImpl() {
NamedDecl *ND = this;
if (auto *UD = dyn_cast<UsingShadowDecl>(ND))
ND = UD->getTargetDecl();
if (auto *AD = dyn_cast<ObjCCompatibleAliasDecl>(ND))
return AD->getClassInterface();
if (auto *AD = dyn_cast<NamespaceAliasDecl>(ND))
return AD->getNamespace();
return ND;
}
bool NamedDecl::isCXXInstanceMember() const {
if (!isCXXClassMember())
return false;
const NamedDecl *D = this;
if (isa<UsingShadowDecl>(D))
D = cast<UsingShadowDecl>(D)->getTargetDecl();
if (isa<FieldDecl>(D) || isa<IndirectFieldDecl>(D) || isa<MSPropertyDecl>(D))
return true;
if (const auto *MD = dyn_cast_or_null<CXXMethodDecl>(D->getAsFunction()))
return MD->isInstance();
return false;
}
template <typename DeclT>
static SourceLocation getTemplateOrInnerLocStart(const DeclT *decl) {
if (decl->getNumTemplateParameterLists() > 0)
return decl->getTemplateParameterList(0)->getTemplateLoc();
return decl->getInnerLocStart();
}
SourceLocation DeclaratorDecl::getTypeSpecStartLoc() const {
TypeSourceInfo *TSI = getTypeSourceInfo();
if (TSI) return TSI->getTypeLoc().getBeginLoc();
return SourceLocation();
}
SourceLocation DeclaratorDecl::getTypeSpecEndLoc() const {
TypeSourceInfo *TSI = getTypeSourceInfo();
if (TSI) return TSI->getTypeLoc().getEndLoc();
return SourceLocation();
}
void DeclaratorDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) {
if (QualifierLoc) {
if (!hasExtInfo()) {
auto *savedTInfo = DeclInfo.get<TypeSourceInfo*>();
DeclInfo = new (getASTContext()) ExtInfo;
getExtInfo()->TInfo = savedTInfo;
}
getExtInfo()->QualifierLoc = QualifierLoc;
} else if (hasExtInfo()) {
getExtInfo()->QualifierLoc = QualifierLoc;
}
}
void DeclaratorDecl::setTrailingRequiresClause(Expr *TrailingRequiresClause) {
assert(TrailingRequiresClause);
if (!hasExtInfo()) {
auto *savedTInfo = DeclInfo.get<TypeSourceInfo*>();
DeclInfo = new (getASTContext()) ExtInfo;
getExtInfo()->TInfo = savedTInfo;
}
getExtInfo()->TrailingRequiresClause = TrailingRequiresClause;
}
void DeclaratorDecl::setTemplateParameterListsInfo(
ASTContext &Context, ArrayRef<TemplateParameterList *> TPLists) {
assert(!TPLists.empty());
if (!hasExtInfo()) {
auto *savedTInfo = DeclInfo.get<TypeSourceInfo*>();
DeclInfo = new (getASTContext()) ExtInfo;
getExtInfo()->TInfo = savedTInfo;
}
getExtInfo()->setTemplateParameterListsInfo(Context, TPLists);
}
SourceLocation DeclaratorDecl::getOuterLocStart() const {
return getTemplateOrInnerLocStart(this);
}
static bool typeIsPostfix(QualType QT) {
while (true) {
const Type* T = QT.getTypePtr();
switch (T->getTypeClass()) {
default:
return false;
case Type::Pointer:
QT = cast<PointerType>(T)->getPointeeType();
break;
case Type::BlockPointer:
QT = cast<BlockPointerType>(T)->getPointeeType();
break;
case Type::MemberPointer:
QT = cast<MemberPointerType>(T)->getPointeeType();
break;
case Type::LValueReference:
case Type::RValueReference:
QT = cast<ReferenceType>(T)->getPointeeType();
break;
case Type::PackExpansion:
QT = cast<PackExpansionType>(T)->getPattern();
break;
case Type::Paren:
case Type::ConstantArray:
case Type::DependentSizedArray:
case Type::IncompleteArray:
case Type::VariableArray:
case Type::FunctionProto:
case Type::FunctionNoProto:
return true;
}
}
}
SourceRange DeclaratorDecl::getSourceRange() const {
SourceLocation RangeEnd = getLocation();
if (TypeSourceInfo *TInfo = getTypeSourceInfo()) {
if (!getDeclName() || typeIsPostfix(TInfo->getType()))
RangeEnd = TInfo->getTypeLoc().getSourceRange().getEnd();
}
return SourceRange(getOuterLocStart(), RangeEnd);
}
void QualifierInfo::setTemplateParameterListsInfo(
ASTContext &Context, ArrayRef<TemplateParameterList *> TPLists) {
if (NumTemplParamLists > 0) {
Context.Deallocate(TemplParamLists);
TemplParamLists = nullptr;
NumTemplParamLists = 0;
}
if (!TPLists.empty()) {
TemplParamLists = new (Context) TemplateParameterList *[TPLists.size()];
NumTemplParamLists = TPLists.size();
std::copy(TPLists.begin(), TPLists.end(), TemplParamLists);
}
}
const char *VarDecl::getStorageClassSpecifierString(StorageClass SC) {
switch (SC) {
case SC_None: break;
case SC_Auto: return "auto";
case SC_Extern: return "extern";
case SC_PrivateExtern: return "__private_extern__";
case SC_Register: return "register";
case SC_Static: return "static";
}
llvm_unreachable("Invalid storage class");
}
VarDecl::VarDecl(Kind DK, ASTContext &C, DeclContext *DC,
SourceLocation StartLoc, SourceLocation IdLoc,
const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo,
StorageClass SC)
: DeclaratorDecl(DK, DC, IdLoc, Id, T, TInfo, StartLoc),
redeclarable_base(C) {
static_assert(sizeof(VarDeclBitfields) <= sizeof(unsigned),
"VarDeclBitfields too large!");
static_assert(sizeof(ParmVarDeclBitfields) <= sizeof(unsigned),
"ParmVarDeclBitfields too large!");
static_assert(sizeof(NonParmVarDeclBitfields) <= sizeof(unsigned),
"NonParmVarDeclBitfields too large!");
AllBits = 0;
VarDeclBits.SClass = SC;
}
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);
}
VarDecl *VarDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
return new (C, ID)
VarDecl(Var, C, nullptr, SourceLocation(), SourceLocation(), nullptr,
QualType(), nullptr, SC_None);
}
void VarDecl::setStorageClass(StorageClass SC) {
assert(isLegalForVariable(SC));
VarDeclBits.SClass = SC;
}
VarDecl::TLSKind VarDecl::getTLSKind() const {
switch (VarDeclBits.TSCSpec) {
case TSCS_unspecified:
if (!hasAttr<ThreadAttr>() &&
!(getASTContext().getLangOpts().OpenMPUseTLS &&
getASTContext().getTargetInfo().isTLSSupported() &&
hasAttr<OMPThreadPrivateDeclAttr>()))
return TLS_None;
return ((getASTContext().getLangOpts().isCompatibleWithMSVC(
LangOptions::MSVC2015)) ||
hasAttr<OMPThreadPrivateDeclAttr>())
? TLS_Dynamic
: TLS_Static;
case TSCS___thread: case TSCS__Thread_local:
return TLS_Static;
case TSCS_thread_local:
return TLS_Dynamic;
}
llvm_unreachable("Unknown thread storage class specifier!");
}
SourceRange VarDecl::getSourceRange() const {
if (const Expr *Init = getInit()) {
SourceLocation InitEnd = Init->getEndLoc();
if (InitEnd.isValid() && InitEnd != getLocation())
return SourceRange(getOuterLocStart(), InitEnd);
}
return DeclaratorDecl::getSourceRange();
}
template<typename T>
static LanguageLinkage getDeclLanguageLinkage(const T &D) {
if (!D.hasExternalFormalLinkage())
return NoLanguageLinkage;
ASTContext &Context = D.getASTContext();
if (!Context.getLangOpts().CPlusPlus)
return CLanguageLinkage;
const DeclContext *DC = D.getDeclContext();
if (DC->isRecord())
return CXXLanguageLinkage;
if (isFirstInExternCContext(&D))
return CLanguageLinkage;
return CXXLanguageLinkage;
}
template<typename T>
static bool isDeclExternC(const T &D) {
const DeclContext *DC = D.getDeclContext();
if (DC->isRecord()) {
assert(D.getASTContext().getLangOpts().CPlusPlus);
return false;
}
return D.getLanguageLinkage() == CLanguageLinkage;
}
LanguageLinkage VarDecl::getLanguageLinkage() const {
return getDeclLanguageLinkage(*this);
}
bool VarDecl::isExternC() const {
return isDeclExternC(*this);
}
bool VarDecl::isInExternCContext() const {
return getLexicalDeclContext()->isExternCContext();
}
bool VarDecl::isInExternCXXContext() const {
return getLexicalDeclContext()->isExternCXXContext();
}
VarDecl *VarDecl::getCanonicalDecl() { return getFirstDecl(); }
VarDecl::DefinitionKind
VarDecl::isThisDeclarationADefinition(ASTContext &C) const {
if (isThisDeclarationADemotedDefinition())
return DeclarationOnly;
if (isStaticDataMember()) {
if (isOutOfLine() &&
!(getCanonicalDecl()->isInline() &&
getCanonicalDecl()->isConstexpr()) &&
(hasInit() ||
(getFirstDecl()->isOutOfLine()
? getTemplateSpecializationKind() == TSK_Undeclared
: getTemplateSpecializationKind() !=
TSK_ExplicitSpecialization) ||
isa<VarTemplatePartialSpecializationDecl>(this)))
return Definition;
if (!isOutOfLine() && isInline())
return Definition;
return DeclarationOnly;
}
if (hasInit())
return Definition;
if (hasDefiningAttr())
return Definition;
if (const auto *SAA = getAttr<SelectAnyAttr>())
if (!SAA->isInherited())
return Definition;
if (auto *VTSD = dyn_cast<VarTemplateSpecializationDecl>(this)) {
if (VTSD->getTemplateSpecializationKind() != TSK_ExplicitSpecialization &&
!isa<VarTemplatePartialSpecializationDecl>(VTSD) &&
!VTSD->IsCompleteDefinition)
return DeclarationOnly;
}
if (hasExternalStorage())
return DeclarationOnly;
if (isSingleLineLanguageLinkage(*this))
return DeclarationOnly;
if (!C.getLangOpts().CPlusPlus && isFileVarDecl())
return TentativeDefinition;
return Definition;
}
VarDecl *VarDecl::getActingDefinition() {
DefinitionKind Kind = isThisDeclarationADefinition();
if (Kind != TentativeDefinition)
return nullptr;
VarDecl *LastTentative = nullptr;
for (VarDecl *Decl = getMostRecentDecl(); Decl;
Decl = Decl->getPreviousDecl()) {
Kind = Decl->isThisDeclarationADefinition();
if (Kind == Definition)
return nullptr;
if (Kind == TentativeDefinition && !LastTentative)
LastTentative = Decl;
}
return LastTentative;
}
VarDecl *VarDecl::getDefinition(ASTContext &C) {
VarDecl *First = getFirstDecl();
for (auto I : First->redecls()) {
if (I->isThisDeclarationADefinition(C) == Definition)
return I;
}
return nullptr;
}
VarDecl::DefinitionKind VarDecl::hasDefinition(ASTContext &C) const {
DefinitionKind Kind = DeclarationOnly;
const VarDecl *First = getFirstDecl();
for (auto I : First->redecls()) {
Kind = std::max(Kind, I->isThisDeclarationADefinition(C));
if (Kind == Definition)
break;
}
return Kind;
}
const Expr *VarDecl::getAnyInitializer(const VarDecl *&D) const {
for (auto I : redecls()) {
if (auto Expr = I->getInit()) {
D = I;
return Expr;
}
}
return nullptr;
}
bool VarDecl::hasInit() const {
if (auto *P = dyn_cast<ParmVarDecl>(this))
if (P->hasUnparsedDefaultArg() || P->hasUninstantiatedDefaultArg())
return false;
return !Init.isNull();
}
Expr *VarDecl::getInit() {
if (!hasInit())
return nullptr;
if (auto *S = Init.dyn_cast<Stmt *>())
return cast<Expr>(S);
return cast_or_null<Expr>(Init.get<EvaluatedStmt *>()->Value);
}
Stmt **VarDecl::getInitAddress() {
if (auto *ES = Init.dyn_cast<EvaluatedStmt *>())
return &ES->Value;
return Init.getAddrOfPtr1();
}
VarDecl *VarDecl::getInitializingDeclaration() {
VarDecl *Def = nullptr;
for (auto I : redecls()) {
if (I->hasInit())
return I;
if (I->isThisDeclarationADefinition()) {
if (isStaticDataMember())
return I;
Def = I;
}
}
return Def;
}
bool VarDecl::isOutOfLine() const {
if (Decl::isOutOfLine())
return true;
if (!isStaticDataMember())
return false;
if (VarDecl *VD = getInstantiatedFromStaticDataMember())
return VD->isOutOfLine();
return false;
}
void VarDecl::setInit(Expr *I) {
if (auto *Eval = Init.dyn_cast<EvaluatedStmt *>()) {
Eval->~EvaluatedStmt();
getASTContext().Deallocate(Eval);
}
Init = I;
}
bool VarDecl::mightBeUsableInConstantExpressions(const ASTContext &C) const {
const LangOptions &Lang = C.getLangOpts();
if (!Lang.CPlusPlus && !Lang.OpenCL)
return false;
if (isa<ParmVarDecl>(this))
return false;
if (isWeak())
return false;
if (Lang.CPlusPlus11 && getType()->isReferenceType())
return true;
if (!getType().isConstant(C) || getType().isVolatileQualified())
return false;
if (getType()->isIntegralOrEnumerationType())
return true;
return Lang.CPlusPlus11 && isConstexpr();
}
bool VarDecl::isUsableInConstantExpressions(const ASTContext &Context) const {
const VarDecl *DefVD = nullptr;
const Expr *Init = getAnyInitializer(DefVD);
if (!Init || Init->isValueDependent() || getType()->isDependentType())
return false;
if (!DefVD->mightBeUsableInConstantExpressions(Context))
return false;
if (Context.getLangOpts().CPlusPlus && !DefVD->hasConstantInitialization())
return false;
if ((Context.getLangOpts().CPlusPlus || Context.getLangOpts().OpenCL) &&
!Context.getLangOpts().CPlusPlus11 && !DefVD->hasICEInitializer(Context))
return false;
return true;
}
EvaluatedStmt *VarDecl::ensureEvaluatedStmt() const {
auto *Eval = Init.dyn_cast<EvaluatedStmt *>();
if (!Eval) {
Eval = new (getASTContext()) EvaluatedStmt;
Eval->Value = Init.get<Stmt *>();
Init = Eval;
}
return Eval;
}
EvaluatedStmt *VarDecl::getEvaluatedStmt() const {
return Init.dyn_cast<EvaluatedStmt *>();
}
APValue *VarDecl::evaluateValue() const {
SmallVector<PartialDiagnosticAt, 8> Notes;
return evaluateValueImpl(Notes, hasConstantInitialization());
}
APValue *VarDecl::evaluateValueImpl(SmallVectorImpl<PartialDiagnosticAt> &Notes,
bool IsConstantInitialization) const {
EvaluatedStmt *Eval = ensureEvaluatedStmt();
const auto *Init = cast<Expr>(Eval->Value);
assert(!Init->isValueDependent());
if (Eval->WasEvaluated)
return Eval->Evaluated.isAbsent() ? nullptr : &Eval->Evaluated;
if (Eval->IsEvaluating) {
return nullptr;
}
Eval->IsEvaluating = true;
ASTContext &Ctx = getASTContext();
bool Result = Init->EvaluateAsInitializer(Eval->Evaluated, Ctx, this, Notes,
IsConstantInitialization);
if (IsConstantInitialization && Ctx.getLangOpts().CPlusPlus11 &&
!Notes.empty())
Result = false;
if (!Result)
Eval->Evaluated = APValue();
else if (Eval->Evaluated.needsCleanup())
Ctx.addDestruction(&Eval->Evaluated);
Eval->IsEvaluating = false;
Eval->WasEvaluated = true;
return Result ? &Eval->Evaluated : nullptr;
}
APValue *VarDecl::getEvaluatedValue() const {
if (EvaluatedStmt *Eval = getEvaluatedStmt())
if (Eval->WasEvaluated)
return &Eval->Evaluated;
return nullptr;
}
bool VarDecl::hasICEInitializer(const ASTContext &Context) const {
const Expr *Init = getInit();
assert(Init && "no initializer");
EvaluatedStmt *Eval = ensureEvaluatedStmt();
if (!Eval->CheckedForICEInit) {
Eval->CheckedForICEInit = true;
Eval->HasICEInit = Init->isIntegerConstantExpr(Context);
}
return Eval->HasICEInit;
}
bool VarDecl::hasConstantInitialization() const {
if (hasGlobalStorage() && !getASTContext().getLangOpts().CPlusPlus)
return true;
if (EvaluatedStmt *Eval = getEvaluatedStmt())
return Eval->HasConstantInitialization;
return false;
}
bool VarDecl::checkForConstantInitialization(
SmallVectorImpl<PartialDiagnosticAt> &Notes) const {
EvaluatedStmt *Eval = ensureEvaluatedStmt();
assert(!Eval->WasEvaluated &&
"already evaluated var value before checking for constant init");
assert(getASTContext().getLangOpts().CPlusPlus && "only meaningful in C++");
assert(!cast<Expr>(Eval->Value)->isValueDependent());
Eval->HasConstantInitialization =
evaluateValueImpl(Notes, true) && Notes.empty();
if (!Eval->HasConstantInitialization)
Eval->WasEvaluated = false;
return Eval->HasConstantInitialization;
}
bool VarDecl::isParameterPack() const {
return isa<PackExpansionType>(getType());
}
template<typename DeclT>
static DeclT *getDefinitionOrSelf(DeclT *D) {
assert(D);
if (auto *Def = D->getDefinition())
return Def;
return D;
}
bool VarDecl::isEscapingByref() const {
return hasAttr<BlocksAttr>() && NonParmVarDeclBits.EscapingByref;
}
bool VarDecl::isNonEscapingByref() const {
return hasAttr<BlocksAttr>() && !NonParmVarDeclBits.EscapingByref;
}
bool VarDecl::hasDependentAlignment() const {
QualType T = getType();
return T->isDependentType() || T->isUndeducedAutoType() ||
llvm::any_of(specific_attrs<AlignedAttr>(), [](const AlignedAttr *AA) {
return AA->isAlignmentDependent();
});
}
VarDecl *VarDecl::getTemplateInstantiationPattern() const {
const VarDecl *VD = this;
if (MemberSpecializationInfo *MSInfo = VD->getMemberSpecializationInfo()) {
if (isTemplateInstantiation(MSInfo->getTemplateSpecializationKind())) {
VD = VD->getInstantiatedFromStaticDataMember();
while (auto *NewVD = VD->getInstantiatedFromStaticDataMember())
VD = NewVD;
}
}
if (auto *VDTemplSpec = dyn_cast<VarTemplateSpecializationDecl>(VD)) {
if (isTemplateInstantiation(VDTemplSpec->getTemplateSpecializationKind())) {
auto From = VDTemplSpec->getInstantiatedFrom();
if (auto *VTD = From.dyn_cast<VarTemplateDecl *>()) {
while (!VTD->isMemberSpecialization()) {
auto *NewVTD = VTD->getInstantiatedFromMemberTemplate();
if (!NewVTD)
break;
VTD = NewVTD;
}
return getDefinitionOrSelf(VTD->getTemplatedDecl());
}
if (auto *VTPSD =
From.dyn_cast<VarTemplatePartialSpecializationDecl *>()) {
while (!VTPSD->isMemberSpecialization()) {
auto *NewVTPSD = VTPSD->getInstantiatedFromMember();
if (!NewVTPSD)
break;
VTPSD = NewVTPSD;
}
return getDefinitionOrSelf<VarDecl>(VTPSD);
}
}
}
if (VarTemplateDecl *VarTemplate = VD->getDescribedVarTemplate()) {
while (!VarTemplate->isMemberSpecialization()) {
auto *NewVT = VarTemplate->getInstantiatedFromMemberTemplate();
if (!NewVT)
break;
VarTemplate = NewVT;
}
return getDefinitionOrSelf(VarTemplate->getTemplatedDecl());
}
if (VD == this)
return nullptr;
return getDefinitionOrSelf(const_cast<VarDecl*>(VD));
}
VarDecl *VarDecl::getInstantiatedFromStaticDataMember() const {
if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo())
return cast<VarDecl>(MSI->getInstantiatedFrom());
return nullptr;
}
TemplateSpecializationKind VarDecl::getTemplateSpecializationKind() const {
if (const auto *Spec = dyn_cast<VarTemplateSpecializationDecl>(this))
return Spec->getSpecializationKind();
if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo())
return MSI->getTemplateSpecializationKind();
return TSK_Undeclared;
}
TemplateSpecializationKind
VarDecl::getTemplateSpecializationKindForInstantiation() const {
if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo())
return MSI->getTemplateSpecializationKind();
if (const auto *Spec = dyn_cast<VarTemplateSpecializationDecl>(this))
return Spec->getSpecializationKind();
return TSK_Undeclared;
}
SourceLocation VarDecl::getPointOfInstantiation() const {
if (const auto *Spec = dyn_cast<VarTemplateSpecializationDecl>(this))
return Spec->getPointOfInstantiation();
if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo())
return MSI->getPointOfInstantiation();
return SourceLocation();
}
VarTemplateDecl *VarDecl::getDescribedVarTemplate() const {
return getASTContext().getTemplateOrSpecializationInfo(this)
.dyn_cast<VarTemplateDecl *>();
}
void VarDecl::setDescribedVarTemplate(VarTemplateDecl *Template) {
getASTContext().setTemplateOrSpecializationInfo(this, Template);
}
bool VarDecl::isKnownToBeDefined() const {
const auto &LangOpts = getASTContext().getLangOpts();
if (LangOpts.CUDA && !LangOpts.GPURelocatableDeviceCode &&
hasExternalStorage() && hasAttr<CUDASharedAttr>() &&
isa<IncompleteArrayType>(getType()))
return true;
return hasDefinition();
}
bool VarDecl::isNoDestroy(const ASTContext &Ctx) const {
return hasGlobalStorage() && (hasAttr<NoDestroyAttr>() ||
(!Ctx.getLangOpts().RegisterStaticDestructors &&
!hasAttr<AlwaysDestroyAttr>()));
}
QualType::DestructionKind
VarDecl::needsDestruction(const ASTContext &Ctx) const {
if (EvaluatedStmt *Eval = getEvaluatedStmt())
if (Eval->HasConstantDestruction)
return QualType::DK_none;
if (isNoDestroy(Ctx))
return QualType::DK_none;
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)
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())
return getASTContext().getTemplateOrSpecializationInfo(this)
.dyn_cast<MemberSpecializationInfo *>();
return nullptr;
}
void VarDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK,
SourceLocation PointOfInstantiation) {
assert((isa<VarTemplateSpecializationDecl>(this) ||
getMemberSpecializationInfo()) &&
"not a variable or static data member template specialization");
if (VarTemplateSpecializationDecl *Spec =
dyn_cast<VarTemplateSpecializationDecl>(this)) {
Spec->setSpecializationKind(TSK);
if (TSK != TSK_ExplicitSpecialization &&
PointOfInstantiation.isValid() &&
Spec->getPointOfInstantiation().isInvalid()) {
Spec->setPointOfInstantiation(PointOfInstantiation);
if (ASTMutationListener *L = getASTContext().getASTMutationListener())
L->InstantiationRequested(this);
}
} else if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo()) {
MSI->setTemplateSpecializationKind(TSK);
if (TSK != TSK_ExplicitSpecialization && PointOfInstantiation.isValid() &&
MSI->getPointOfInstantiation().isInvalid()) {
MSI->setPointOfInstantiation(PointOfInstantiation);
if (ASTMutationListener *L = getASTContext().getASTMutationListener())
L->InstantiationRequested(this);
}
}
}
void
VarDecl::setInstantiationOfStaticDataMember(VarDecl *VD,
TemplateSpecializationKind TSK) {
assert(getASTContext().getTemplateOrSpecializationInfo(this).isNull() &&
"Previous template or instantiation?");
getASTContext().setInstantiatedFromStaticDataMember(this, VD, TSK);
}
ParmVarDecl *ParmVarDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation StartLoc,
SourceLocation IdLoc, IdentifierInfo *Id,
QualType T, TypeSourceInfo *TInfo,
StorageClass S, Expr *DefArg) {
return new (C, DC) ParmVarDecl(ParmVar, C, DC, StartLoc, IdLoc, Id, T, TInfo,
S, DefArg);
}
QualType ParmVarDecl::getOriginalType() const {
TypeSourceInfo *TSI = getTypeSourceInfo();
QualType T = TSI ? TSI->getType() : getType();
if (const auto *DT = dyn_cast<DecayedType>(T))
return DT->getOriginalType();
return T;
}
ParmVarDecl *ParmVarDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
return new (C, ID)
ParmVarDecl(ParmVar, C, nullptr, SourceLocation(), SourceLocation(),
nullptr, QualType(), nullptr, SC_None, nullptr);
}
SourceRange ParmVarDecl::getSourceRange() const {
if (!hasInheritedDefaultArg()) {
SourceRange ArgRange = getDefaultArgRange();
if (ArgRange.isValid())
return SourceRange(getOuterLocStart(), ArgRange.getEnd());
}
if (isa<ObjCMethodDecl>(getDeclContext()))
return SourceRange(DeclaratorDecl::getBeginLoc(), getLocation());
return DeclaratorDecl::getSourceRange();
}
bool ParmVarDecl::isDestroyedInCallee() const {
if (hasAttr<NSConsumedAttr>())
return getASTContext().getLangOpts().ObjCAutoRefCount;
auto *RT = getType()->getAs<RecordType>();
if (RT && RT->getDecl()->isParamDestroyedInCallee() &&
getType().isDestructedType())
return true;
return false;
}
Expr *ParmVarDecl::getDefaultArg() {
assert(!hasUnparsedDefaultArg() && "Default argument is not yet parsed!");
assert(!hasUninstantiatedDefaultArg() &&
"Default argument is not yet instantiated!");
Expr *Arg = getInit();
if (auto *E = dyn_cast_or_null<FullExpr>(Arg))
if (!isa<ConstantExpr>(E))
return E->getSubExpr();
return Arg;
}
void ParmVarDecl::setDefaultArg(Expr *defarg) {
ParmVarDeclBits.DefaultArgKind = DAK_Normal;
Init = defarg;
}
SourceRange ParmVarDecl::getDefaultArgRange() const {
switch (ParmVarDeclBits.DefaultArgKind) {
case DAK_None:
case DAK_Unparsed:
return SourceRange();
case DAK_Uninstantiated:
return getUninstantiatedDefaultArg()->getSourceRange();
case DAK_Normal:
if (const Expr *E = getInit())
return E->getSourceRange();
return SourceRange();
}
llvm_unreachable("Invalid default argument kind.");
}
void ParmVarDecl::setUninstantiatedDefaultArg(Expr *arg) {
ParmVarDeclBits.DefaultArgKind = DAK_Uninstantiated;
Init = arg;
}
Expr *ParmVarDecl::getUninstantiatedDefaultArg() {
assert(hasUninstantiatedDefaultArg() &&
"Wrong kind of initialization expression!");
return cast_or_null<Expr>(Init.get<Stmt *>());
}
bool ParmVarDecl::hasDefaultArg() const {
return hasUnparsedDefaultArg() || hasUninstantiatedDefaultArg() ||
!Init.isNull();
}
void ParmVarDecl::setParameterIndexLarge(unsigned parameterIndex) {
getASTContext().setParameterIndex(this, parameterIndex);
ParmVarDeclBits.ParameterIndex = ParameterIndexSentinel;
}
unsigned ParmVarDecl::getParameterIndexLarge() const {
return getASTContext().getParameterIndex(this);
}
FunctionDecl::FunctionDecl(Kind DK, ASTContext &C, DeclContext *DC,
SourceLocation StartLoc,
const DeclarationNameInfo &NameInfo, QualType T,
TypeSourceInfo *TInfo, StorageClass S,
bool UsesFPIntrin, bool isInlineSpecified,
ConstexprSpecKind ConstexprKind,
Expr *TrailingRequiresClause)
: DeclaratorDecl(DK, DC, NameInfo.getLoc(), NameInfo.getName(), T, TInfo,
StartLoc),
DeclContext(DK), redeclarable_base(C), Body(), ODRHash(0),
EndRangeLoc(NameInfo.getEndLoc()), DNLoc(NameInfo.getInfo()) {
assert(T.isNull() || T->isFunctionType());
FunctionDeclBits.SClass = S;
FunctionDeclBits.IsInline = isInlineSpecified;
FunctionDeclBits.IsInlineSpecified = isInlineSpecified;
FunctionDeclBits.IsVirtualAsWritten = false;
FunctionDeclBits.IsPure = false;
FunctionDeclBits.HasInheritedPrototype = false;
FunctionDeclBits.HasWrittenPrototype = true;
FunctionDeclBits.IsDeleted = false;
FunctionDeclBits.IsTrivial = false;
FunctionDeclBits.IsTrivialForCall = false;
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.InstantiationIsPending = false;
FunctionDeclBits.UsesSEHTry = false;
FunctionDeclBits.UsesFPIntrin = UsesFPIntrin;
FunctionDeclBits.HasSkippedBody = false;
FunctionDeclBits.WillHaveBody = false;
FunctionDeclBits.IsMultiVersion = false;
FunctionDeclBits.IsCopyDeductionCandidate = false;
FunctionDeclBits.HasODRHash = false;
if (TrailingRequiresClause)
setTrailingRequiresClause(TrailingRequiresClause);
}
void FunctionDecl::getNameForDiagnostic(
raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const {
NamedDecl::getNameForDiagnostic(OS, Policy, Qualified);
const TemplateArgumentList *TemplateArgs = getTemplateSpecializationArgs();
if (TemplateArgs)
printTemplateArgumentList(OS, TemplateArgs->asArray(), Policy);
}
bool FunctionDecl::isVariadic() const {
if (const auto *FT = getType()->getAs<FunctionProtoType>())
return FT->isVariadic();
return false;
}
FunctionDecl::DefaultedFunctionInfo *
FunctionDecl::DefaultedFunctionInfo::Create(ASTContext &Context,
ArrayRef<DeclAccessPair> Lookups) {
DefaultedFunctionInfo *Info = new (Context.Allocate(
totalSizeToAlloc<DeclAccessPair>(Lookups.size()),
std::max(alignof(DefaultedFunctionInfo), alignof(DeclAccessPair))))
DefaultedFunctionInfo;
Info->NumLookups = Lookups.size();
std::uninitialized_copy(Lookups.begin(), Lookups.end(),
Info->getTrailingObjects<DeclAccessPair>());
return Info;
}
void FunctionDecl::setDefaultedFunctionInfo(DefaultedFunctionInfo *Info) {
assert(!FunctionDeclBits.HasDefaultedFunctionInfo && "already have this");
assert(!Body && "can't replace function body with defaulted function info");
FunctionDeclBits.HasDefaultedFunctionInfo = true;
DefaultedInfo = Info;
}
FunctionDecl::DefaultedFunctionInfo *
FunctionDecl::getDefaultedFunctionInfo() const {
return FunctionDeclBits.HasDefaultedFunctionInfo ? DefaultedInfo : nullptr;
}
bool FunctionDecl::hasBody(const FunctionDecl *&Definition) const {
for (auto I : redecls()) {
if (I->doesThisDeclarationHaveABody()) {
Definition = I;
return true;
}
}
return false;
}
bool FunctionDecl::hasTrivialBody() const {
Stmt *S = getBody();
if (!S) {
return false;
}
if (isa<CompoundStmt>(S) && cast<CompoundStmt>(S)->body_empty())
return true;
return false;
}
bool FunctionDecl::isThisDeclarationInstantiatedFromAFriendDefinition() const {
if (!getFriendObjectKind())
return false;
if (const FunctionDecl *InstantiatedFrom =
getInstantiatedFromMemberFunction())
return InstantiatedFrom->getFriendObjectKind() &&
InstantiatedFrom->isThisDeclarationADefinition();
if (const FunctionTemplateDecl *Template = getDescribedFunctionTemplate()) {
if (const FunctionTemplateDecl *InstantiatedFrom =
Template->getInstantiatedFromMemberTemplate())
return InstantiatedFrom->getFriendObjectKind() &&
InstantiatedFrom->isThisDeclarationADefinition();
}
return false;
}
bool FunctionDecl::isDefined(const FunctionDecl *&Definition,
bool CheckForPendingFriendDefinition) const {
for (const FunctionDecl *FD : redecls()) {
if (FD->isThisDeclarationADefinition()) {
Definition = FD;
return true;
}
if (CheckForPendingFriendDefinition &&
FD->isThisDeclarationInstantiatedFromAFriendDefinition()) {
Definition = FD;
return true;
}
}
return false;
}
Stmt *FunctionDecl::getBody(const FunctionDecl *&Definition) const {
if (!hasBody(Definition))
return nullptr;
assert(!Definition->FunctionDeclBits.HasDefaultedFunctionInfo &&
"definition should not have a body");
if (Definition->Body)
return Definition->Body.get(getASTContext().getExternalSource());
return nullptr;
}
void FunctionDecl::setBody(Stmt *B) {
FunctionDeclBits.HasDefaultedFunctionInfo = false;
Body = LazyDeclStmtPtr(B);
if (B)
EndRangeLoc = B->getEndLoc();
}
void FunctionDecl::setPure(bool P) {
FunctionDeclBits.IsPure = P;
if (P)
if (auto *Parent = dyn_cast<CXXRecordDecl>(getDeclContext()))
Parent->markedVirtualFunctionPure();
}
template<std::size_t Len>
static bool isNamed(const NamedDecl *ND, const char (&Str)[Len]) {
IdentifierInfo *II = ND->getIdentifier();
return II && II->isStr(Str);
}
bool FunctionDecl::isMain() const {
const TranslationUnitDecl *tunit =
dyn_cast<TranslationUnitDecl>(getDeclContext()->getRedeclContext());
return tunit &&
!tunit->getASTContext().getLangOpts().Freestanding &&
isNamed(this, "main");
}
bool FunctionDecl::isMSVCRTEntryPoint() const {
const TranslationUnitDecl *TUnit =
dyn_cast<TranslationUnitDecl>(getDeclContext()->getRedeclContext());
if (!TUnit)
return false;
if (!TUnit->getASTContext().getTargetInfo().getTriple().isOSMSVCRT())
return false;
if (!getIdentifier())
return false;
return llvm::StringSwitch<bool>(getName())
.Cases("main", "wmain", "WinMain", "wWinMain", "DllMain", true)
.Default(false);
}
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 (!getDeclContext()->getRedeclContext()->isTranslationUnit())
return false;
const auto *proto = getType()->castAs<FunctionProtoType>();
if (proto->getNumParams() != 2 || proto->isVariadic())
return false;
ASTContext &Context =
cast<TranslationUnitDecl>(getDeclContext()->getRedeclContext())
->getASTContext();
return (proto->getParamType(1).getCanonicalType() == Context.VoidPtrTy);
}
bool FunctionDecl::isReplaceableGlobalAllocationFunction(
Optional<unsigned> *AlignmentParam, bool *IsNothrow) const {
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 (isa<CXXRecordDecl>(getDeclContext()))
return false;
if (!getDeclContext()->getRedeclContext()->isTranslationUnit())
return false;
const auto *FPT = getType()->castAs<FunctionProtoType>();
if (FPT->getNumParams() == 0 || FPT->getNumParams() > 3 || FPT->isVariadic())
return false;
if (FPT->getNumParams() == 1)
return true;
unsigned Params = 1;
QualType Ty = FPT->getParamType(Params);
ASTContext &Ctx = getASTContext();
auto Consume = [&] {
++Params;
Ty = Params < FPT->getNumParams() ? FPT->getParamType(Params) : QualType();
};
bool IsSizedDelete = false;
if (Ctx.getLangOpts().SizedDeallocation &&
(getDeclName().getCXXOverloadedOperator() == OO_Delete ||
getDeclName().getCXXOverloadedOperator() == OO_Array_Delete) &&
Ctx.hasSameType(Ty, Ctx.getSizeType())) {
IsSizedDelete = true;
Consume();
}
if (Ctx.getLangOpts().AlignedAllocation && !Ty.isNull() && Ty->isAlignValT()) {
Consume();
if (AlignmentParam)
*AlignmentParam = Params;
}
if (!IsSizedDelete && !Ty.isNull() && Ty->isReferenceType()) {
Ty = Ty->getPointeeType();
if (Ty.getCVRQualifiers() != Qualifiers::Const)
return false;
if (Ty->isNothrowT()) {
if (IsNothrow)
*IsNothrow = true;
Consume();
}
}
return Params == FPT->getNumParams();
}
bool FunctionDecl::isInlineBuiltinDeclaration() const {
if (!getBuiltinID())
return false;
const FunctionDecl *Definition;
return hasBody(Definition) && Definition->isInlineSpecified() &&
Definition->hasAttr<AlwaysInlineAttr>() &&
Definition->hasAttr<GNUInlineAttr>();
}
bool FunctionDecl::isDestroyingOperatorDelete() const {
if (!isa<CXXMethodDecl>(this) || getOverloadedOperator() != OO_Delete ||
getNumParams() < 2)
return false;
auto *RD = getParamDecl(1)->getType()->getAsCXXRecordDecl();
return RD && RD->isInStdNamespace() && RD->getIdentifier() &&
RD->getIdentifier()->isStr("destroying_delete_t");
}
LanguageLinkage FunctionDecl::getLanguageLinkage() const {
return getDeclLanguageLinkage(*this);
}
bool FunctionDecl::isExternC() const {
return isDeclExternC(*this);
}
bool FunctionDecl::isInExternCContext() const {
if (hasAttr<OpenCLKernelAttr>())
return true;
return getLexicalDeclContext()->isExternCContext();
}
bool FunctionDecl::isInExternCXXContext() const {
return getLexicalDeclContext()->isExternCXXContext();
}
bool FunctionDecl::isGlobal() const {
if (const auto *Method = dyn_cast<CXXMethodDecl>(this))
return Method->isStatic();
if (getCanonicalDecl()->getStorageClass() == SC_Static)
return false;
for (const DeclContext *DC = getDeclContext();
DC->isNamespace();
DC = DC->getParent()) {
if (const auto *Namespace = cast<NamespaceDecl>(DC)) {
if (!Namespace->getDeclName())
return false;
}
}
return true;
}
bool FunctionDecl::isNoReturn() const {
if (hasAttr<NoReturnAttr>() || hasAttr<CXX11NoReturnAttr>() ||
hasAttr<C11NoReturnAttr>())
return true;
if (auto *FnTy = getType()->getAs<FunctionType>())
return FnTy->getNoReturnAttr();
return false;
}
MultiVersionKind FunctionDecl::getMultiVersionKind() const {
if (hasAttr<TargetAttr>())
return MultiVersionKind::Target;
if (hasAttr<CPUDispatchAttr>())
return MultiVersionKind::CPUDispatch;
if (hasAttr<CPUSpecificAttr>())
return MultiVersionKind::CPUSpecific;
if (hasAttr<TargetClonesAttr>())
return MultiVersionKind::TargetClones;
return MultiVersionKind::None;
}
bool FunctionDecl::isCPUDispatchMultiVersion() const {
return isMultiVersion() && hasAttr<CPUDispatchAttr>();
}
bool FunctionDecl::isCPUSpecificMultiVersion() const {
return isMultiVersion() && hasAttr<CPUSpecificAttr>();
}
bool FunctionDecl::isTargetMultiVersion() const {
return isMultiVersion() && hasAttr<TargetAttr>();
}
bool FunctionDecl::isTargetClonesMultiVersion() const {
return isMultiVersion() && hasAttr<TargetClonesAttr>();
}
void
FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) {
redeclarable_base::setPreviousDecl(PrevDecl);
if (FunctionTemplateDecl *FunTmpl = getDescribedFunctionTemplate()) {
FunctionTemplateDecl *PrevFunTmpl
= PrevDecl? PrevDecl->getDescribedFunctionTemplate() : nullptr;
assert((!PrevDecl || PrevFunTmpl) && "Function/function template mismatch");
FunTmpl->setPreviousDecl(PrevFunTmpl);
}
if (PrevDecl && PrevDecl->isInlined())
setImplicitlyInline(true);
}
FunctionDecl *FunctionDecl::getCanonicalDecl() { return getFirstDecl(); }
unsigned FunctionDecl::getBuiltinID(bool ConsiderWrapperFunctions) const {
unsigned BuiltinID = 0;
if (const auto *ABAA = getAttr<ArmBuiltinAliasAttr>()) {
BuiltinID = ABAA->getBuiltinName()->getBuiltinID();
} else if (const auto *BAA = getAttr<BuiltinAliasAttr>()) {
BuiltinID = BAA->getBuiltinName()->getBuiltinID();
} else if (const auto *A = getAttr<BuiltinAttr>()) {
BuiltinID = A->getID();
}
if (!BuiltinID)
return 0;
if (!ConsiderWrapperFunctions && hasAttr<OverloadableAttr>() &&
(!hasAttr<ArmBuiltinAliasAttr>() && !hasAttr<BuiltinAliasAttr>()))
return 0;
ASTContext &Context = getASTContext();
if (!Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID))
return BuiltinID;
if (!ConsiderWrapperFunctions && getStorageClass() == SC_Static)
return 0;
if (Context.getLangOpts().OpenCL &&
Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID))
return 0;
if (Context.getLangOpts().CUDA && hasAttr<CUDADeviceAttr>() &&
!hasAttr<CUDAHostAttr>() &&
!(BuiltinID == Builtin::BIprintf || BuiltinID == Builtin::BImalloc))
return 0;
if (Context.getTargetInfo().getTriple().isAMDGCN() &&
Context.getLangOpts().OpenMPIsDevice &&
Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID) &&
!(BuiltinID == Builtin::BIprintf || BuiltinID == Builtin::BImalloc))
return 0;
return BuiltinID;
}
unsigned FunctionDecl::getNumParams() const {
const auto *FPT = getType()->getAs<FunctionProtoType>();
return FPT ? FPT->getNumParams() : 0;
}
void FunctionDecl::setParams(ASTContext &C,
ArrayRef<ParmVarDecl *> NewParamInfo) {
assert(!ParamInfo && "Already has param info!");
assert(NewParamInfo.size() == getNumParams() && "Parameter count mismatch!");
if (!NewParamInfo.empty()) {
ParamInfo = new (C) ParmVarDecl*[NewParamInfo.size()];
std::copy(NewParamInfo.begin(), NewParamInfo.end(), ParamInfo);
}
}
unsigned FunctionDecl::getMinRequiredArguments() const {
if (!getASTContext().getLangOpts().CPlusPlus)
return getNumParams();
unsigned NumRequiredArgs = 0;
unsigned MinParamsSoFar = 0;
for (auto *Param : parameters()) {
if (!Param->isParameterPack()) {
++MinParamsSoFar;
if (!Param->hasDefaultArg())
NumRequiredArgs = MinParamsSoFar;
}
}
return NumRequiredArgs;
}
bool FunctionDecl::hasOneParamOrDefaultArgs() const {
return getNumParams() == 1 ||
(getNumParams() > 1 &&
std::all_of(param_begin() + 1, param_end(),
[](ParmVarDecl *P) { return P->hasDefaultArg(); }));
}
bool FunctionDecl::isMSExternInline() const {
assert(isInlined() && "expected to get called on an inlined function!");
const ASTContext &Context = getASTContext();
if (!Context.getTargetInfo().getCXXABI().isMicrosoft() &&
!hasAttr<DLLExportAttr>())
return false;
for (const FunctionDecl *FD = getMostRecentDecl(); FD;
FD = FD->getPreviousDecl())
if (!FD->isImplicit() && FD->getStorageClass() == SC_Extern)
return true;
return false;
}
static bool redeclForcesDefMSVC(const FunctionDecl *Redecl) {
if (Redecl->getStorageClass() != SC_Extern)
return false;
for (const FunctionDecl *FD = Redecl->getPreviousDecl(); FD;
FD = FD->getPreviousDecl())
if (!FD->isImplicit() && FD->getStorageClass() == SC_Extern)
return false;
return true;
}
static bool RedeclForcesDefC99(const FunctionDecl *Redecl) {
if (!Redecl->getLexicalDeclContext()->isTranslationUnit())
return false;
if (Redecl->isImplicit())
return false;
if (!Redecl->isInlineSpecified() || Redecl->getStorageClass() == SC_Extern)
return true;
return false;
}
bool FunctionDecl::doesDeclarationForceExternallyVisibleDefinition() const {
assert(!doesThisDeclarationHaveABody() &&
"Must have a declaration without a body.");
ASTContext &Context = getASTContext();
if (Context.getLangOpts().MSVCCompat) {
const FunctionDecl *Definition;
if (hasBody(Definition) && Definition->isInlined() &&
redeclForcesDefMSVC(this))
return true;
}
if (Context.getLangOpts().CPlusPlus)
return false;
if (Context.getLangOpts().GNUInline || hasAttr<GNUInlineAttr>()) {
if (!isInlineSpecified() || getStorageClass() == SC_Extern)
return false;
const FunctionDecl *Prev = this;
bool FoundBody = false;
while ((Prev = Prev->getPreviousDecl())) {
FoundBody |= Prev->doesThisDeclarationHaveABody();
if (Prev->doesThisDeclarationHaveABody()) {
if (!Prev->isInlineSpecified() ||
Prev->getStorageClass() != SC_Extern)
return false;
} else if (Prev->isInlineSpecified() &&
Prev->getStorageClass() != SC_Extern) {
return false;
}
}
return FoundBody;
}
if (isInlineSpecified() && getStorageClass() != SC_Extern)
return false;
const FunctionDecl *Prev = this;
bool FoundBody = false;
while ((Prev = Prev->getPreviousDecl())) {
FoundBody |= Prev->doesThisDeclarationHaveABody();
if (RedeclForcesDefC99(Prev))
return false;
}
return FoundBody;
}
FunctionTypeLoc FunctionDecl::getFunctionTypeLoc() const {
const TypeSourceInfo *TSI = getTypeSourceInfo();
return TSI ? TSI->getTypeLoc().IgnoreParens().getAs<FunctionTypeLoc>()
: FunctionTypeLoc();
}
SourceRange FunctionDecl::getReturnTypeSourceRange() const {
FunctionTypeLoc FTL = getFunctionTypeLoc();
if (!FTL)
return SourceRange();
const SourceManager &SM = getASTContext().getSourceManager();
SourceRange RTRange = FTL.getReturnLoc().getSourceRange();
SourceLocation Boundary = getNameInfo().getBeginLoc();
if (RTRange.isInvalid() || Boundary.isInvalid() ||
!SM.isBeforeInTranslationUnit(RTRange.getEnd(), Boundary))
return SourceRange();
return RTRange;
}
SourceRange FunctionDecl::getParametersSourceRange() const {
unsigned NP = getNumParams();
SourceLocation EllipsisLoc = getEllipsisLoc();
if (NP == 0 && EllipsisLoc.isInvalid())
return SourceRange();
SourceLocation Begin =
NP > 0 ? ParamInfo[0]->getSourceRange().getBegin() : EllipsisLoc;
SourceLocation End = EllipsisLoc.isValid()
? EllipsisLoc
: ParamInfo[NP - 1]->getSourceRange().getEnd();
return SourceRange(Begin, End);
}
SourceRange FunctionDecl::getExceptionSpecSourceRange() const {
FunctionTypeLoc FTL = getFunctionTypeLoc();
return FTL ? FTL.getExceptionSpecRange() : SourceRange();
}
bool FunctionDecl::isInlineDefinitionExternallyVisible() const {
assert((doesThisDeclarationHaveABody() || willHaveBody() ||
hasAttr<AliasAttr>()) &&
"Must be a function definition");
assert(isInlined() && "Function must be inline");
ASTContext &Context = getASTContext();
if (Context.getLangOpts().GNUInline || hasAttr<GNUInlineAttr>()) {
if (Context.getLangOpts().CPlusPlus)
return false;
if (!(isInlineSpecified() && getStorageClass() == SC_Extern))
return true;
for (auto Redecl : redecls()) {
if (Redecl->isInlineSpecified() &&
Redecl->getStorageClass() != SC_Extern)
return true;
}
return false;
}
assert(!Context.getLangOpts().CPlusPlus &&
"should not use C inline rules in C++");
for (auto Redecl : redecls()) {
if (RedeclForcesDefC99(Redecl))
return true;
}
return false;
}
OverloadedOperatorKind FunctionDecl::getOverloadedOperator() const {
if (getDeclName().getNameKind() == DeclarationName::CXXOperatorName)
return getDeclName().getCXXOverloadedOperator();
return OO_None;
}
const IdentifierInfo *FunctionDecl::getLiteralIdentifier() const {
if (getDeclName().getNameKind() == DeclarationName::CXXLiteralOperatorName)
return getDeclName().getCXXLiteralIdentifier();
return nullptr;
}
FunctionDecl::TemplatedKind FunctionDecl::getTemplatedKind() const {
if (TemplateOrSpecialization.isNull())
return TK_NonTemplate;
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 *>())
return TK_FunctionTemplateSpecialization;
if (TemplateOrSpecialization.is
<DependentFunctionTemplateSpecializationInfo*>())
return TK_DependentFunctionTemplateSpecialization;
llvm_unreachable("Did we miss a TemplateOrSpecialization type?");
}
FunctionDecl *FunctionDecl::getInstantiatedFromMemberFunction() const {
if (MemberSpecializationInfo *Info = getMemberSpecializationInfo())
return cast<FunctionDecl>(Info->getInstantiatedFrom());
return nullptr;
}
MemberSpecializationInfo *FunctionDecl::getMemberSpecializationInfo() const {
if (auto *MSI =
TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo *>())
return MSI;
if (auto *FTSI = TemplateOrSpecialization
.dyn_cast<FunctionTemplateSpecializationInfo *>())
return FTSI->getMemberSpecializationInfo();
return nullptr;
}
void
FunctionDecl::setInstantiationOfMemberFunction(ASTContext &C,
FunctionDecl *FD,
TemplateSpecializationKind TSK) {
assert(TemplateOrSpecialization.isNull() &&
"Member function is already a specialization");
MemberSpecializationInfo *Info
= new (C) MemberSpecializationInfo(FD, TSK);
TemplateOrSpecialization = Info;
}
FunctionTemplateDecl *FunctionDecl::getDescribedFunctionTemplate() const {
return dyn_cast_or_null<FunctionTemplateDecl>(
TemplateOrSpecialization.dyn_cast<NamedDecl *>());
}
void FunctionDecl::setDescribedFunctionTemplate(
FunctionTemplateDecl *Template) {
assert(TemplateOrSpecialization.isNull() &&
"Member function is already a specialization");
TemplateOrSpecialization = Template;
}
void FunctionDecl::setInstantiatedFromDecl(FunctionDecl *FD) {
assert(TemplateOrSpecialization.isNull() &&
"Function is already a specialization");
TemplateOrSpecialization = FD;
}
FunctionDecl *FunctionDecl::getInstantiatedFromDecl() const {
return dyn_cast_or_null<FunctionDecl>(
TemplateOrSpecialization.dyn_cast<NamedDecl *>());
}
bool FunctionDecl::isImplicitlyInstantiable() const {
if (isInvalidDecl())
return false;
switch (getTemplateSpecializationKindForInstantiation()) {
case TSK_Undeclared:
case TSK_ExplicitInstantiationDefinition:
case TSK_ExplicitSpecialization:
return false;
case TSK_ImplicitInstantiation:
return true;
case TSK_ExplicitInstantiationDeclaration:
break;
}
const FunctionDecl *PatternDecl = getTemplateInstantiationPattern();
bool HasPattern = false;
if (PatternDecl)
HasPattern = PatternDecl->hasBody(PatternDecl);
if (!HasPattern || !PatternDecl)
return true;
return PatternDecl->isInlined();
}
bool FunctionDecl::isTemplateInstantiation() const {
return clang::isTemplateInstantiation(getTemplateSpecializationKind());
}
FunctionDecl *
FunctionDecl::getTemplateInstantiationPattern(bool ForDefinition) const {
if (isGenericLambdaCallOperatorSpecialization(
dyn_cast<CXXMethodDecl>(this))) {
assert(getPrimaryTemplate() && "not a generic lambda call operator?");
return getDefinitionOrSelf(getPrimaryTemplate()->getTemplatedDecl());
}
const FunctionDecl *FD = nullptr;
if (!isDefined(FD, true))
FD = this;
if (MemberSpecializationInfo *Info = FD->getMemberSpecializationInfo()) {
if (ForDefinition &&
!clang::isTemplateInstantiation(Info->getTemplateSpecializationKind()))
return nullptr;
return getDefinitionOrSelf(cast<FunctionDecl>(Info->getInstantiatedFrom()));
}
if (ForDefinition &&
!clang::isTemplateInstantiation(getTemplateSpecializationKind()))
return nullptr;
if (FunctionTemplateDecl *Primary = getPrimaryTemplate()) {
while (!ForDefinition || !Primary->isMemberSpecialization()) {
auto *NewPrimary = Primary->getInstantiatedFromMemberTemplate();
if (!NewPrimary)
break;
Primary = NewPrimary;
}
return getDefinitionOrSelf(Primary->getTemplatedDecl());
}
return nullptr;
}
FunctionTemplateDecl *FunctionDecl::getPrimaryTemplate() const {
if (FunctionTemplateSpecializationInfo *Info
= TemplateOrSpecialization
.dyn_cast<FunctionTemplateSpecializationInfo*>()) {
return Info->getTemplate();
}
return nullptr;
}
FunctionTemplateSpecializationInfo *
FunctionDecl::getTemplateSpecializationInfo() const {
return TemplateOrSpecialization
.dyn_cast<FunctionTemplateSpecializationInfo *>();
}
const TemplateArgumentList *
FunctionDecl::getTemplateSpecializationArgs() const {
if (FunctionTemplateSpecializationInfo *Info
= TemplateOrSpecialization
.dyn_cast<FunctionTemplateSpecializationInfo*>()) {
return Info->TemplateArguments;
}
return nullptr;
}
const ASTTemplateArgumentListInfo *
FunctionDecl::getTemplateSpecializationArgsAsWritten() const {
if (FunctionTemplateSpecializationInfo *Info
= TemplateOrSpecialization
.dyn_cast<FunctionTemplateSpecializationInfo*>()) {
return Info->TemplateArgumentsAsWritten;
}
return nullptr;
}
void
FunctionDecl::setFunctionTemplateSpecialization(ASTContext &C,
FunctionTemplateDecl *Template,
const TemplateArgumentList *TemplateArgs,
void *InsertPos,
TemplateSpecializationKind TSK,
const TemplateArgumentListInfo *TemplateArgsAsWritten,
SourceLocation PointOfInstantiation) {
assert((TemplateOrSpecialization.isNull() ||
TemplateOrSpecialization.is<MemberSpecializationInfo *>()) &&
"Member function is already a specialization");
assert(TSK != TSK_Undeclared &&
"Must specify the type of function template specialization");
assert((TemplateOrSpecialization.isNull() ||
TSK == TSK_ExplicitSpecialization) &&
"Member specialization must be an explicit specialization");
FunctionTemplateSpecializationInfo *Info =
FunctionTemplateSpecializationInfo::Create(
C, this, Template, TSK, TemplateArgs, TemplateArgsAsWritten,
PointOfInstantiation,
TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo *>());
TemplateOrSpecialization = Info;
Template->addSpecialization(Info, InsertPos);
}
void
FunctionDecl::setDependentTemplateSpecialization(ASTContext &Context,
const UnresolvedSetImpl &Templates,
const TemplateArgumentListInfo &TemplateArgs) {
assert(TemplateOrSpecialization.isNull());
DependentFunctionTemplateSpecializationInfo *Info =
DependentFunctionTemplateSpecializationInfo::Create(Context, Templates,
TemplateArgs);
TemplateOrSpecialization = Info;
}
DependentFunctionTemplateSpecializationInfo *
FunctionDecl::getDependentSpecializationInfo() const {
return TemplateOrSpecialization
.dyn_cast<DependentFunctionTemplateSpecializationInfo *>();
}
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);
}
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]);
}
TemplateSpecializationKind FunctionDecl::getTemplateSpecializationKind() const {
if (FunctionTemplateSpecializationInfo *FTSInfo =
TemplateOrSpecialization
.dyn_cast<FunctionTemplateSpecializationInfo *>())
return FTSInfo->getTemplateSpecializationKind();
if (MemberSpecializationInfo *MSInfo =
TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo *>())
return MSInfo->getTemplateSpecializationKind();
return TSK_Undeclared;
}
TemplateSpecializationKind
FunctionDecl::getTemplateSpecializationKindForInstantiation() const {
if (FunctionTemplateSpecializationInfo *FTSInfo =
TemplateOrSpecialization
.dyn_cast<FunctionTemplateSpecializationInfo *>()) {
if (auto *MSInfo = FTSInfo->getMemberSpecializationInfo())
return MSInfo->getTemplateSpecializationKind();
return FTSInfo->getTemplateSpecializationKind();
}
if (MemberSpecializationInfo *MSInfo =
TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo *>())
return MSInfo->getTemplateSpecializationKind();
return TSK_Undeclared;
}
void
FunctionDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK,
SourceLocation PointOfInstantiation) {
if (FunctionTemplateSpecializationInfo *FTSInfo
= TemplateOrSpecialization.dyn_cast<
FunctionTemplateSpecializationInfo*>()) {
FTSInfo->setTemplateSpecializationKind(TSK);
if (TSK != TSK_ExplicitSpecialization &&
PointOfInstantiation.isValid() &&
FTSInfo->getPointOfInstantiation().isInvalid()) {
FTSInfo->setPointOfInstantiation(PointOfInstantiation);
if (ASTMutationListener *L = getASTContext().getASTMutationListener())
L->InstantiationRequested(this);
}
} else if (MemberSpecializationInfo *MSInfo
= TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>()) {
MSInfo->setTemplateSpecializationKind(TSK);
if (TSK != TSK_ExplicitSpecialization &&
PointOfInstantiation.isValid() &&
MSInfo->getPointOfInstantiation().isInvalid()) {
MSInfo->setPointOfInstantiation(PointOfInstantiation);
if (ASTMutationListener *L = getASTContext().getASTMutationListener())
L->InstantiationRequested(this);
}
} else
llvm_unreachable("Function cannot have a template specialization kind");
}
SourceLocation FunctionDecl::getPointOfInstantiation() const {
if (FunctionTemplateSpecializationInfo *FTSInfo
= TemplateOrSpecialization.dyn_cast<
FunctionTemplateSpecializationInfo*>())
return FTSInfo->getPointOfInstantiation();
if (MemberSpecializationInfo *MSInfo =
TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo *>())
return MSInfo->getPointOfInstantiation();
return SourceLocation();
}
bool FunctionDecl::isOutOfLine() const {
if (Decl::isOutOfLine())
return true;
if (FunctionDecl *FD = getInstantiatedFromMemberFunction()) {
const FunctionDecl *Definition;
if (FD->hasBody(Definition))
return Definition->isOutOfLine();
}
if (FunctionTemplateDecl *FunTmpl = getPrimaryTemplate()) {
const FunctionDecl *Definition;
if (FunTmpl->getTemplatedDecl()->hasBody(Definition))
return Definition->isOutOfLine();
}
return false;
}
SourceRange FunctionDecl::getSourceRange() const {
return SourceRange(getOuterLocStart(), EndRangeLoc);
}
unsigned FunctionDecl::getMemoryFunctionKind() const {
IdentifierInfo *FnInfo = getIdentifier();
if (!FnInfo)
return 0;
switch (getBuiltinID()) {
case Builtin::BI__builtin_memset:
case Builtin::BI__builtin___memset_chk:
case Builtin::BImemset:
return Builtin::BImemset;
case Builtin::BI__builtin_memcpy:
case Builtin::BI__builtin___memcpy_chk:
case Builtin::BImemcpy:
return Builtin::BImemcpy;
case Builtin::BI__builtin_mempcpy:
case Builtin::BI__builtin___mempcpy_chk:
case Builtin::BImempcpy:
return Builtin::BImempcpy;
case Builtin::BI__builtin_memmove:
case Builtin::BI__builtin___memmove_chk:
case Builtin::BImemmove:
return Builtin::BImemmove;
case Builtin::BIstrlcpy:
case Builtin::BI__builtin___strlcpy_chk:
return Builtin::BIstrlcpy;
case Builtin::BIstrlcat:
case Builtin::BI__builtin___strlcat_chk:
return Builtin::BIstrlcat;
case Builtin::BI__builtin_memcmp:
case Builtin::BImemcmp:
return Builtin::BImemcmp;
case Builtin::BI__builtin_bcmp:
case Builtin::BIbcmp:
return Builtin::BIbcmp;
case Builtin::BI__builtin_strncpy:
case Builtin::BI__builtin___strncpy_chk:
case Builtin::BIstrncpy:
return Builtin::BIstrncpy;
case Builtin::BI__builtin_strncmp:
case Builtin::BIstrncmp:
return Builtin::BIstrncmp;
case Builtin::BI__builtin_strncasecmp:
case Builtin::BIstrncasecmp:
return Builtin::BIstrncasecmp;
case Builtin::BI__builtin_strncat:
case Builtin::BI__builtin___strncat_chk:
case Builtin::BIstrncat:
return Builtin::BIstrncat;
case Builtin::BI__builtin_strndup:
case Builtin::BIstrndup:
return Builtin::BIstrndup;
case Builtin::BI__builtin_strlen:
case Builtin::BIstrlen:
return Builtin::BIstrlen;
case Builtin::BI__builtin_bzero:
case Builtin::BIbzero:
return Builtin::BIbzero;
case Builtin::BIfree:
return Builtin::BIfree;
default:
if (isExternC()) {
if (FnInfo->isStr("memset"))
return Builtin::BImemset;
if (FnInfo->isStr("memcpy"))
return Builtin::BImemcpy;
if (FnInfo->isStr("mempcpy"))
return Builtin::BImempcpy;
if (FnInfo->isStr("memmove"))
return Builtin::BImemmove;
if (FnInfo->isStr("memcmp"))
return Builtin::BImemcmp;
if (FnInfo->isStr("bcmp"))
return Builtin::BIbcmp;
if (FnInfo->isStr("strncpy"))
return Builtin::BIstrncpy;
if (FnInfo->isStr("strncmp"))
return Builtin::BIstrncmp;
if (FnInfo->isStr("strncasecmp"))
return Builtin::BIstrncasecmp;
if (FnInfo->isStr("strncat"))
return Builtin::BIstrncat;
if (FnInfo->isStr("strndup"))
return Builtin::BIstrndup;
if (FnInfo->isStr("strlen"))
return Builtin::BIstrlen;
if (FnInfo->isStr("bzero"))
return Builtin::BIbzero;
} else if (isInStdNamespace()) {
if (FnInfo->isStr("free"))
return Builtin::BIfree;
}
break;
}
return 0;
}
unsigned FunctionDecl::getODRHash() const {
assert(hasODRHash());
return ODRHash;
}
unsigned FunctionDecl::getODRHash() {
if (hasODRHash())
return ODRHash;
if (auto *FT = getInstantiatedFromMemberFunction()) {
setHasODRHash(true);
ODRHash = FT->getODRHash();
return ODRHash;
}
class ODRHash Hash;
Hash.AddFunctionDecl(this);
setHasODRHash(true);
ODRHash = Hash.CalculateHash();
return ODRHash;
}
FieldDecl *FieldDecl::Create(const ASTContext &C, DeclContext *DC,
SourceLocation StartLoc, SourceLocation IdLoc,
IdentifierInfo *Id, QualType T,
TypeSourceInfo *TInfo, Expr *BW, bool Mutable,
InClassInitStyle InitStyle) {
return new (C, DC) FieldDecl(Decl::Field, DC, StartLoc, IdLoc, Id, T, TInfo,
BW, Mutable, InitStyle);
}
FieldDecl *FieldDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
return new (C, ID) FieldDecl(Field, nullptr, SourceLocation(),
SourceLocation(), nullptr, QualType(), nullptr,
nullptr, false, ICIS_NoInit);
}
bool FieldDecl::isAnonymousStructOrUnion() const {
if (!isImplicit() || getDeclName())
return false;
if (const auto *Record = getType()->getAs<RecordType>())
return Record->getDecl()->isAnonymousStructOrUnion();
return false;
}
unsigned FieldDecl::getBitWidthValue(const ASTContext &Ctx) const {
assert(isBitField() && "not a bitfield");
return getBitWidth()->EvaluateKnownConstInt(Ctx).getZExtValue();
}
bool FieldDecl::isZeroLengthBitField(const ASTContext &Ctx) const {
return isUnnamedBitfield() && !getBitWidth()->isValueDependent() &&
getBitWidthValue(Ctx) == 0;
}
bool FieldDecl::isZeroSize(const ASTContext &Ctx) const {
if (isZeroLengthBitField(Ctx))
return true;
if (!hasAttr<NoUniqueAddressAttr>())
return false;
const auto *RT = getType()->getAs<RecordType>();
if (!RT)
return false;
const RecordDecl *RD = RT->getDecl()->getDefinition();
if (!RD) {
assert(isInvalidDecl() && "valid field has incomplete type");
return false;
}
const auto *CXXRD = cast<CXXRecordDecl>(RD);
if (!CXXRD->isEmpty())
return false;
return true;
}
unsigned FieldDecl::getFieldIndex() const {
const FieldDecl *Canonical = getCanonicalDecl();
if (Canonical != this)
return Canonical->getFieldIndex();
if (CachedFieldIndex) return CachedFieldIndex - 1;
unsigned Index = 0;
const RecordDecl *RD = getParent()->getDefinition();
assert(RD && "requested index for field of struct with no definition");
for (auto *Field : RD->fields()) {
Field->getCanonicalDecl()->CachedFieldIndex = Index + 1;
++Index;
}
assert(CachedFieldIndex && "failed to find field in parent");
return CachedFieldIndex - 1;
}
SourceRange FieldDecl::getSourceRange() const {
const Expr *FinalExpr = getInClassInitializer();
if (!FinalExpr)
FinalExpr = getBitWidth();
if (FinalExpr)
return SourceRange(getInnerLocStart(), FinalExpr->getEndLoc());
return DeclaratorDecl::getSourceRange();
}
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);
}
TagDecl::TagDecl(Kind DK, TagKind TK, const ASTContext &C, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id, TagDecl *PrevDecl,
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");
setPreviousDecl(PrevDecl);
setTagKind(TK);
setCompleteDefinition(false);
setBeingDefined(false);
setEmbeddedInDeclarator(false);
setFreeStanding(false);
setCompleteDefinitionRequired(false);
TagDeclBits.IsThisDeclarationADemotedDefinition = false;
}
SourceLocation TagDecl::getOuterLocStart() const {
return getTemplateOrInnerLocStart(this);
}
SourceRange TagDecl::getSourceRange() const {
SourceLocation RBraceLoc = BraceRange.getEnd();
SourceLocation E = RBraceLoc.isValid() ? RBraceLoc : getLocation();
return SourceRange(getOuterLocStart(), E);
}
TagDecl *TagDecl::getCanonicalDecl() { return getFirstDecl(); }
void TagDecl::setTypedefNameForAnonDecl(TypedefNameDecl *TDD) {
TypedefNameDeclOrQualifier = TDD;
if (const Type *T = getTypeForDecl()) {
(void)T;
assert(T->isLinkageValid());
}
assert(isLinkageValid());
}
void TagDecl::startDefinition() {
setBeingDefined(true);
if (auto *D = dyn_cast<CXXRecordDecl>(this)) {
struct CXXRecordDecl::DefinitionData *Data =
new (getASTContext()) struct CXXRecordDecl::DefinitionData(D);
for (auto I : redecls())
cast<CXXRecordDecl>(I)->DefinitionData = Data;
}
}
void TagDecl::completeDefinition() {
assert((!isa<CXXRecordDecl>(this) ||
cast<CXXRecordDecl>(this)->hasDefinition()) &&
"definition completed but not started");
setCompleteDefinition(true);
setBeingDefined(false);
if (ASTMutationListener *L = getASTMutationListener())
L->CompletedTagDefinition(this);
}
TagDecl *TagDecl::getDefinition() const {
if (isCompleteDefinition())
return const_cast<TagDecl *>(this);
if (mayHaveOutOfDateDef()) {
if (IdentifierInfo *II = getIdentifier()) {
if (II->isOutOfDate()) {
updateOutOfDate(*II);
}
}
}
if (const auto *CXXRD = dyn_cast<CXXRecordDecl>(this))
return CXXRD->getDefinition();
for (auto R : redecls())
if (R->isCompleteDefinition())
return R;
return nullptr;
}
void TagDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) {
if (QualifierLoc) {
if (!hasExtInfo())
TypedefNameDeclOrQualifier = new (getASTContext()) ExtInfo;
getExtInfo()->QualifierLoc = QualifierLoc;
} else {
if (hasExtInfo()) {
if (getExtInfo()->NumTemplParamLists == 0) {
getASTContext().Deallocate(getExtInfo());
TypedefNameDeclOrQualifier = (TypedefNameDecl *)nullptr;
}
else
getExtInfo()->QualifierLoc = QualifierLoc;
}
}
}
void TagDecl::setTemplateParameterListsInfo(
ASTContext &Context, ArrayRef<TemplateParameterList *> TPLists) {
assert(!TPLists.empty());
if (!hasExtInfo())
TypedefNameDeclOrQualifier = new (getASTContext()) ExtInfo;
getExtInfo()->setTemplateParameterListsInfo(Context, TPLists);
}
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) {
assert(Scoped || !ScopedUsingClassTag);
IntegerType = nullptr;
setNumPositiveBits(0);
setNumNegativeBits(0);
setScoped(Scoped);
setScopedUsingClassTag(ScopedUsingClassTag);
setFixed(Fixed);
setHasODRHash(false);
ODRHash = 0;
}
void EnumDecl::anchor() {}
EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation StartLoc, SourceLocation IdLoc,
IdentifierInfo *Id,
EnumDecl *PrevDecl, bool IsScoped,
bool IsScopedUsingClassTag, bool IsFixed) {
auto *Enum = new (C, DC) EnumDecl(C, DC, StartLoc, IdLoc, Id, PrevDecl,
IsScoped, IsScopedUsingClassTag, IsFixed);
Enum->setMayHaveOutOfDateDef(C.getLangOpts().Modules);
C.getTypeDeclType(Enum, PrevDecl);
return Enum;
}
EnumDecl *EnumDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
EnumDecl *Enum =
new (C, ID) EnumDecl(C, nullptr, SourceLocation(), SourceLocation(),
nullptr, nullptr, false, false, false);
Enum->setMayHaveOutOfDateDef(C.getLangOpts().Modules);
return Enum;
}
SourceRange EnumDecl::getIntegerTypeRange() const {
if (const TypeSourceInfo *TI = getIntegerTypeSourceInfo())
return TI->getTypeLoc().getSourceRange();
return SourceRange();
}
void EnumDecl::completeDefinition(QualType NewType,
QualType NewPromotionType,
unsigned NumPositiveBits,
unsigned NumNegativeBits) {
assert(!isCompleteDefinition() && "Cannot redefine enums!");
if (!IntegerType)
IntegerType = NewType.getTypePtr();
PromotionType = NewPromotionType;
setNumPositiveBits(NumPositiveBits);
setNumNegativeBits(NumNegativeBits);
TagDecl::completeDefinition();
}
bool EnumDecl::isClosed() const {
if (const auto *A = getAttr<EnumExtensibilityAttr>())
return A->getExtensibility() == EnumExtensibilityAttr::Closed;
return true;
}
bool EnumDecl::isClosedFlag() const {
return isClosed() && hasAttr<FlagEnumAttr>();
}
bool EnumDecl::isClosedNonFlag() const {
return isClosed() && !hasAttr<FlagEnumAttr>();
}
TemplateSpecializationKind EnumDecl::getTemplateSpecializationKind() const {
if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo())
return MSI->getTemplateSpecializationKind();
return TSK_Undeclared;
}
void EnumDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK,
SourceLocation PointOfInstantiation) {
MemberSpecializationInfo *MSI = getMemberSpecializationInfo();
assert(MSI && "Not an instantiated member enumeration?");
MSI->setTemplateSpecializationKind(TSK);
if (TSK != TSK_ExplicitSpecialization &&
PointOfInstantiation.isValid() &&
MSI->getPointOfInstantiation().isInvalid())
MSI->setPointOfInstantiation(PointOfInstantiation);
}
EnumDecl *EnumDecl::getTemplateInstantiationPattern() const {
if (MemberSpecializationInfo *MSInfo = getMemberSpecializationInfo()) {
if (isTemplateInstantiation(MSInfo->getTemplateSpecializationKind())) {
EnumDecl *ED = getInstantiatedFromMemberEnum();
while (auto *NewED = ED->getInstantiatedFromMemberEnum())
ED = NewED;
return getDefinitionOrSelf(ED);
}
}
assert(!isTemplateInstantiation(getTemplateSpecializationKind()) &&
"couldn't find pattern for enum instantiation");
return nullptr;
}
EnumDecl *EnumDecl::getInstantiatedFromMemberEnum() const {
if (SpecializationInfo)
return cast<EnumDecl>(SpecializationInfo->getInstantiatedFrom());
return nullptr;
}
void EnumDecl::setInstantiationOfMemberEnum(ASTContext &C, EnumDecl *ED,
TemplateSpecializationKind TSK) {
assert(!SpecializationInfo && "Member enum is already a specialization");
SpecializationInfo = new (C) MemberSpecializationInfo(ED, TSK);
}
unsigned EnumDecl::getODRHash() {
if (hasODRHash())
return ODRHash;
class ODRHash Hash;
Hash.AddEnumDecl(this);
setHasODRHash(true);
ODRHash = Hash.CalculateHash();
return ODRHash;
}
SourceRange EnumDecl::getSourceRange() const {
auto Res = TagDecl::getSourceRange();
if (auto *TSI = getIntegerTypeSourceInfo()) {
if (!getBraceRange().getEnd().isValid())
Res.setEnd(TSI->getTypeLoc().getEndLoc());
}
return Res;
}
RecordDecl::RecordDecl(Kind DK, TagKind TK, const ASTContext &C,
DeclContext *DC, SourceLocation StartLoc,
SourceLocation IdLoc, IdentifierInfo *Id,
RecordDecl *PrevDecl)
: TagDecl(DK, TK, C, DC, IdLoc, Id, PrevDecl, StartLoc) {
assert(classof(static_cast<Decl *>(this)) && "Invalid Kind!");
setHasFlexibleArrayMember(false);
setAnonymousStructOrUnion(false);
setHasObjectMember(false);
setHasVolatileMember(false);
setHasLoadedFieldsFromExternalStorage(false);
setNonTrivialToPrimitiveDefaultInitialize(false);
setNonTrivialToPrimitiveCopy(false);
setNonTrivialToPrimitiveDestroy(false);
setHasNonTrivialToPrimitiveDefaultInitializeCUnion(false);
setHasNonTrivialToPrimitiveDestructCUnion(false);
setHasNonTrivialToPrimitiveCopyCUnion(false);
setParamDestroyedInCallee(false);
setArgPassingRestrictions(APK_CanPassInRegs);
setIsRandomized(false);
}
RecordDecl *RecordDecl::Create(const ASTContext &C, TagKind TK, DeclContext *DC,
SourceLocation StartLoc, SourceLocation IdLoc,
IdentifierInfo *Id, RecordDecl* PrevDecl) {
RecordDecl *R = new (C, DC) RecordDecl(Record, TK, C, DC,
StartLoc, IdLoc, Id, PrevDecl);
R->setMayHaveOutOfDateDef(C.getLangOpts().Modules);
C.getTypeDeclType(R, PrevDecl);
return R;
}
RecordDecl *RecordDecl::CreateDeserialized(const ASTContext &C, unsigned ID) {
RecordDecl *R =
new (C, ID) RecordDecl(Record, TTK_Struct, C, nullptr, SourceLocation(),
SourceLocation(), nullptr, nullptr);
R->setMayHaveOutOfDateDef(C.getLangOpts().Modules);
return R;
}
bool RecordDecl::isInjectedClassName() const {
return isImplicit() && getDeclName() && getDeclContext()->isRecord() &&
cast<RecordDecl>(getDeclContext())->getDeclName() == getDeclName();
}
bool RecordDecl::isLambda() const {
if (auto RD = dyn_cast<CXXRecordDecl>(this))
return RD->isLambda();
return false;
}
bool RecordDecl::isCapturedRecord() const {
return hasAttr<CapturedRecordAttr>();
}
void RecordDecl::setCapturedRecord() {
addAttr(CapturedRecordAttr::CreateImplicit(getASTContext()));
}
bool RecordDecl::isOrContainsUnion() const {
if (isUnion())
return true;
if (const RecordDecl *Def = getDefinition()) {
for (const FieldDecl *FD : Def->fields()) {
const RecordType *RT = FD->getType()->getAs<RecordType>();
if (RT && RT->getDecl()->isOrContainsUnion())
return true;
}
}
return false;
}
RecordDecl::field_iterator RecordDecl::field_begin() const {
if (hasExternalLexicalStorage() && !hasLoadedFieldsFromExternalStorage())
LoadFieldsFromExternalStorage();
return field_iterator(decl_iterator(FirstDecl));
}
void RecordDecl::completeDefinition() {
assert(!isCompleteDefinition() && "Cannot redefine record!");
TagDecl::completeDefinition();
ASTContext &Ctx = getASTContext();
if (Ctx.getLangOpts().DumpRecordLayoutsComplete)
(void)Ctx.getASTRecordLayout(this);
}
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?");
ExternalASTSource::Deserializing TheFields(Source);
SmallVector<Decl*, 64> Decls;
setHasLoadedFieldsFromExternalStorage(true);
Source->FindExternalLexicalDecls(this, [](Decl::Kind K) {
return FieldDecl::classofKind(K) || IndirectFieldDecl::classofKind(K);
}, Decls);
#ifndef NDEBUG
for (unsigned i=0, e=Decls.size(); i != e; ++i)
assert(isa<FieldDecl>(Decls[i]) || isa<IndirectFieldDecl>(Decls[i]));
#endif
if (Decls.empty())
return;
std::tie(FirstDecl, LastDecl) = BuildDeclChain(Decls,
false);
}
bool RecordDecl::mayInsertExtraPadding(bool EmitRemark) const {
ASTContext &Context = getASTContext();
const SanitizerMask EnabledAsanMask = Context.getLangOpts().Sanitize.Mask &
(SanitizerKind::Address | SanitizerKind::KernelAddress);
if (!EnabledAsanMask || !Context.getLangOpts().SanitizeAddressFieldPadding)
return false;
const auto &NoSanitizeList = Context.getNoSanitizeList();
const auto *CXXRD = dyn_cast<CXXRecordDecl>(this);
int ReasonToReject = -1;
if (!CXXRD || CXXRD->isExternCContext())
ReasonToReject = 0; else if (CXXRD->hasAttr<PackedAttr>())
ReasonToReject = 1; else if (CXXRD->isUnion())
ReasonToReject = 2; else if (CXXRD->isTriviallyCopyable())
ReasonToReject = 3; else if (CXXRD->hasTrivialDestructor())
ReasonToReject = 4; else if (CXXRD->isStandardLayout())
ReasonToReject = 5; else if (NoSanitizeList.containsLocation(EnabledAsanMask, getLocation(),
"field-padding"))
ReasonToReject = 6; else if (NoSanitizeList.containsType(
EnabledAsanMask, getQualifiedNameAsString(), "field-padding"))
ReasonToReject = 7;
if (EmitRemark) {
if (ReasonToReject >= 0)
Context.getDiagnostics().Report(
getLocation(),
diag::remark_sanitize_address_insert_extra_padding_rejected)
<< getQualifiedNameAsString() << ReasonToReject;
else
Context.getDiagnostics().Report(
getLocation(),
diag::remark_sanitize_address_insert_extra_padding_accepted)
<< getQualifiedNameAsString();
}
return ReasonToReject < 0;
}
const FieldDecl *RecordDecl::findFirstNamedDataMember() const {
for (const auto *I : fields()) {
if (I->getIdentifier())
return I;
if (const auto *RT = I->getType()->getAs<RecordType>())
if (const FieldDecl *NamedDataMember =
RT->getDecl()->findFirstNamedDataMember())
return NamedDataMember;
}
return nullptr;
}
BlockDecl::BlockDecl(DeclContext *DC, SourceLocation CaretLoc)
: Decl(Block, DC, CaretLoc), DeclContext(Block) {
setIsVariadic(false);
setCapturesCXXThis(false);
setBlockMissingReturnType(true);
setIsConversionFromLambda(false);
setDoesNotEscape(false);
setCanAvoidCopyToHeap(false);
}
void BlockDecl::setParams(ArrayRef<ParmVarDecl *> NewParamInfo) {
assert(!ParamInfo && "Already has param info!");
if (!NewParamInfo.empty()) {
NumParams = NewParamInfo.size();
ParamInfo = new (getASTContext()) ParmVarDecl*[NewParamInfo.size()];
std::copy(NewParamInfo.begin(), NewParamInfo.end(), ParamInfo);
}
}
void BlockDecl::setCaptures(ASTContext &Context, ArrayRef<Capture> Captures,
bool CapturesCXXThis) {
this->setCapturesCXXThis(CapturesCXXThis);
this->NumCaptures = Captures.size();
if (Captures.empty()) {
this->Captures = nullptr;
return;
}
this->Captures = Captures.copy(Context).data();
}
bool BlockDecl::capturesVariable(const VarDecl *variable) const {
for (const auto &I : captures())
if (I.getVariable() == variable)
return true;
return false;
}
SourceRange BlockDecl::getSourceRange() const {
return SourceRange(getLocation(), Body ? Body->getEndLoc() : getLocation());
}
void TranslationUnitDecl::anchor() {}
TranslationUnitDecl *TranslationUnitDecl::Create(ASTContext &C) {
return new (C, (DeclContext *)nullptr) TranslationUnitDecl(C);
}
void PragmaCommentDecl::anchor() {}
PragmaCommentDecl *PragmaCommentDecl::Create(const ASTContext &C,
TranslationUnitDecl *DC,
SourceLocation CommentLoc,
PragmaMSCommentKind CommentKind,
StringRef Arg) {
PragmaCommentDecl *PCD =
new (C, DC, additionalSizeToAlloc<char>(Arg.size() + 1))
PragmaCommentDecl(DC, CommentLoc, CommentKind);
memcpy(PCD->getTrailingObjects<char>(), Arg.data(), Arg.size());
PCD->getTrailingObjects<char>()[Arg.size()] = '\0';
return PCD;
}
PragmaCommentDecl *PragmaCommentDecl::CreateDeserialized(ASTContext &C,
unsigned ID,
unsigned ArgSize) {
return new (C, ID, additionalSizeToAlloc<char>(ArgSize + 1))
PragmaCommentDecl(nullptr, SourceLocation(), PCK_Unknown);
}
void PragmaDetectMismatchDecl::anchor() {}
PragmaDetectMismatchDecl *
PragmaDetectMismatchDecl::Create(const ASTContext &C, TranslationUnitDecl *DC,
SourceLocation Loc, StringRef Name,
StringRef Value) {
size_t ValueStart = Name.size() + 1;
PragmaDetectMismatchDecl *PDMD =
new (C, DC, additionalSizeToAlloc<char>(ValueStart + Value.size() + 1))
PragmaDetectMismatchDecl(DC, Loc, ValueStart);
memcpy(PDMD->getTrailingObjects<char>(), Name.data(), Name.size());
PDMD->getTrailingObjects<char>()[Name.size()] = '\0';
memcpy(PDMD->getTrailingObjects<char>() + ValueStart, Value.data(),
Value.size());
PDMD->getTrailingObjects<char>()[ValueStart + Value.size()] = '\0';
return PDMD;
}
PragmaDetectMismatchDecl *
PragmaDetectMismatchDecl::CreateDeserialized(ASTContext &C, unsigned ID,
unsigned NameValueSize) {
return new (C, ID, additionalSizeToAlloc<char>(NameValueSize + 1))
PragmaDetectMismatchDecl(nullptr, SourceLocation(), 0);
}
void ExternCContextDecl::anchor() {}
ExternCContextDecl *ExternCContextDecl::Create(const ASTContext &C,
TranslationUnitDecl *DC) {
return new (C, DC) ExternCContextDecl(DC);
}
void LabelDecl::anchor() {}
LabelDecl *LabelDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation IdentL, IdentifierInfo *II) {
return new (C, DC) LabelDecl(DC, IdentL, II, nullptr, IdentL);
}
LabelDecl *LabelDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation IdentL, IdentifierInfo *II,
SourceLocation GnuLabelL) {
assert(GnuLabelL != IdentL && "Use this only for GNU local labels");
return new (C, DC) LabelDecl(DC, IdentL, II, nullptr, GnuLabelL);
}
LabelDecl *LabelDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
return new (C, ID) LabelDecl(nullptr, SourceLocation(), nullptr, nullptr,
SourceLocation());
}
void LabelDecl::setMSAsmLabel(StringRef Name) {
char *Buffer = new (getASTContext(), 1) char[Name.size() + 1];
memcpy(Buffer, Name.data(), Name.size());
Buffer[Name.size()] = '\0';
MSAsmName = Buffer;
}
void ValueDecl::anchor() {}
bool ValueDecl::isWeak() const {
auto *MostRecent = getMostRecentDecl();
return MostRecent->hasAttr<WeakAttr>() ||
MostRecent->hasAttr<WeakRefAttr>() || isWeakImported();
}
void ImplicitParamDecl::anchor() {}
ImplicitParamDecl *ImplicitParamDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation IdLoc,
IdentifierInfo *Id, QualType Type,
ImplicitParamKind ParamKind) {
return new (C, DC) ImplicitParamDecl(C, DC, IdLoc, Id, Type, ParamKind);
}
ImplicitParamDecl *ImplicitParamDecl::Create(ASTContext &C, QualType Type,
ImplicitParamKind ParamKind) {
return new (C, nullptr) ImplicitParamDecl(C, Type, ParamKind);
}
ImplicitParamDecl *ImplicitParamDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
return new (C, ID) ImplicitParamDecl(C, QualType(), ImplicitParamKind::Other);
}
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;
}
FunctionDecl *FunctionDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
return new (C, ID) FunctionDecl(
Function, C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(),
nullptr, SC_None, false, false, ConstexprSpecKind::Unspecified, nullptr);
}
BlockDecl *BlockDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L) {
return new (C, DC) BlockDecl(DC, L);
}
BlockDecl *BlockDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
return new (C, ID) BlockDecl(nullptr, SourceLocation());
}
CapturedDecl::CapturedDecl(DeclContext *DC, unsigned NumParams)
: Decl(Captured, DC, SourceLocation()), DeclContext(Captured),
NumParams(NumParams), ContextParam(0), BodyAndNothrow(nullptr, false) {}
CapturedDecl *CapturedDecl::Create(ASTContext &C, DeclContext *DC,
unsigned NumParams) {
return new (C, DC, additionalSizeToAlloc<ImplicitParamDecl *>(NumParams))
CapturedDecl(DC, NumParams);
}
CapturedDecl *CapturedDecl::CreateDeserialized(ASTContext &C, unsigned ID,
unsigned NumParams) {
return new (C, ID, additionalSizeToAlloc<ImplicitParamDecl *>(NumParams))
CapturedDecl(nullptr, NumParams);
}
Stmt *CapturedDecl::getBody() const { return BodyAndNothrow.getPointer(); }
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::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);
}
EnumConstantDecl *
EnumConstantDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
return new (C, ID) EnumConstantDecl(nullptr, SourceLocation(), nullptr,
QualType(), nullptr, llvm::APSInt());
}
void IndirectFieldDecl::anchor() {}
IndirectFieldDecl::IndirectFieldDecl(ASTContext &C, DeclContext *DC,
SourceLocation L, DeclarationName N,
QualType T,
MutableArrayRef<NamedDecl *> CH)
: ValueDecl(IndirectField, DC, L, N, T), Chaining(CH.data()),
ChainingSize(CH.size()) {
if (C.getLangOpts().CPlusPlus)
IdentifierNamespace |= IDNS_Tag;
}
IndirectFieldDecl *
IndirectFieldDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
IdentifierInfo *Id, QualType T,
llvm::MutableArrayRef<NamedDecl *> CH) {
return new (C, DC) IndirectFieldDecl(C, DC, L, Id, T, CH);
}
IndirectFieldDecl *IndirectFieldDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
return new (C, ID) IndirectFieldDecl(C, nullptr, SourceLocation(),
DeclarationName(), QualType(), None);
}
SourceRange EnumConstantDecl::getSourceRange() const {
SourceLocation End = getLocation();
if (Init)
End = Init->getEndLoc();
return SourceRange(getLocation(), End);
}
void TypeDecl::anchor() {}
TypedefDecl *TypedefDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation StartLoc, SourceLocation IdLoc,
IdentifierInfo *Id, TypeSourceInfo *TInfo) {
return new (C, DC) TypedefDecl(C, DC, StartLoc, IdLoc, Id, TInfo);
}
void TypedefNameDecl::anchor() {}
TagDecl *TypedefNameDecl::getAnonDeclWithTypedefName(bool AnyRedecl) const {
if (auto *TT = getTypeSourceInfo()->getType()->getAs<TagType>()) {
auto *OwningTypedef = TT->getDecl()->getTypedefNameForAnonDecl();
auto *ThisTypedef = this;
if (AnyRedecl && OwningTypedef) {
OwningTypedef = OwningTypedef->getCanonicalDecl();
ThisTypedef = ThisTypedef->getCanonicalDecl();
}
if (OwningTypedef == ThisTypedef)
return TT->getDecl();
}
return nullptr;
}
bool TypedefNameDecl::isTransparentTagSlow() const {
auto determineIsTransparent = [&]() {
if (auto *TT = getUnderlyingType()->getAs<TagType>()) {
if (auto *TD = TT->getDecl()) {
if (TD->getName() != getName())
return false;
SourceLocation TTLoc = getLocation();
SourceLocation TDLoc = TD->getLocation();
if (!TTLoc.isMacroID() || !TDLoc.isMacroID())
return false;
SourceManager &SM = getASTContext().getSourceManager();
return SM.getSpellingLoc(TTLoc) == SM.getSpellingLoc(TDLoc);
}
}
return false;
};
bool isTransparent = determineIsTransparent();
MaybeModedTInfo.setInt((isTransparent << 1) | 1);
return isTransparent;
}
TypedefDecl *TypedefDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
return new (C, ID) TypedefDecl(C, nullptr, SourceLocation(), SourceLocation(),
nullptr, nullptr);
}
TypeAliasDecl *TypeAliasDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation StartLoc,
SourceLocation IdLoc, IdentifierInfo *Id,
TypeSourceInfo *TInfo) {
return new (C, DC) TypeAliasDecl(C, DC, StartLoc, IdLoc, Id, TInfo);
}
TypeAliasDecl *TypeAliasDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
return new (C, ID) TypeAliasDecl(C, nullptr, SourceLocation(),
SourceLocation(), nullptr, nullptr);
}
SourceRange TypedefDecl::getSourceRange() const {
SourceLocation RangeEnd = getLocation();
if (TypeSourceInfo *TInfo = getTypeSourceInfo()) {
if (typeIsPostfix(TInfo->getType()))
RangeEnd = TInfo->getTypeLoc().getSourceRange().getEnd();
}
return SourceRange(getBeginLoc(), RangeEnd);
}
SourceRange TypeAliasDecl::getSourceRange() const {
SourceLocation RangeEnd = getBeginLoc();
if (TypeSourceInfo *TInfo = getTypeSourceInfo())
RangeEnd = TInfo->getTypeLoc().getSourceRange().getEnd();
return SourceRange(getBeginLoc(), RangeEnd);
}
void FileScopeAsmDecl::anchor() {}
FileScopeAsmDecl *FileScopeAsmDecl::Create(ASTContext &C, DeclContext *DC,
StringLiteral *Str,
SourceLocation AsmLoc,
SourceLocation RParenLoc) {
return new (C, DC) FileScopeAsmDecl(DC, Str, AsmLoc, RParenLoc);
}
FileScopeAsmDecl *FileScopeAsmDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
return new (C, ID) FileScopeAsmDecl(nullptr, nullptr, SourceLocation(),
SourceLocation());
}
void EmptyDecl::anchor() {}
EmptyDecl *EmptyDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L) {
return new (C, DC) EmptyDecl(DC, L);
}
EmptyDecl *EmptyDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
return new (C, ID) EmptyDecl(nullptr, SourceLocation());
}
static unsigned getNumModuleIdentifiers(Module *Mod) {
unsigned Result = 1;
while (Mod->Parent) {
Mod = Mod->Parent;
++Result;
}
return Result;
}
ImportDecl::ImportDecl(DeclContext *DC, SourceLocation StartLoc,
Module *Imported,
ArrayRef<SourceLocation> IdentifierLocs)
: Decl(Import, DC, StartLoc), ImportedModule(Imported),
NextLocalImportAndComplete(nullptr, true) {
assert(getNumModuleIdentifiers(Imported) == IdentifierLocs.size());
auto *StoredLocs = getTrailingObjects<SourceLocation>();
std::uninitialized_copy(IdentifierLocs.begin(), IdentifierLocs.end(),
StoredLocs);
}
ImportDecl::ImportDecl(DeclContext *DC, SourceLocation StartLoc,
Module *Imported, SourceLocation EndLoc)
: Decl(Import, DC, StartLoc), ImportedModule(Imported),
NextLocalImportAndComplete(nullptr, false) {
*getTrailingObjects<SourceLocation>() = EndLoc;
}
ImportDecl *ImportDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation StartLoc, Module *Imported,
ArrayRef<SourceLocation> IdentifierLocs) {
return new (C, DC,
additionalSizeToAlloc<SourceLocation>(IdentifierLocs.size()))
ImportDecl(DC, StartLoc, Imported, IdentifierLocs);
}
ImportDecl *ImportDecl::CreateImplicit(ASTContext &C, DeclContext *DC,
SourceLocation StartLoc,
Module *Imported,
SourceLocation EndLoc) {
ImportDecl *Import = new (C, DC, additionalSizeToAlloc<SourceLocation>(1))
ImportDecl(DC, StartLoc, Imported, EndLoc);
Import->setImplicit();
return Import;
}
ImportDecl *ImportDecl::CreateDeserialized(ASTContext &C, unsigned ID,
unsigned NumLocations) {
return new (C, ID, additionalSizeToAlloc<SourceLocation>(NumLocations))
ImportDecl(EmptyShell());
}
ArrayRef<SourceLocation> ImportDecl::getIdentifierLocs() const {
if (!isImportComplete())
return None;
const auto *StoredLocs = getTrailingObjects<SourceLocation>();
return llvm::makeArrayRef(StoredLocs,
getNumModuleIdentifiers(getImportedModule()));
}
SourceRange ImportDecl::getSourceRange() const {
if (!isImportComplete())
return SourceRange(getLocation(), *getTrailingObjects<SourceLocation>());
return SourceRange(getLocation(), getIdentifierLocs().back());
}
void ExportDecl::anchor() {}
ExportDecl *ExportDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation ExportLoc) {
return new (C, DC) ExportDecl(DC, ExportLoc);
}
ExportDecl *ExportDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
return new (C, ID) ExportDecl(nullptr, SourceLocation());
}