aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang/lib/AST/ASTContext.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/clang/lib/AST/ASTContext.cpp')
-rw-r--r--contrib/llvm-project/clang/lib/AST/ASTContext.cpp398
1 files changed, 389 insertions, 9 deletions
diff --git a/contrib/llvm-project/clang/lib/AST/ASTContext.cpp b/contrib/llvm-project/clang/lib/AST/ASTContext.cpp
index 701260881a93..a1d5673950e1 100644
--- a/contrib/llvm-project/clang/lib/AST/ASTContext.cpp
+++ b/contrib/llvm-project/clang/lib/AST/ASTContext.cpp
@@ -6147,6 +6147,376 @@ bool ASTContext::hasSameTemplateName(TemplateName X, TemplateName Y) {
return X.getAsVoidPointer() == Y.getAsVoidPointer();
}
+bool ASTContext::isSameTemplateParameter(NamedDecl *X, NamedDecl *Y) {
+ if (X->getKind() != Y->getKind())
+ return false;
+
+ if (auto *TX = dyn_cast<TemplateTypeParmDecl>(X)) {
+ auto *TY = cast<TemplateTypeParmDecl>(Y);
+ if (TX->isParameterPack() != TY->isParameterPack())
+ return false;
+ if (TX->hasTypeConstraint() != TY->hasTypeConstraint())
+ return false;
+ const TypeConstraint *TXTC = TX->getTypeConstraint();
+ const TypeConstraint *TYTC = TY->getTypeConstraint();
+ if (!TXTC != !TYTC)
+ return false;
+ if (TXTC && TYTC) {
+ auto *NCX = TXTC->getNamedConcept();
+ auto *NCY = TYTC->getNamedConcept();
+ if (!NCX || !NCY || !isSameEntity(NCX, NCY))
+ return false;
+ if (TXTC->hasExplicitTemplateArgs() != TYTC->hasExplicitTemplateArgs())
+ return false;
+ if (TXTC->hasExplicitTemplateArgs()) {
+ auto *TXTCArgs = TXTC->getTemplateArgsAsWritten();
+ auto *TYTCArgs = TYTC->getTemplateArgsAsWritten();
+ if (TXTCArgs->NumTemplateArgs != TYTCArgs->NumTemplateArgs)
+ return false;
+ llvm::FoldingSetNodeID XID, YID;
+ for (auto &ArgLoc : TXTCArgs->arguments())
+ ArgLoc.getArgument().Profile(XID, X->getASTContext());
+ for (auto &ArgLoc : TYTCArgs->arguments())
+ ArgLoc.getArgument().Profile(YID, Y->getASTContext());
+ if (XID != YID)
+ return false;
+ }
+ }
+ return true;
+ }
+
+ if (auto *TX = dyn_cast<NonTypeTemplateParmDecl>(X)) {
+ auto *TY = cast<NonTypeTemplateParmDecl>(Y);
+ return TX->isParameterPack() == TY->isParameterPack() &&
+ TX->getASTContext().hasSameType(TX->getType(), TY->getType());
+ }
+
+ auto *TX = cast<TemplateTemplateParmDecl>(X);
+ auto *TY = cast<TemplateTemplateParmDecl>(Y);
+ return TX->isParameterPack() == TY->isParameterPack() &&
+ isSameTemplateParameterList(TX->getTemplateParameters(),
+ TY->getTemplateParameters());
+}
+
+bool ASTContext::isSameTemplateParameterList(TemplateParameterList *X,
+ TemplateParameterList *Y) {
+ if (X->size() != Y->size())
+ return false;
+
+ for (unsigned I = 0, N = X->size(); I != N; ++I)
+ if (!isSameTemplateParameter(X->getParam(I), Y->getParam(I)))
+ return false;
+
+ const Expr *XRC = X->getRequiresClause();
+ const Expr *YRC = Y->getRequiresClause();
+ if (!XRC != !YRC)
+ return false;
+ if (XRC) {
+ llvm::FoldingSetNodeID XRCID, YRCID;
+ XRC->Profile(XRCID, *this, /*Canonical=*/true);
+ YRC->Profile(YRCID, *this, /*Canonical=*/true);
+ if (XRCID != YRCID)
+ return false;
+ }
+
+ return true;
+}
+
+static NamespaceDecl *getNamespace(const NestedNameSpecifier *X) {
+ if (auto *NS = X->getAsNamespace())
+ return NS;
+ if (auto *NAS = X->getAsNamespaceAlias())
+ return NAS->getNamespace();
+ return nullptr;
+}
+
+static bool isSameQualifier(const NestedNameSpecifier *X,
+ const NestedNameSpecifier *Y) {
+ if (auto *NSX = getNamespace(X)) {
+ auto *NSY = getNamespace(Y);
+ if (!NSY || NSX->getCanonicalDecl() != NSY->getCanonicalDecl())
+ return false;
+ } else if (X->getKind() != Y->getKind())
+ return false;
+
+ // FIXME: For namespaces and types, we're permitted to check that the entity
+ // is named via the same tokens. We should probably do so.
+ switch (X->getKind()) {
+ case NestedNameSpecifier::Identifier:
+ if (X->getAsIdentifier() != Y->getAsIdentifier())
+ return false;
+ break;
+ case NestedNameSpecifier::Namespace:
+ case NestedNameSpecifier::NamespaceAlias:
+ // We've already checked that we named the same namespace.
+ break;
+ case NestedNameSpecifier::TypeSpec:
+ case NestedNameSpecifier::TypeSpecWithTemplate:
+ if (X->getAsType()->getCanonicalTypeInternal() !=
+ Y->getAsType()->getCanonicalTypeInternal())
+ return false;
+ break;
+ case NestedNameSpecifier::Global:
+ case NestedNameSpecifier::Super:
+ return true;
+ }
+
+ // Recurse into earlier portion of NNS, if any.
+ auto *PX = X->getPrefix();
+ auto *PY = Y->getPrefix();
+ if (PX && PY)
+ return isSameQualifier(PX, PY);
+ return !PX && !PY;
+}
+
+/// Determine whether the attributes we can overload on are identical for A and
+/// B. Will ignore any overloadable attrs represented in the type of A and B.
+static bool hasSameOverloadableAttrs(const FunctionDecl *A,
+ const FunctionDecl *B) {
+ // Note that pass_object_size attributes are represented in the function's
+ // ExtParameterInfo, so we don't need to check them here.
+
+ llvm::FoldingSetNodeID Cand1ID, Cand2ID;
+ auto AEnableIfAttrs = A->specific_attrs<EnableIfAttr>();
+ auto BEnableIfAttrs = B->specific_attrs<EnableIfAttr>();
+
+ for (auto Pair : zip_longest(AEnableIfAttrs, BEnableIfAttrs)) {
+ Optional<EnableIfAttr *> Cand1A = std::get<0>(Pair);
+ Optional<EnableIfAttr *> Cand2A = std::get<1>(Pair);
+
+ // Return false if the number of enable_if attributes is different.
+ if (!Cand1A || !Cand2A)
+ return false;
+
+ Cand1ID.clear();
+ Cand2ID.clear();
+
+ (*Cand1A)->getCond()->Profile(Cand1ID, A->getASTContext(), true);
+ (*Cand2A)->getCond()->Profile(Cand2ID, B->getASTContext(), true);
+
+ // Return false if any of the enable_if expressions of A and B are
+ // different.
+ if (Cand1ID != Cand2ID)
+ return false;
+ }
+ return true;
+}
+
+bool ASTContext::isSameEntity(NamedDecl *X, NamedDecl *Y) {
+ if (X == Y)
+ return true;
+
+ if (X->getDeclName() != Y->getDeclName())
+ return false;
+
+ // Must be in the same context.
+ //
+ // Note that we can't use DeclContext::Equals here, because the DeclContexts
+ // could be two different declarations of the same function. (We will fix the
+ // semantic DC to refer to the primary definition after merging.)
+ if (!declaresSameEntity(cast<Decl>(X->getDeclContext()->getRedeclContext()),
+ cast<Decl>(Y->getDeclContext()->getRedeclContext())))
+ return false;
+
+ // Two typedefs refer to the same entity if they have the same underlying
+ // type.
+ if (const auto *TypedefX = dyn_cast<TypedefNameDecl>(X))
+ if (const auto *TypedefY = dyn_cast<TypedefNameDecl>(Y))
+ return hasSameType(TypedefX->getUnderlyingType(),
+ TypedefY->getUnderlyingType());
+
+ // Must have the same kind.
+ if (X->getKind() != Y->getKind())
+ return false;
+
+ // Objective-C classes and protocols with the same name always match.
+ if (isa<ObjCInterfaceDecl>(X) || isa<ObjCProtocolDecl>(X))
+ return true;
+
+ if (isa<ClassTemplateSpecializationDecl>(X)) {
+ // No need to handle these here: we merge them when adding them to the
+ // template.
+ return false;
+ }
+
+ // Compatible tags match.
+ if (const auto *TagX = dyn_cast<TagDecl>(X)) {
+ const auto *TagY = cast<TagDecl>(Y);
+ return (TagX->getTagKind() == TagY->getTagKind()) ||
+ ((TagX->getTagKind() == TTK_Struct ||
+ TagX->getTagKind() == TTK_Class ||
+ TagX->getTagKind() == TTK_Interface) &&
+ (TagY->getTagKind() == TTK_Struct ||
+ TagY->getTagKind() == TTK_Class ||
+ TagY->getTagKind() == TTK_Interface));
+ }
+
+ // Functions with the same type and linkage match.
+ // FIXME: This needs to cope with merging of prototyped/non-prototyped
+ // functions, etc.
+ if (const auto *FuncX = dyn_cast<FunctionDecl>(X)) {
+ const auto *FuncY = cast<FunctionDecl>(Y);
+ if (const auto *CtorX = dyn_cast<CXXConstructorDecl>(X)) {
+ const auto *CtorY = cast<CXXConstructorDecl>(Y);
+ if (CtorX->getInheritedConstructor() &&
+ !isSameEntity(CtorX->getInheritedConstructor().getConstructor(),
+ CtorY->getInheritedConstructor().getConstructor()))
+ return false;
+ }
+
+ if (FuncX->isMultiVersion() != FuncY->isMultiVersion())
+ return false;
+
+ // Multiversioned functions with different feature strings are represented
+ // as separate declarations.
+ if (FuncX->isMultiVersion()) {
+ const auto *TAX = FuncX->getAttr<TargetAttr>();
+ const auto *TAY = FuncY->getAttr<TargetAttr>();
+ assert(TAX && TAY && "Multiversion Function without target attribute");
+
+ if (TAX->getFeaturesStr() != TAY->getFeaturesStr())
+ return false;
+ }
+
+ const Expr *XRC = FuncX->getTrailingRequiresClause();
+ const Expr *YRC = FuncY->getTrailingRequiresClause();
+ if (!XRC != !YRC)
+ return false;
+ if (XRC) {
+ llvm::FoldingSetNodeID XRCID, YRCID;
+ XRC->Profile(XRCID, *this, /*Canonical=*/true);
+ YRC->Profile(YRCID, *this, /*Canonical=*/true);
+ if (XRCID != YRCID)
+ return false;
+ }
+
+ auto GetTypeAsWritten = [](const FunctionDecl *FD) {
+ // Map to the first declaration that we've already merged into this one.
+ // The TSI of redeclarations might not match (due to calling conventions
+ // being inherited onto the type but not the TSI), but the TSI type of
+ // the first declaration of the function should match across modules.
+ FD = FD->getCanonicalDecl();
+ return FD->getTypeSourceInfo() ? FD->getTypeSourceInfo()->getType()
+ : FD->getType();
+ };
+ QualType XT = GetTypeAsWritten(FuncX), YT = GetTypeAsWritten(FuncY);
+ if (!hasSameType(XT, YT)) {
+ // We can get functions with different types on the redecl chain in C++17
+ // if they have differing exception specifications and at least one of
+ // the excpetion specs is unresolved.
+ auto *XFPT = XT->getAs<FunctionProtoType>();
+ auto *YFPT = YT->getAs<FunctionProtoType>();
+ if (getLangOpts().CPlusPlus17 && XFPT && YFPT &&
+ (isUnresolvedExceptionSpec(XFPT->getExceptionSpecType()) ||
+ isUnresolvedExceptionSpec(YFPT->getExceptionSpecType())) &&
+ hasSameFunctionTypeIgnoringExceptionSpec(XT, YT))
+ return true;
+ return false;
+ }
+
+ return FuncX->getLinkageInternal() == FuncY->getLinkageInternal() &&
+ hasSameOverloadableAttrs(FuncX, FuncY);
+ }
+
+ // Variables with the same type and linkage match.
+ if (const auto *VarX = dyn_cast<VarDecl>(X)) {
+ const auto *VarY = cast<VarDecl>(Y);
+ if (VarX->getLinkageInternal() == VarY->getLinkageInternal()) {
+ if (hasSameType(VarX->getType(), VarY->getType()))
+ return true;
+
+ // We can get decls with different types on the redecl chain. Eg.
+ // template <typename T> struct S { static T Var[]; }; // #1
+ // template <typename T> T S<T>::Var[sizeof(T)]; // #2
+ // Only? happens when completing an incomplete array type. In this case
+ // when comparing #1 and #2 we should go through their element type.
+ const ArrayType *VarXTy = getAsArrayType(VarX->getType());
+ const ArrayType *VarYTy = getAsArrayType(VarY->getType());
+ if (!VarXTy || !VarYTy)
+ return false;
+ if (VarXTy->isIncompleteArrayType() || VarYTy->isIncompleteArrayType())
+ return hasSameType(VarXTy->getElementType(), VarYTy->getElementType());
+ }
+ return false;
+ }
+
+ // Namespaces with the same name and inlinedness match.
+ if (const auto *NamespaceX = dyn_cast<NamespaceDecl>(X)) {
+ const auto *NamespaceY = cast<NamespaceDecl>(Y);
+ return NamespaceX->isInline() == NamespaceY->isInline();
+ }
+
+ // Identical template names and kinds match if their template parameter lists
+ // and patterns match.
+ if (const auto *TemplateX = dyn_cast<TemplateDecl>(X)) {
+ const auto *TemplateY = cast<TemplateDecl>(Y);
+ return isSameEntity(TemplateX->getTemplatedDecl(),
+ TemplateY->getTemplatedDecl()) &&
+ isSameTemplateParameterList(TemplateX->getTemplateParameters(),
+ TemplateY->getTemplateParameters());
+ }
+
+ // Fields with the same name and the same type match.
+ if (const auto *FDX = dyn_cast<FieldDecl>(X)) {
+ const auto *FDY = cast<FieldDecl>(Y);
+ // FIXME: Also check the bitwidth is odr-equivalent, if any.
+ return hasSameType(FDX->getType(), FDY->getType());
+ }
+
+ // Indirect fields with the same target field match.
+ if (const auto *IFDX = dyn_cast<IndirectFieldDecl>(X)) {
+ const auto *IFDY = cast<IndirectFieldDecl>(Y);
+ return IFDX->getAnonField()->getCanonicalDecl() ==
+ IFDY->getAnonField()->getCanonicalDecl();
+ }
+
+ // Enumerators with the same name match.
+ if (isa<EnumConstantDecl>(X))
+ // FIXME: Also check the value is odr-equivalent.
+ return true;
+
+ // Using shadow declarations with the same target match.
+ if (const auto *USX = dyn_cast<UsingShadowDecl>(X)) {
+ const auto *USY = cast<UsingShadowDecl>(Y);
+ return USX->getTargetDecl() == USY->getTargetDecl();
+ }
+
+ // Using declarations with the same qualifier match. (We already know that
+ // the name matches.)
+ if (const auto *UX = dyn_cast<UsingDecl>(X)) {
+ const auto *UY = cast<UsingDecl>(Y);
+ return isSameQualifier(UX->getQualifier(), UY->getQualifier()) &&
+ UX->hasTypename() == UY->hasTypename() &&
+ UX->isAccessDeclaration() == UY->isAccessDeclaration();
+ }
+ if (const auto *UX = dyn_cast<UnresolvedUsingValueDecl>(X)) {
+ const auto *UY = cast<UnresolvedUsingValueDecl>(Y);
+ return isSameQualifier(UX->getQualifier(), UY->getQualifier()) &&
+ UX->isAccessDeclaration() == UY->isAccessDeclaration();
+ }
+ if (const auto *UX = dyn_cast<UnresolvedUsingTypenameDecl>(X)) {
+ return isSameQualifier(
+ UX->getQualifier(),
+ cast<UnresolvedUsingTypenameDecl>(Y)->getQualifier());
+ }
+
+ // Using-pack declarations are only created by instantiation, and match if
+ // they're instantiated from matching UnresolvedUsing...Decls.
+ if (const auto *UX = dyn_cast<UsingPackDecl>(X)) {
+ return declaresSameEntity(
+ UX->getInstantiatedFromUsingDecl(),
+ cast<UsingPackDecl>(Y)->getInstantiatedFromUsingDecl());
+ }
+
+ // Namespace alias definitions with the same target match.
+ if (const auto *NAX = dyn_cast<NamespaceAliasDecl>(X)) {
+ const auto *NAY = cast<NamespaceAliasDecl>(Y);
+ return NAX->getNamespace()->Equals(NAY->getNamespace());
+ }
+
+ return false;
+}
+
TemplateArgument
ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) const {
switch (Arg.getKind()) {
@@ -8474,8 +8844,8 @@ static TypedefDecl *CreateHexagonBuiltinVaListDecl(const ASTContext *Context) {
FieldDecl *Field = FieldDecl::Create(
const_cast<ASTContext &>(*Context), VaListTagDecl, SourceLocation(),
SourceLocation(), &Context->Idents.get(FieldNames[i]), FieldTypes[i],
- /*TInfo=*/0,
- /*BitWidth=*/0,
+ /*TInfo=*/nullptr,
+ /*BitWidth=*/nullptr,
/*Mutable=*/false, ICIS_NoInit);
Field->setAccess(AS_public);
VaListTagDecl->addDecl(Field);
@@ -9817,12 +10187,13 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
// designates the object or function denoted by the reference, and the
// expression is an lvalue unless the reference is an rvalue reference and
// the expression is a function call (possibly inside parentheses).
- if (LangOpts.OpenMP && LHS->getAs<ReferenceType>() &&
- RHS->getAs<ReferenceType>() && LHS->getTypeClass() == RHS->getTypeClass())
- return mergeTypes(LHS->getAs<ReferenceType>()->getPointeeType(),
- RHS->getAs<ReferenceType>()->getPointeeType(),
+ auto *LHSRefTy = LHS->getAs<ReferenceType>();
+ auto *RHSRefTy = RHS->getAs<ReferenceType>();
+ if (LangOpts.OpenMP && LHSRefTy && RHSRefTy &&
+ LHS->getTypeClass() == RHS->getTypeClass())
+ return mergeTypes(LHSRefTy->getPointeeType(), RHSRefTy->getPointeeType(),
OfBlockPointer, Unqualified, BlockReturnType);
- if (LHS->getAs<ReferenceType>() || RHS->getAs<ReferenceType>())
+ if (LHSRefTy || RHSRefTy)
return {};
if (Unqualified) {
@@ -10309,7 +10680,7 @@ QualType ASTContext::getCorrespondingUnsignedType(QualType T) const {
// For _BitInt, return an unsigned _BitInt with same width.
if (const auto *EITy = T->getAs<BitIntType>())
- return getBitIntType(/*IsUnsigned=*/true, EITy->getNumBits());
+ return getBitIntType(/*Unsigned=*/true, EITy->getNumBits());
// For enums, get the underlying integer type of the enum, and let the general
// integer type signchanging code handle it.
@@ -10377,7 +10748,7 @@ QualType ASTContext::getCorrespondingSignedType(QualType T) const {
// For _BitInt, return a signed _BitInt with same width.
if (const auto *EITy = T->getAs<BitIntType>())
- return getBitIntType(/*IsUnsigned=*/false, EITy->getNumBits());
+ return getBitIntType(/*Unsigned=*/false, EITy->getNumBits());
// For enums, get the underlying integer type of the enum, and let the general
// integer type signchanging code handle it.
@@ -11572,6 +11943,15 @@ uint64_t ASTContext::getTargetNullPointerValue(QualType QT) const {
return getTargetInfo().getNullPointerValue(AS);
}
+unsigned ASTContext::getTargetAddressSpace(QualType T) const {
+ return T->isFunctionType() ? getTargetInfo().getProgramAddressSpace()
+ : getTargetAddressSpace(T.getQualifiers());
+}
+
+unsigned ASTContext::getTargetAddressSpace(Qualifiers Q) const {
+ return getTargetAddressSpace(Q.getAddressSpace());
+}
+
unsigned ASTContext::getTargetAddressSpace(LangAS AS) const {
if (isTargetAddressSpace(AS))
return toTargetAddressSpace(AS);