From 48203b327d8ddf2cb785a1ac30b3cd9fa1e54b44 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Thu, 8 Sep 2022 15:09:39 -0700 Subject: [PATCH] Revert D130308 "[clang] extend getCommonSugaredType to merge sugar nodes" This reverts commit 16e5d6d7f98f1119aab3d10ec4f9e59b5aacd359. There are multiple complaints on the review. In addition, it may cause spurious ``` error: invalid operands to binary expression ('SinkPrinter' and 'char[cluster_name_length]') note: candidate template ignored: substitution failure: variably modified type 'char *' cannot be used as a template argument SinkPrinter operator<<(const SinkPrinter &s, T) { ``` for some C++ code --- clang/include/clang/AST/ASTContext.h | 3 - clang/lib/AST/ASTContext.cpp | 379 +++++------------------------- clang/lib/Sema/SemaTemplateDeduction.cpp | 6 +- clang/test/SemaCXX/sugar-common-types.cpp | 76 +----- 4 files changed, 60 insertions(+), 404 deletions(-) diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index acde4ff..8ef7a32 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -1366,9 +1366,6 @@ public: CanQualType getDecayedType(CanQualType T) const { return CanQualType::CreateUnsafe(getDecayedType((QualType) T)); } - /// Return the uniqued reference to a specified decay from the original - /// type to the decayed type. - QualType getDecayedType(QualType Orig, QualType Decayed) const; /// Return the uniqued reference to the atomic type for the specified /// type. diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index fe06e8e..d7c626a 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -3332,26 +3332,6 @@ QualType ASTContext::getAdjustedType(QualType Orig, QualType New) const { return QualType(AT, 0); } -QualType ASTContext::getDecayedType(QualType Orig, QualType Decayed) const { - llvm::FoldingSetNodeID ID; - AdjustedType::Profile(ID, Orig, Decayed); - void *InsertPos = nullptr; - AdjustedType *AT = AdjustedTypes.FindNodeOrInsertPos(ID, InsertPos); - if (AT) - return QualType(AT, 0); - - QualType Canonical = getCanonicalType(Decayed); - - // Get the new insert position for the node we care about. - AT = AdjustedTypes.FindNodeOrInsertPos(ID, InsertPos); - assert(!AT && "Shouldn't be in the map!"); - - AT = new (*this, TypeAlignment) DecayedType(Orig, Decayed, Canonical); - Types.push_back(AT); - AdjustedTypes.InsertNode(AT, InsertPos); - return QualType(AT, 0); -} - QualType ASTContext::getDecayedType(QualType T) const { assert((T->isArrayType() || T->isFunctionType()) && "T does not decay"); @@ -3372,7 +3352,23 @@ QualType ASTContext::getDecayedType(QualType T) const { if (T->isFunctionType()) Decayed = getPointerType(T); - return getDecayedType(T, Decayed); + llvm::FoldingSetNodeID ID; + AdjustedType::Profile(ID, T, Decayed); + void *InsertPos = nullptr; + AdjustedType *AT = AdjustedTypes.FindNodeOrInsertPos(ID, InsertPos); + if (AT) + return QualType(AT, 0); + + QualType Canonical = getCanonicalType(Decayed); + + // Get the new insert position for the node we care about. + AT = AdjustedTypes.FindNodeOrInsertPos(ID, InsertPos); + assert(!AT && "Shouldn't be in the map!"); + + AT = new (*this, TypeAlignment) DecayedType(T, Decayed, Canonical); + Types.push_back(AT); + AdjustedTypes.InsertNode(AT, InsertPos); + return QualType(AT, 0); } /// getBlockPointerType - Return the uniqued reference to the type for @@ -12149,8 +12145,9 @@ unsigned ASTContext::getTargetAddressSpace(LangAS AS) const { // the regular ones. static Decl *getCommonDecl(Decl *X, Decl *Y) { - if (!declaresSameEntity(X, Y)) - return nullptr; + if (X == Y) + return X; + assert(declaresSameEntity(X, Y)); for (const Decl *DX : X->redecls()) { // If we reach Y before reaching the first decl, that means X is older. if (DX == Y) @@ -12185,19 +12182,11 @@ static TemplateName getCommonTemplateName(ASTContext &Ctx, TemplateName X, // with more sugar. For example one could be a SubstTemplateTemplate* // replacing the other. TemplateName CX = Ctx.getCanonicalTemplateName(X); - if (CX.getAsVoidPointer() != - Ctx.getCanonicalTemplateName(Y).getAsVoidPointer()) - return TemplateName(); + assert(CX.getAsVoidPointer() == + Ctx.getCanonicalTemplateName(Y).getAsVoidPointer()); return CX; } -static TemplateName -getCommonTemplateNameChecked(ASTContext &Ctx, TemplateName X, TemplateName Y) { - TemplateName R = getCommonTemplateName(Ctx, X, Y); - assert(R.getAsVoidPointer() != nullptr); - return R; -} - static auto getCommonTypes(ASTContext &Ctx, ArrayRef Xs, ArrayRef Ys, bool Unqualified = false) { assert(Xs.size() == Ys.size()); @@ -12216,71 +12205,27 @@ static SourceLocation getCommonAttrLoc(const T *X, const T *Y) { static TemplateArgument getCommonTemplateArgument(ASTContext &Ctx, const TemplateArgument &X, const TemplateArgument &Y) { - if (X.getKind() != Y.getKind()) - return TemplateArgument(); - + assert(X.getKind() == Y.getKind()); switch (X.getKind()) { case TemplateArgument::ArgKind::Type: - if (!Ctx.hasSameType(X.getAsType(), Y.getAsType())) - return TemplateArgument(); return TemplateArgument( Ctx.getCommonSugaredType(X.getAsType(), Y.getAsType())); case TemplateArgument::ArgKind::NullPtr: - if (!Ctx.hasSameType(X.getNullPtrType(), Y.getNullPtrType())) - return TemplateArgument(); return TemplateArgument( Ctx.getCommonSugaredType(X.getNullPtrType(), Y.getNullPtrType()), /*Unqualified=*/true); - case TemplateArgument::ArgKind::Expression: - if (!Ctx.hasSameType(X.getAsExpr()->getType(), Y.getAsExpr()->getType())) - return TemplateArgument(); - // FIXME: Try to keep the common sugar. - return X; - case TemplateArgument::ArgKind::Template: { - TemplateName TX = X.getAsTemplate(), TY = Y.getAsTemplate(); - TemplateName CTN = ::getCommonTemplateName(Ctx, TX, TY); - if (!CTN.getAsVoidPointer()) - return TemplateArgument(); - return TemplateArgument(CTN); - } - case TemplateArgument::ArgKind::TemplateExpansion: { - TemplateName TX = X.getAsTemplateOrTemplatePattern(), - TY = Y.getAsTemplateOrTemplatePattern(); - TemplateName CTN = ::getCommonTemplateName(Ctx, TX, TY); - if (!CTN.getAsVoidPointer()) - return TemplateName(); - auto NExpX = X.getNumTemplateExpansions(); - assert(NExpX == Y.getNumTemplateExpansions()); - return TemplateArgument(CTN, NExpX); - } default: // FIXME: Handle the other argument kinds. return X; } } -static bool getCommonTemplateArguments(ASTContext &Ctx, - SmallVectorImpl &R, - ArrayRef Xs, - ArrayRef Ys) { - if (Xs.size() != Ys.size()) - return true; - R.resize(Xs.size()); - for (size_t I = 0; I < R.size(); ++I) { - R[I] = getCommonTemplateArgument(Ctx, Xs[I], Ys[I]); - if (R[I].isNull()) - return true; - } - return false; -} - static auto getCommonTemplateArguments(ASTContext &Ctx, - ArrayRef Xs, - ArrayRef Ys) { - SmallVector R; - bool Different = getCommonTemplateArguments(Ctx, R, Xs, Ys); - assert(!Different); - (void)Different; + ArrayRef X, + ArrayRef Y) { + SmallVector R(X.size()); + for (size_t I = 0; I < R.size(); ++I) + R[I] = getCommonTemplateArgument(Ctx, X[I], Y[I]); return R; } @@ -12413,8 +12358,7 @@ ASTContext::mergeExceptionSpecs(FunctionProtoType::ExceptionSpecInfo ESI1, llvm_unreachable("invalid ExceptionSpecificationType"); } -static QualType getCommonNonSugarTypeNode(ASTContext &Ctx, const Type *X, - const Type *Y) { +static QualType getCommonType(ASTContext &Ctx, const Type *X, const Type *Y) { Type::TypeClass TC = X->getTypeClass(); assert(TC == Y->getTypeClass()); switch (TC) { @@ -12460,8 +12404,8 @@ static QualType getCommonNonSugarTypeNode(ASTContext &Ctx, const Type *X, return Ctx.getAutoType(QualType(), AX->getKeyword(), AX->isInstantiationDependentType(), AX->containsUnexpandedParameterPack(), - getCommonDeclChecked(AX->getTypeConstraintConcept(), - AY->getTypeConstraintConcept()), + getCommonDecl(AX->getTypeConstraintConcept(), + AY->getTypeConstraintConcept()), As); } case Type::IncompleteArray: { @@ -12643,9 +12587,9 @@ static QualType getCommonNonSugarTypeNode(ASTContext &Ctx, const Type *X, auto As = getCommonTemplateArguments(Ctx, TX->template_arguments(), TY->template_arguments()); return Ctx.getTemplateSpecializationType( - ::getCommonTemplateNameChecked(Ctx, TX->getTemplateName(), - TY->getTemplateName()), - As, X->getCanonicalTypeInternal()); + ::getCommonTemplateName(Ctx, TX->getTemplateName(), + TY->getTemplateName()), + As, TX->getCanonicalTypeInternal()); } case Type::DependentName: { const auto *NX = cast(X), @@ -12693,208 +12637,31 @@ static QualType getCommonNonSugarTypeNode(ASTContext &Ctx, const Type *X, llvm_unreachable("Unknown Type Class"); } -static QualType getCommonSugarTypeNode(ASTContext &Ctx, const Type *X, - const Type *Y, - SplitQualType Underlying) { - Type::TypeClass TC = X->getTypeClass(); - if (TC != Y->getTypeClass()) - return QualType(); - switch (TC) { -#define UNEXPECTED_TYPE(Class, Kind) \ - case Type::Class: \ - llvm_unreachable("Unexpected " Kind ": " #Class); -#define TYPE(Class, Base) -#define DEPENDENT_TYPE(Class, Base) UNEXPECTED_TYPE(Class, "dependent") -#include "clang/AST/TypeNodes.inc" - -#define CANONICAL_TYPE(Class) UNEXPECTED_TYPE(Class, "canonical") - CANONICAL_TYPE(Atomic) - CANONICAL_TYPE(BitInt) - CANONICAL_TYPE(BlockPointer) - CANONICAL_TYPE(Builtin) - CANONICAL_TYPE(Complex) - CANONICAL_TYPE(ConstantArray) - CANONICAL_TYPE(ConstantMatrix) - CANONICAL_TYPE(Enum) - CANONICAL_TYPE(ExtVector) - CANONICAL_TYPE(FunctionNoProto) - CANONICAL_TYPE(FunctionProto) - CANONICAL_TYPE(IncompleteArray) - CANONICAL_TYPE(LValueReference) - CANONICAL_TYPE(MemberPointer) - CANONICAL_TYPE(ObjCInterface) - CANONICAL_TYPE(ObjCObject) - CANONICAL_TYPE(ObjCObjectPointer) - CANONICAL_TYPE(Pipe) - CANONICAL_TYPE(Pointer) - CANONICAL_TYPE(Record) - CANONICAL_TYPE(RValueReference) - CANONICAL_TYPE(VariableArray) - CANONICAL_TYPE(Vector) -#undef CANONICAL_TYPE - -#undef UNEXPECTED_TYPE - - case Type::Adjusted: { - const auto *AX = cast(X), *AY = cast(Y); - QualType OX = AX->getOriginalType(), OY = AY->getOriginalType(); - if (!Ctx.hasSameType(OX, OY)) - return QualType(); - // FIXME: It's inefficient to have to unify the original types. - return Ctx.getAdjustedType(Ctx.getCommonSugaredType(OX, OY), - Ctx.getQualifiedType(Underlying)); - } - case Type::Decayed: { - const auto *DX = cast(X), *DY = cast(Y); - QualType OX = DX->getOriginalType(), OY = DY->getOriginalType(); - if (!Ctx.hasSameType(OX, OY)) - return QualType(); - // FIXME: It's inefficient to have to unify the original types. - return Ctx.getDecayedType(Ctx.getCommonSugaredType(OX, OY), - Ctx.getQualifiedType(Underlying)); - } - case Type::Attributed: { - const auto *AX = cast(X), *AY = cast(Y); - AttributedType::Kind Kind = AX->getAttrKind(); - if (Kind != AY->getAttrKind()) - return QualType(); - QualType MX = AX->getModifiedType(), MY = AY->getModifiedType(); - if (!Ctx.hasSameType(MX, MY)) - return QualType(); - // FIXME: It's inefficient to have to unify the modified types. - return Ctx.getAttributedType(Kind, Ctx.getCommonSugaredType(MX, MY), - Ctx.getQualifiedType(Underlying)); - } - case Type::BTFTagAttributed: { - const auto *BX = cast(X); - const BTFTypeTagAttr *AX = BX->getAttr(); - // The attribute is not uniqued, so just compare the tag. - if (AX->getBTFTypeTag() != - cast(Y)->getAttr()->getBTFTypeTag()) - return QualType(); - return Ctx.getBTFTagAttributedType(AX, Ctx.getQualifiedType(Underlying)); - } - case Type::Auto: { - const auto *AX = cast(X), *AY = cast(Y); - - AutoTypeKeyword KW = AX->getKeyword(); - if (KW != AY->getKeyword()) - return QualType(); - - ConceptDecl *CD = ::getCommonDecl(AX->getTypeConstraintConcept(), - AY->getTypeConstraintConcept()); - SmallVector As; - if (CD && - getCommonTemplateArguments(Ctx, As, AX->getTypeConstraintArguments(), - AY->getTypeConstraintArguments())) - CD = nullptr; // The arguments differ, so make it unconstrained. - - // Both auto types can't be dependent, otherwise they wouldn't have been - // sugar. This implies they can't contain unexpanded packs either. - return Ctx.getAutoType(Ctx.getQualifiedType(Underlying), AX->getKeyword(), - /*IsDependent=*/false, /*IsPack=*/false, CD, As); - } - case Type::Decltype: - return QualType(); - case Type::DeducedTemplateSpecialization: - // FIXME: Try to merge these. - return QualType(); - - case Type::Elaborated: { - const auto *EX = cast(X), *EY = cast(Y); - return Ctx.getElaboratedType( - ::getCommonTypeKeyword(EX, EY), ::getCommonNNS(Ctx, EX, EY), - Ctx.getQualifiedType(Underlying), - ::getCommonDecl(EX->getOwnedTagDecl(), EY->getOwnedTagDecl())); - } - case Type::MacroQualified: { - const auto *MX = cast(X), - *MY = cast(Y); - const IdentifierInfo *IX = MX->getMacroIdentifier(); - if (IX != MY->getMacroIdentifier()) - return QualType(); - return Ctx.getMacroQualifiedType(Ctx.getQualifiedType(Underlying), IX); - } - case Type::SubstTemplateTypeParm: { - const auto *SX = cast(X), - *SY = cast(Y); - const TemplateTypeParmType *PX = SX->getReplacedParameter(); - if (PX != SY->getReplacedParameter()) - return QualType(); - - return Ctx.getSubstTemplateTypeParmType(PX, - Ctx.getQualifiedType(Underlying)); - } - case Type::ObjCTypeParam: - // FIXME: Try to merge these. - return QualType(); - case Type::Paren: - return Ctx.getParenType(Ctx.getQualifiedType(Underlying)); - - case Type::TemplateSpecialization: { - const auto *TX = cast(X), - *TY = cast(Y); - TemplateName CTN = ::getCommonTemplateName(Ctx, TX->getTemplateName(), - TY->getTemplateName()); - if (!CTN.getAsVoidPointer()) - return QualType(); - SmallVector Args; - if (getCommonTemplateArguments(Ctx, Args, TX->template_arguments(), - TY->template_arguments())) - return QualType(); - return Ctx.getTemplateSpecializationType(CTN, Args, - Ctx.getQualifiedType(Underlying)); - } - case Type::Typedef: { - const auto *TX = cast(X), *TY = cast(Y); - const TypedefNameDecl *CD = ::getCommonDecl(TX->getDecl(), TY->getDecl()); - if (!CD) - return QualType(); - return Ctx.getTypedefType(CD, Ctx.getQualifiedType(Underlying)); - } - case Type::TypeOf: - return Ctx.getTypeOfType(Ctx.getQualifiedType(Underlying)); - case Type::TypeOfExpr: - return QualType(); - - case Type::UnaryTransform: { - const auto *UX = cast(X), - *UY = cast(Y); - UnaryTransformType::UTTKind KX = UX->getUTTKind(); - if (KX != UY->getUTTKind()) - return QualType(); - QualType BX = UX->getBaseType(), BY = UY->getBaseType(); - if (!Ctx.hasSameType(BX, BY)) - return QualType(); - // FIXME: It's inefficient to have to unify the base types. - return Ctx.getUnaryTransformType(Ctx.getCommonSugaredType(BX, BY), - Ctx.getQualifiedType(Underlying), KX); - } - case Type::Using: { - const auto *UX = cast(X), *UY = cast(Y); - const UsingShadowDecl *CD = - ::getCommonDecl(UX->getFoundDecl(), UY->getFoundDecl()); - if (!CD) - return QualType(); - return Ctx.getUsingType(CD, Ctx.getQualifiedType(Underlying)); - } - } - llvm_unreachable("Unhandled Type Class"); -} - -static auto unwrapSugar(SplitQualType &T, Qualifiers &QTotal) { +static auto unwrapSugar(SplitQualType &T) { SmallVector R; while (true) { - QTotal += T.Quals; QualType NT = T.Ty->getLocallyUnqualifiedSingleStepDesugaredType(); if (NT == QualType(T.Ty, 0)) break; + SplitQualType SplitNT = NT.split(); + SplitNT.Quals += T.Quals; R.push_back(T); - T = NT.split(); + T = SplitNT; } return R; } +static bool removeDifferentTopLevelSugar(SplitQualType &SX, SplitQualType &SY) { + auto Xs = ::unwrapSugar(SX), Ys = ::unwrapSugar(SY); + if (SX.Ty != SY.Ty) + return true; + while (!Xs.empty() && !Ys.empty() && Xs.back().Ty == Ys.back().Ty) { + SX = Xs.pop_back_val(); + SY = Ys.pop_back_val(); + } + return false; +} + QualType ASTContext::getCommonSugaredType(QualType X, QualType Y, bool Unqualified) { assert(Unqualified ? hasSameUnqualifiedType(X, Y) : hasSameType(X, Y)); @@ -12908,51 +12675,15 @@ QualType ASTContext::getCommonSugaredType(QualType X, QualType Y, } SplitQualType SX = X.split(), SY = Y.split(); - Qualifiers QX, QY; - // Desugar SX and SY, setting the sugar and qualifiers aside into Xs and Ys, - // until we reach their underlying "canonical nodes". Note these are not - // necessarily canonical types, as they may still have sugared properties. - // QX and QY will store the sum of all qualifiers in Xs and Ys respectively. - auto Xs = ::unwrapSugar(SX, QX), Ys = ::unwrapSugar(SY, QY); - if (SX.Ty != SY.Ty) { - // The canonical nodes differ. Build a common canonical node out of the two, - // unifying their sugar. This may recurse back here. - SX.Ty = ::getCommonNonSugarTypeNode(*this, SX.Ty, SY.Ty).getTypePtr(); - } else { - // The canonical nodes were identical: We may have desugared too much. - // Add any common sugar back in. - while (!Xs.empty() && !Ys.empty() && Xs.back().Ty == Ys.back().Ty) { - QX -= SX.Quals; - QY -= SY.Quals; - SX = Xs.pop_back_val(); - SY = Ys.pop_back_val(); - } - } + if (::removeDifferentTopLevelSugar(SX, SY)) + SX.Ty = ::getCommonType(*this, SX.Ty, SY.Ty).getTypePtr(); + if (Unqualified) - QX = Qualifiers::removeCommonQualifiers(QX, QY); + SX.Quals = Qualifiers::removeCommonQualifiers(SX.Quals, SY.Quals); else - assert(QX == QY); - - // Even though the remaining sugar nodes in Xs and Ys differ, some may be - // related. Walk up these nodes, unifying them and adding the result. - while (!Xs.empty() && !Ys.empty()) { - auto Underlying = SplitQualType( - SX.Ty, Qualifiers::removeCommonQualifiers(SX.Quals, SY.Quals)); - SX = Xs.pop_back_val(); - SY = Ys.pop_back_val(); - SX.Ty = ::getCommonSugarTypeNode(*this, SX.Ty, SY.Ty, Underlying) - .getTypePtrOrNull(); - // Stop at the first pair which is unrelated. - if (!SX.Ty) { - SX.Ty = Underlying.Ty; - break; - } - QX -= Underlying.Quals; - }; + assert(SX.Quals == SY.Quals); - // Add back the missing accumulated qualifiers, which were stripped off - // with the sugar nodes we could not unify. - QualType R = getQualifiedType(SX.Ty, QX); + QualType R = getQualifiedType(SX); assert(Unqualified ? hasSameUnqualifiedType(R, X) : hasSameType(R, X)); return R; } diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 82f6d94..0e07a15 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -3825,11 +3825,13 @@ static bool AdjustFunctionParmAndArgTypesForDeduction( // - If A is an array type, the pointer type produced by the // array-to-pointer standard conversion (4.2) is used in place of // A for type deduction; otherwise, + if (ArgType->isArrayType()) + ArgType = S.Context.getArrayDecayedType(ArgType); // - If A is a function type, the pointer type produced by the // function-to-pointer standard conversion (4.3) is used in place // of A for type deduction; otherwise, - if (ArgType->canDecayToPointerType()) - ArgType = S.Context.getDecayedType(ArgType); + else if (ArgType->isFunctionType()) + ArgType = S.Context.getPointerType(ArgType); else { // - If A is a cv-qualified type, the top level cv-qualifiers of A's // type are ignored for type deduction. diff --git a/clang/test/SemaCXX/sugar-common-types.cpp b/clang/test/SemaCXX/sugar-common-types.cpp index 7ae3a87..8c18d8a 100644 --- a/clang/test/SemaCXX/sugar-common-types.cpp +++ b/clang/test/SemaCXX/sugar-common-types.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++20 -fenable-matrix -triple i686-pc-win32 +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++20 -fenable-matrix enum class N {}; @@ -38,77 +38,3 @@ N t6 = A3() ? X1() : Y1(); // expected-error {{vector condition type 'A3' (vecto N t7 = X4() + Y4(); // expected-error {{rvalue of type 'B4'}} N t8 = X4() * Y4(); // expected-error {{rvalue of type 'B4'}} N t9 = X5() * Y5(); // expected-error {{rvalue of type 'A4 __attribute__((matrix_type(3, 3)))'}} - -template struct S1 { - template struct S2 {}; -}; - -N t10 = 0 ? S1() : S1(); // expected-error {{from 'S1' (aka 'S1')}} -N t11 = 0 ? S1::S2() : S1::S2(); // expected-error {{from 'S1::S2' (aka 'S2')}} - -template using Al = S1; - -N t12 = 0 ? Al() : Al(); // expected-error {{from 'Al' (aka 'S1')}} - -#define AS1 __attribute__((address_space(1))) -#define AS2 __attribute__((address_space(1))) -using AS1X1 = AS1 B1; -using AS1Y1 = AS1 B1; -using AS2Y1 = AS2 B1; -N t13 = 0 ? (AS1X1){} : (AS1Y1){}; // expected-error {{rvalue of type 'AS1 B1' (aka '__attribute__((address_space(1))) int')}} -N t14 = 0 ? (AS1X1){} : (AS2Y1){}; // expected-error {{rvalue of type '__attribute__((address_space(1))) B1' (aka '__attribute__((address_space(1))) int')}} - -using FX1 = X1 (); -using FY1 = Y1 (); -N t15 = 0 ? (FX1*){} : (FY1*){}; // expected-error {{rvalue of type 'B1 (*)()' (aka 'int (*)()')}} - -struct SS1 {}; -using SB1 = SS1; -using SX1 = SB1; -using SY1 = SB1; - -using MFX1 = X1 SX1::*(); -using MFY1 = Y1 SY1::*(); - -N t16 = 0 ? (MFX1*){} : (MFY1*){}; // expected-error {{rvalue of type 'B1 SB1::*(*)()'}} - -N t17 = 0 ? (FX1 SX1::*){} : (FY1 SY1::*){}; // expected-error {{rvalue of type 'B1 (SB1::*)() __attribute__((thiscall))'}} - -N t18 = 0 ? (__typeof(X1*)){} : (__typeof(Y1*)){}; // expected-error {{rvalue of type 'typeof(B1 *)' (aka 'int *')}} - -struct Enums { - enum X : B1; - enum Y : ::B1; -}; -using EnumsB = Enums; -using EnumsX = EnumsB; -using EnumsY = EnumsB; - -N t19 = 0 ? (__underlying_type(EnumsX::X)){} : (__underlying_type(EnumsY::Y)){}; -// expected-error@-1 {{rvalue of type 'B1' (aka 'int')}} - -N t20 = 0 ? (__underlying_type(EnumsX::X)){} : (__underlying_type(EnumsY::X)){}; -// expected-error@-1 {{rvalue of type '__underlying_type(Enums::X)' (aka 'int')}} - -using SBTF1 = SS1 [[clang::btf_type_tag("1")]]; -using SBTF2 = ::SS1 [[clang::btf_type_tag("1")]]; -using SBTF3 = ::SS1 [[clang::btf_type_tag("2")]]; - -N t21 = 0 ? (SBTF1){} : (SBTF3){}; // expected-error {{from 'SS1'}} -N t22 = 0 ? (SBTF1){} : (SBTF2){}; // expected-error {{from 'SS1 btf_type_tag(1)' (aka 'SS1')}} - -using QX = const SB1 *; -using QY = const ::SB1 *; -N t23 = 0 ? (QX){} : (QY){}; // expected-error {{rvalue of type 'const SB1 *' (aka 'const SS1 *')}} - -template using Alias = short; -N t24 = 0 ? (Alias){} : (Alias){}; // expected-error {{rvalue of type 'Alias' (aka 'short')}} -N t25 = 0 ? (Alias){} : (Alias){}; // expected-error {{rvalue of type 'short'}} - -template concept C1 = true; -template concept C2 = true; -C1 auto t26_1 = (SB1){}; -C1 auto t26_2 = (::SB1){}; -C2 auto t26_3 = (::SB1){}; -N t26 = 0 ? t26_1 : t26_2; // expected-error {{from 'SB1' (aka 'SS1')}} -N t27 = 0 ? t26_1 : t26_3; // expected-error {{from 'SB1' (aka 'SS1')}} -- 2.7.4