[clang] 48203b3 - Revert D130308 "[clang] extend getCommonSugaredType to merge sugar nodes"
Fangrui Song via cfe-commits
cfe-commits at lists.llvm.org
Thu Sep 8 15:09:47 PDT 2022
Author: Fangrui Song
Date: 2022-09-08T15:09:39-07:00
New Revision: 48203b327d8ddf2cb785a1ac30b3cd9fa1e54b44
URL: https://github.com/llvm/llvm-project/commit/48203b327d8ddf2cb785a1ac30b3cd9fa1e54b44
DIFF: https://github.com/llvm/llvm-project/commit/48203b327d8ddf2cb785a1ac30b3cd9fa1e54b44.diff
LOG: 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
Added:
Modified:
clang/include/clang/AST/ASTContext.h
clang/lib/AST/ASTContext.cpp
clang/lib/Sema/SemaTemplateDeduction.cpp
clang/test/SemaCXX/sugar-common-types.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index acde4ff6f9429..8ef7a32e6f09e 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -1366,9 +1366,6 @@ class ASTContext : public RefCountedBase<ASTContext> {
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 fe06e8eb18f16..d7c626adee19b 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<QualType> Xs,
ArrayRef<QualType> 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<TemplateArgument> &R,
- ArrayRef<TemplateArgument> Xs,
- ArrayRef<TemplateArgument> 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<TemplateArgument> Xs,
- ArrayRef<TemplateArgument> Ys) {
- SmallVector<TemplateArgument, 8> R;
- bool Different = getCommonTemplateArguments(Ctx, R, Xs, Ys);
- assert(!Different);
- (void)Different;
+ ArrayRef<TemplateArgument> X,
+ ArrayRef<TemplateArgument> Y) {
+ SmallVector<TemplateArgument, 8> 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<DependentNameType>(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<AdjustedType>(X), *AY = cast<AdjustedType>(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<DecayedType>(X), *DY = cast<DecayedType>(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<AttributedType>(X), *AY = cast<AttributedType>(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<BTFTagAttributedType>(X);
- const BTFTypeTagAttr *AX = BX->getAttr();
- // The attribute is not uniqued, so just compare the tag.
- if (AX->getBTFTypeTag() !=
- cast<BTFTagAttributedType>(Y)->getAttr()->getBTFTypeTag())
- return QualType();
- return Ctx.getBTFTagAttributedType(AX, Ctx.getQualifiedType(Underlying));
- }
- case Type::Auto: {
- const auto *AX = cast<AutoType>(X), *AY = cast<AutoType>(Y);
-
- AutoTypeKeyword KW = AX->getKeyword();
- if (KW != AY->getKeyword())
- return QualType();
-
- ConceptDecl *CD = ::getCommonDecl(AX->getTypeConstraintConcept(),
- AY->getTypeConstraintConcept());
- SmallVector<TemplateArgument, 8> As;
- if (CD &&
- getCommonTemplateArguments(Ctx, As, AX->getTypeConstraintArguments(),
- AY->getTypeConstraintArguments()))
- CD = nullptr; // The arguments
diff er, 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<ElaboratedType>(X), *EY = cast<ElaboratedType>(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<MacroQualifiedType>(X),
- *MY = cast<MacroQualifiedType>(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<SubstTemplateTypeParmType>(X),
- *SY = cast<SubstTemplateTypeParmType>(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<TemplateSpecializationType>(X),
- *TY = cast<TemplateSpecializationType>(Y);
- TemplateName CTN = ::getCommonTemplateName(Ctx, TX->getTemplateName(),
- TY->getTemplateName());
- if (!CTN.getAsVoidPointer())
- return QualType();
- SmallVector<TemplateArgument, 8> 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<TypedefType>(X), *TY = cast<TypedefType>(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<UnaryTransformType>(X),
- *UY = cast<UnaryTransformType>(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<UsingType>(X), *UY = cast<UsingType>(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<SplitQualType, 8> 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
diff er. 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
diff er, 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 82f6d9458dada..0e07a150a8b28 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 7ae3a873a3167..8c18d8add028a 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 <class T> struct S1 {
- template <class U> struct S2 {};
-};
-
-N t10 = 0 ? S1<X1>() : S1<Y1>(); // expected-error {{from 'S1<B1>' (aka 'S1<int>')}}
-N t11 = 0 ? S1<X1>::S2<X2>() : S1<Y1>::S2<Y2>(); // expected-error {{from 'S1<int>::S2<B2>' (aka 'S2<void>')}}
-
-template <class T> using Al = S1<T>;
-
-N t12 = 0 ? Al<X1>() : Al<Y1>(); // expected-error {{from 'Al<B1>' (aka 'S1<int>')}}
-
-#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 at -1 {{rvalue of type 'B1' (aka 'int')}}
-
-N t20 = 0 ? (__underlying_type(EnumsX::X)){} : (__underlying_type(EnumsY::X)){};
-// expected-error at -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 <class T> using Alias = short;
-N t24 = 0 ? (Alias<X1>){} : (Alias<Y1>){}; // expected-error {{rvalue of type 'Alias<B1>' (aka 'short')}}
-N t25 = 0 ? (Alias<X1>){} : (Alias<X2>){}; // expected-error {{rvalue of type 'short'}}
-
-template <class T, class U> concept C1 = true;
-template <class T, class U> concept C2 = true;
-C1<X1> auto t26_1 = (SB1){};
-C1<X2> auto t26_2 = (::SB1){};
-C2<X2> 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')}}
More information about the cfe-commits
mailing list