diff options
Diffstat (limited to 'contrib/llvm-project/clang/lib/AST/ASTContext.cpp')
-rw-r--r-- | contrib/llvm-project/clang/lib/AST/ASTContext.cpp | 398 |
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); |