forked from OSchip/llvm-project
Revert "[clang] retain type sugar in auto / template argument deduction"
This reverts commit 9b6036deed
.
Breaks two libc++ tests.
This commit is contained in:
parent
c30c37c00a
commit
1d7fdbbc18
|
@ -134,9 +134,14 @@ void OwningMemoryCheck::registerMatchers(MatchFinder *Finder) {
|
|||
// Matching on initialization operations where the initial value is a newly
|
||||
// created owner, but the LHS is not an owner.
|
||||
Finder->addMatcher(
|
||||
traverse(TK_AsIs, namedDecl(varDecl(allOf(hasInitializer(CreatesOwner),
|
||||
unless(IsOwnerType)))
|
||||
.bind("bad_owner_creation_variable"))),
|
||||
traverse(
|
||||
TK_AsIs,
|
||||
namedDecl(
|
||||
varDecl(eachOf(allOf(hasInitializer(CreatesOwner),
|
||||
unless(IsOwnerType)),
|
||||
allOf(hasInitializer(ConsideredOwner),
|
||||
hasType(autoType().bind("deduced_type")))))
|
||||
.bind("bad_owner_creation_variable"))),
|
||||
this);
|
||||
|
||||
// Match on all function calls that expect owners as arguments, but didn't
|
||||
|
@ -319,6 +324,13 @@ bool OwningMemoryCheck::handleAssignmentFromNewOwner(const BoundNodes &Nodes) {
|
|||
|
||||
// FIXME: FixitHint to rewrite the type of the initialized variable
|
||||
// as 'gsl::owner<OriginalType>'
|
||||
|
||||
// If the type of the variable was deduced, the wrapping owner typedef is
|
||||
// eliminated, therefore the check emits a special note for that case.
|
||||
if (Nodes.getNodeAs<AutoType>("deduced_type")) {
|
||||
diag(BadOwnerInitialization->getBeginLoc(),
|
||||
"type deduction did not result in an owner", DiagnosticIDs::Note);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,11 +20,9 @@ void ProBoundsPointerArithmeticCheck::registerMatchers(MatchFinder *Finder) {
|
|||
if (!getLangOpts().CPlusPlus)
|
||||
return;
|
||||
|
||||
const auto AllPointerTypes =
|
||||
anyOf(hasType(pointerType()),
|
||||
hasType(autoType(
|
||||
hasDeducedType(hasUnqualifiedDesugaredType(pointerType())))),
|
||||
hasType(decltypeType(hasUnderlyingType(pointerType()))));
|
||||
const auto AllPointerTypes = anyOf(
|
||||
hasType(pointerType()), hasType(autoType(hasDeducedType(pointerType()))),
|
||||
hasType(decltypeType(hasUnderlyingType(pointerType()))));
|
||||
|
||||
// Flag all operators +, -, +=, -=, ++, -- that result in a pointer
|
||||
Finder->addMatcher(
|
||||
|
|
|
@ -125,22 +125,18 @@ void QualifiedAutoCheck::registerMatchers(MatchFinder *Finder) {
|
|||
};
|
||||
|
||||
auto IsBoundToType = refersToType(equalsBoundNode("type"));
|
||||
auto UnlessFunctionType = unless(hasUnqualifiedDesugaredType(functionType()));
|
||||
auto IsAutoDeducedToPointer = [](const auto &...InnerMatchers) {
|
||||
return autoType(hasDeducedType(
|
||||
hasUnqualifiedDesugaredType(pointerType(pointee(InnerMatchers...)))));
|
||||
};
|
||||
|
||||
Finder->addMatcher(
|
||||
ExplicitSingleVarDecl(hasType(IsAutoDeducedToPointer(UnlessFunctionType)),
|
||||
ExplicitSingleVarDecl(hasType(autoType(hasDeducedType(
|
||||
pointerType(pointee(unless(functionType())))))),
|
||||
"auto"),
|
||||
this);
|
||||
|
||||
Finder->addMatcher(
|
||||
ExplicitSingleVarDeclInTemplate(
|
||||
allOf(hasType(IsAutoDeducedToPointer(
|
||||
hasUnqualifiedType(qualType().bind("type")),
|
||||
UnlessFunctionType)),
|
||||
allOf(hasType(autoType(hasDeducedType(pointerType(
|
||||
pointee(hasUnqualifiedType(qualType().bind("type")),
|
||||
unless(functionType())))))),
|
||||
anyOf(hasAncestor(
|
||||
functionDecl(hasAnyTemplateArgument(IsBoundToType))),
|
||||
hasAncestor(classTemplateSpecializationDecl(
|
||||
|
|
|
@ -374,7 +374,7 @@ public:
|
|||
void VisitDeducedType(const DeducedType *DT) {
|
||||
// FIXME: In practice this doesn't work: the AutoType you find inside
|
||||
// TypeLoc never has a deduced type. https://llvm.org/PR42914
|
||||
Outer.add(DT->getDeducedType(), Flags);
|
||||
Outer.add(DT->getDeducedType(), Flags | Rel::Underlying);
|
||||
}
|
||||
void VisitDeducedTemplateSpecializationType(
|
||||
const DeducedTemplateSpecializationType *DTST) {
|
||||
|
|
|
@ -38,9 +38,10 @@ public:
|
|||
// For structured bindings, print canonical types. This is important because
|
||||
// for bindings that use the tuple_element protocol, the non-canonical types
|
||||
// would be "tuple_element<I, A>::type".
|
||||
// For "auto", we often prefer sugared types.
|
||||
// Not setting PrintCanonicalTypes for "auto" allows
|
||||
// SuppressDefaultTemplateArgs (set by default) to have an effect.
|
||||
// For "auto", we often prefer sugared types, but the AST doesn't currently
|
||||
// retain them in DeducedType. However, not setting PrintCanonicalTypes for
|
||||
// "auto" at least allows SuppressDefaultTemplateArgs (set by default) to
|
||||
// have an effect.
|
||||
StructuredBindingPolicy = TypeHintPolicy;
|
||||
StructuredBindingPolicy.PrintCanonicalTypes = true;
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ TEST(GetDeducedType, KwAutoKwDecltypeExpansion) {
|
|||
namespace ns1 { struct S {}; }
|
||||
^auto v = ns1::S{};
|
||||
)cpp",
|
||||
"ns1::S",
|
||||
"struct ns1::S",
|
||||
},
|
||||
{
|
||||
R"cpp( // decltype on struct
|
||||
|
@ -63,7 +63,7 @@ TEST(GetDeducedType, KwAutoKwDecltypeExpansion) {
|
|||
ns1::S& j = i;
|
||||
^decltype(auto) k = j;
|
||||
)cpp",
|
||||
"ns1::S &",
|
||||
"struct ns1::S &",
|
||||
},
|
||||
{
|
||||
R"cpp( // auto on template class
|
||||
|
@ -71,7 +71,7 @@ TEST(GetDeducedType, KwAutoKwDecltypeExpansion) {
|
|||
template<typename T> class Foo {};
|
||||
^auto v = Foo<X>();
|
||||
)cpp",
|
||||
"Foo<class X>",
|
||||
"class Foo<class X>",
|
||||
},
|
||||
{
|
||||
R"cpp( // auto on initializer list.
|
||||
|
@ -177,7 +177,8 @@ TEST(GetDeducedType, KwAutoKwDecltypeExpansion) {
|
|||
using Bar = Foo;
|
||||
^auto x = Bar();
|
||||
)cpp",
|
||||
"Bar",
|
||||
// FIXME: it'd be nice if this resolved to the alias instead
|
||||
"struct Foo",
|
||||
},
|
||||
};
|
||||
for (Test T : Tests) {
|
||||
|
|
|
@ -461,7 +461,7 @@ class Foo {})cpp";
|
|||
[](HoverInfo &HI) {
|
||||
HI.Name = "auto";
|
||||
HI.Kind = index::SymbolKind::TypeAlias;
|
||||
HI.Definition = "Foo<int>";
|
||||
HI.Definition = "class Foo<int>";
|
||||
}},
|
||||
// auto on specialized template
|
||||
{R"cpp(
|
||||
|
@ -474,7 +474,7 @@ class Foo {})cpp";
|
|||
[](HoverInfo &HI) {
|
||||
HI.Name = "auto";
|
||||
HI.Kind = index::SymbolKind::TypeAlias;
|
||||
HI.Definition = "Foo<int>";
|
||||
HI.Definition = "class Foo<int>";
|
||||
}},
|
||||
|
||||
// macro
|
||||
|
@ -648,7 +648,7 @@ class Foo {})cpp";
|
|||
[](HoverInfo &HI) {
|
||||
HI.Name = "auto";
|
||||
HI.Kind = index::SymbolKind::TypeAlias;
|
||||
HI.Definition = "Foo<X>";
|
||||
HI.Definition = "class Foo<X>";
|
||||
}},
|
||||
{// Falls back to primary template, when the type is not instantiated.
|
||||
R"cpp(
|
||||
|
@ -2024,7 +2024,7 @@ TEST(Hover, All) {
|
|||
[](HoverInfo &HI) {
|
||||
HI.Name = "auto";
|
||||
HI.Kind = index::SymbolKind::TypeAlias;
|
||||
HI.Definition = "int_type";
|
||||
HI.Definition = "int";
|
||||
}},
|
||||
{
|
||||
R"cpp(// auto on alias
|
||||
|
@ -2035,7 +2035,7 @@ TEST(Hover, All) {
|
|||
[](HoverInfo &HI) {
|
||||
HI.Name = "auto";
|
||||
HI.Kind = index::SymbolKind::TypeAlias;
|
||||
HI.Definition = "cls_type";
|
||||
HI.Definition = "struct cls";
|
||||
HI.Documentation = "auto on alias";
|
||||
}},
|
||||
{
|
||||
|
@ -2047,7 +2047,7 @@ TEST(Hover, All) {
|
|||
[](HoverInfo &HI) {
|
||||
HI.Name = "auto";
|
||||
HI.Kind = index::SymbolKind::TypeAlias;
|
||||
HI.Definition = "templ<int>";
|
||||
HI.Definition = "struct templ<int>";
|
||||
HI.Documentation = "auto on alias";
|
||||
}},
|
||||
{
|
||||
|
|
|
@ -466,14 +466,7 @@ TEST(TypeHints, NoQualifiers) {
|
|||
}
|
||||
}
|
||||
)cpp",
|
||||
ExpectedHint{": S1", "x"},
|
||||
// FIXME: We want to suppress scope specifiers
|
||||
// here because we are into the whole
|
||||
// brevity thing, but the ElaboratedType
|
||||
// printer does not honor the SuppressScope
|
||||
// flag by design, so we need to extend the
|
||||
// PrintingPolicy to support this use case.
|
||||
ExpectedHint{": S2::Inner<int>", "y"});
|
||||
ExpectedHint{": S1", "x"}, ExpectedHint{": Inner<int>", "y"});
|
||||
}
|
||||
|
||||
TEST(TypeHints, Lambda) {
|
||||
|
|
|
@ -57,7 +57,7 @@ TEST_F(ExpandAutoTypeTest, Test) {
|
|||
EXPECT_UNAVAILABLE("au^to x = []{};");
|
||||
// inline namespaces
|
||||
EXPECT_EQ(apply("au^to x = inl_ns::Visible();"),
|
||||
"inl_ns::Visible x = inl_ns::Visible();");
|
||||
"Visible x = inl_ns::Visible();");
|
||||
// local class
|
||||
EXPECT_EQ(apply("namespace x { void y() { struct S{}; ^auto z = S(); } }"),
|
||||
"namespace x { void y() { struct S{}; S z = S(); } }");
|
||||
|
@ -67,9 +67,8 @@ TEST_F(ExpandAutoTypeTest, Test) {
|
|||
|
||||
EXPECT_EQ(apply("ns::Class * foo() { au^to c = foo(); }"),
|
||||
"ns::Class * foo() { ns::Class * c = foo(); }");
|
||||
EXPECT_EQ(
|
||||
apply("void ns::Func() { au^to x = new ns::Class::Nested{}; }"),
|
||||
"void ns::Func() { ns::Class::Nested * x = new ns::Class::Nested{}; }");
|
||||
EXPECT_EQ(apply("void ns::Func() { au^to x = new ns::Class::Nested{}; }"),
|
||||
"void ns::Func() { Class::Nested * x = new ns::Class::Nested{}; }");
|
||||
|
||||
EXPECT_UNAVAILABLE("dec^ltype(au^to) x = 10;");
|
||||
// expanding types in structured bindings is syntactically invalid.
|
||||
|
|
|
@ -91,9 +91,13 @@ void test_assignment_and_initialization() {
|
|||
// FIXME:, flow analysis for the case of reassignment. Value must be released before
|
||||
owned_int6 = owned_int3; // BAD, because reassignment without resource release
|
||||
|
||||
auto owned_int7 = returns_owner1(); // Ok, since type deduction does not eliminate the owner wrapper
|
||||
auto owned_int7 = returns_owner1(); // Bad, since type deduction eliminates the owner wrapper
|
||||
// CHECK-NOTES: [[@LINE-1]]:3: warning: initializing non-owner 'int *' with a newly created 'gsl::owner<>'
|
||||
// CHECK-NOTES: [[@LINE-2]]:3: note: type deduction did not result in an owner
|
||||
|
||||
const auto owned_int8 = returns_owner2(); // Ok, since type deduction does not eliminate the owner wrapper
|
||||
const auto owned_int8 = returns_owner2(); // Bad, since type deduction eliminates the owner wrapper
|
||||
// CHECK-NOTES: [[@LINE-1]]:3: warning: initializing non-owner 'int *const' with a newly created 'gsl::owner<>'
|
||||
// CHECK-NOTES: [[@LINE-2]]:3: note: type deduction did not result in an owner
|
||||
|
||||
gsl::owner<int *> owned_int9 = returns_owner1(); // Ok
|
||||
int *unowned_int3 = returns_owner1(); // Bad
|
||||
|
@ -281,12 +285,15 @@ void test_class_with_owner() {
|
|||
ClassWithOwner C2{A}; // Bad, since the owner would be initialized with an non-owner, but catched in the class
|
||||
ClassWithOwner C3{gsl::owner<ArbitraryClass *>(new ArbitraryClass)}; // Ok
|
||||
|
||||
const auto Owner1 = C3.buggy_but_returns_owner(); // Ok, deduces Owner1 to owner<ArbitraryClass *> const
|
||||
const auto Owner1 = C3.buggy_but_returns_owner(); // BAD, deduces Owner1 to ArbitraryClass *const
|
||||
// CHECK-NOTES: [[@LINE-1]]:3: warning: initializing non-owner 'ArbitraryClass *const' with a newly created 'gsl::owner<>'
|
||||
// CHECK-NOTES: [[@LINE-2]]:3: note: type deduction did not result in an owner
|
||||
|
||||
auto Owner2 = C2.buggy_but_returns_owner(); //Ok, deduces Owner2 to owner<ArbitraryClass *>
|
||||
auto Owner2 = C2.buggy_but_returns_owner(); // BAD, deduces Owner2 to ArbitraryClass *
|
||||
// CHECK-NOTES: [[@LINE-1]]:3: warning: initializing non-owner 'ArbitraryClass *' with a newly created 'gsl::owner<>'
|
||||
// CHECK-NOTES: [[@LINE-2]]:3: note: type deduction did not result in an owner
|
||||
|
||||
Owner2 = &A; // BAD, since type deduction resulted in owner<ArbitraryClass *>
|
||||
// CHECK-NOTES: [[@LINE-1]]:3: warning: expected assignment source to be of type 'gsl::owner<>'; got 'ArbitraryClass *'
|
||||
Owner2 = &A; // Ok, since type deduction did NOT result in owner<int*>
|
||||
|
||||
gsl::owner<ArbitraryClass *> Owner3 = C1.buggy_but_returns_owner(); // Ok, still an owner
|
||||
Owner3 = &A; // Bad, since assignment of non-owner to owner
|
||||
|
|
|
@ -1531,12 +1531,6 @@ private:
|
|||
QualType getFunctionTypeInternal(QualType ResultTy, ArrayRef<QualType> Args,
|
||||
const FunctionProtoType::ExtProtoInfo &EPI,
|
||||
bool OnlyWantCanonical) const;
|
||||
QualType
|
||||
getAutoTypeInternal(QualType DeducedType, AutoTypeKeyword Keyword,
|
||||
bool IsDependent, bool IsPack = false,
|
||||
ConceptDecl *TypeConstraintConcept = nullptr,
|
||||
ArrayRef<TemplateArgument> TypeConstraintArgs = {},
|
||||
bool IsCanon = false) const;
|
||||
|
||||
public:
|
||||
/// Return the unique reference to the type for the specified type
|
||||
|
|
|
@ -4944,29 +4944,29 @@ public:
|
|||
/// type-dependent, there is no deduced type and the type is canonical. In
|
||||
/// the latter case, it is also a dependent type.
|
||||
class DeducedType : public Type {
|
||||
QualType DeducedAsType;
|
||||
|
||||
protected:
|
||||
DeducedType(TypeClass TC, QualType DeducedAsType,
|
||||
TypeDependence ExtraDependence, QualType Canon)
|
||||
: Type(TC, Canon,
|
||||
TypeDependence ExtraDependence)
|
||||
: Type(TC,
|
||||
// FIXME: Retain the sugared deduced type?
|
||||
DeducedAsType.isNull() ? QualType(this, 0)
|
||||
: DeducedAsType.getCanonicalType(),
|
||||
ExtraDependence | (DeducedAsType.isNull()
|
||||
? TypeDependence::None
|
||||
: DeducedAsType->getDependence() &
|
||||
~TypeDependence::VariablyModified)),
|
||||
DeducedAsType(DeducedAsType) {}
|
||||
~TypeDependence::VariablyModified)) {}
|
||||
|
||||
public:
|
||||
bool isSugared() const { return !DeducedAsType.isNull(); }
|
||||
QualType desugar() const {
|
||||
return isSugared() ? DeducedAsType : QualType(this, 0);
|
||||
}
|
||||
bool isSugared() const { return !isCanonicalUnqualified(); }
|
||||
QualType desugar() const { return getCanonicalTypeInternal(); }
|
||||
|
||||
/// Get the type deduced for this placeholder type, or null if it
|
||||
/// has not been deduced.
|
||||
QualType getDeducedType() const { return DeducedAsType; }
|
||||
/// Get the type deduced for this placeholder type, or null if it's
|
||||
/// either not been deduced or was deduced to a dependent type.
|
||||
QualType getDeducedType() const {
|
||||
return !isCanonicalUnqualified() ? getCanonicalTypeInternal() : QualType();
|
||||
}
|
||||
bool isDeduced() const {
|
||||
return !DeducedAsType.isNull() || isDependentType();
|
||||
return !isCanonicalUnqualified() || isDependentType();
|
||||
}
|
||||
|
||||
static bool classof(const Type *T) {
|
||||
|
@ -4983,7 +4983,7 @@ class alignas(8) AutoType : public DeducedType, public llvm::FoldingSetNode {
|
|||
ConceptDecl *TypeConstraintConcept;
|
||||
|
||||
AutoType(QualType DeducedAsType, AutoTypeKeyword Keyword,
|
||||
TypeDependence ExtraDependence, QualType Canon, ConceptDecl *CD,
|
||||
TypeDependence ExtraDependence, ConceptDecl *CD,
|
||||
ArrayRef<TemplateArgument> TypeConstraintArgs);
|
||||
|
||||
const TemplateArgument *getArgBuffer() const {
|
||||
|
@ -5057,9 +5057,7 @@ class DeducedTemplateSpecializationType : public DeducedType,
|
|||
toTypeDependence(Template.getDependence()) |
|
||||
(IsDeducedAsDependent
|
||||
? TypeDependence::DependentInstantiation
|
||||
: TypeDependence::None),
|
||||
DeducedAsType.isNull() ? QualType(this, 0)
|
||||
: DeducedAsType.getCanonicalType()),
|
||||
: TypeDependence::None)),
|
||||
Template(Template) {}
|
||||
|
||||
public:
|
||||
|
|
|
@ -1027,29 +1027,31 @@ private:
|
|||
BoundNodesTreeBuilder *Builder) const {
|
||||
// DeducedType does not have declarations of its own, so
|
||||
// match the deduced type instead.
|
||||
const Type *EffectiveType = &Node;
|
||||
if (const auto *S = dyn_cast<DeducedType>(&Node)) {
|
||||
QualType DT = S->getDeducedType();
|
||||
return !DT.isNull() ? matchesSpecialized(*DT, Finder, Builder) : false;
|
||||
EffectiveType = S->getDeducedType().getTypePtrOrNull();
|
||||
if (!EffectiveType)
|
||||
return false;
|
||||
}
|
||||
|
||||
// First, for any types that have a declaration, extract the declaration and
|
||||
// match on it.
|
||||
if (const auto *S = dyn_cast<TagType>(&Node)) {
|
||||
if (const auto *S = dyn_cast<TagType>(EffectiveType)) {
|
||||
return matchesDecl(S->getDecl(), Finder, Builder);
|
||||
}
|
||||
if (const auto *S = dyn_cast<InjectedClassNameType>(&Node)) {
|
||||
if (const auto *S = dyn_cast<InjectedClassNameType>(EffectiveType)) {
|
||||
return matchesDecl(S->getDecl(), Finder, Builder);
|
||||
}
|
||||
if (const auto *S = dyn_cast<TemplateTypeParmType>(&Node)) {
|
||||
if (const auto *S = dyn_cast<TemplateTypeParmType>(EffectiveType)) {
|
||||
return matchesDecl(S->getDecl(), Finder, Builder);
|
||||
}
|
||||
if (const auto *S = dyn_cast<TypedefType>(&Node)) {
|
||||
if (const auto *S = dyn_cast<TypedefType>(EffectiveType)) {
|
||||
return matchesDecl(S->getDecl(), Finder, Builder);
|
||||
}
|
||||
if (const auto *S = dyn_cast<UnresolvedUsingType>(&Node)) {
|
||||
if (const auto *S = dyn_cast<UnresolvedUsingType>(EffectiveType)) {
|
||||
return matchesDecl(S->getDecl(), Finder, Builder);
|
||||
}
|
||||
if (const auto *S = dyn_cast<ObjCObjectType>(&Node)) {
|
||||
if (const auto *S = dyn_cast<ObjCObjectType>(EffectiveType)) {
|
||||
return matchesDecl(S->getInterface(), Finder, Builder);
|
||||
}
|
||||
|
||||
|
@ -1061,14 +1063,14 @@ private:
|
|||
// template<typename T> struct X { T t; } class A {}; X<A> a;
|
||||
// The following matcher will match, which otherwise would not:
|
||||
// fieldDecl(hasType(pointerType())).
|
||||
if (const auto *S = dyn_cast<SubstTemplateTypeParmType>(&Node)) {
|
||||
if (const auto *S = dyn_cast<SubstTemplateTypeParmType>(EffectiveType)) {
|
||||
return matchesSpecialized(S->getReplacementType(), Finder, Builder);
|
||||
}
|
||||
|
||||
// For template specialization types, we want to match the template
|
||||
// declaration, as long as the type is still dependent, and otherwise the
|
||||
// declaration of the instantiated tag type.
|
||||
if (const auto *S = dyn_cast<TemplateSpecializationType>(&Node)) {
|
||||
if (const auto *S = dyn_cast<TemplateSpecializationType>(EffectiveType)) {
|
||||
if (!S->isTypeAlias() && S->isSugared()) {
|
||||
// If the template is non-dependent, we want to match the instantiated
|
||||
// tag type.
|
||||
|
@ -1087,7 +1089,7 @@ private:
|
|||
// FIXME: We desugar elaborated types. This makes the assumption that users
|
||||
// do never want to match on whether a type is elaborated - there are
|
||||
// arguments for both sides; for now, continue desugaring.
|
||||
if (const auto *S = dyn_cast<ElaboratedType>(&Node)) {
|
||||
if (const auto *S = dyn_cast<ElaboratedType>(EffectiveType)) {
|
||||
return matchesSpecialized(S->desugar(), Finder, Builder);
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -2359,13 +2359,11 @@ public:
|
|||
const CXXScopeSpec &SS, QualType T,
|
||||
TagDecl *OwnedTagDecl = nullptr);
|
||||
|
||||
// Returns the underlying type of a decltype with the given expression.
|
||||
QualType getDecltypeForExpr(Expr *E);
|
||||
|
||||
QualType BuildTypeofExprType(Expr *E);
|
||||
QualType BuildTypeofExprType(Expr *E, SourceLocation Loc);
|
||||
/// If AsUnevaluated is false, E is treated as though it were an evaluated
|
||||
/// context, such as when building a type for decltype(auto).
|
||||
QualType BuildDecltypeType(Expr *E, bool AsUnevaluated = true);
|
||||
QualType BuildDecltypeType(Expr *E, SourceLocation Loc,
|
||||
bool AsUnevaluated = true);
|
||||
QualType BuildUnaryTransformType(QualType BaseType,
|
||||
UnaryTransformType::UTTKind UKind,
|
||||
SourceLocation Loc);
|
||||
|
@ -3504,7 +3502,7 @@ public:
|
|||
bool IsFunctionConversion(QualType FromType, QualType ToType,
|
||||
QualType &ResultTy);
|
||||
bool DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType);
|
||||
bool isSameOrCompatibleFunctionType(QualType Param, QualType Arg);
|
||||
bool isSameOrCompatibleFunctionType(CanQualType Param, CanQualType Arg);
|
||||
|
||||
bool CanPerformAggregateInitializationForOverloadResolution(
|
||||
const InitializedEntity &Entity, InitListExpr *From);
|
||||
|
@ -8567,14 +8565,6 @@ public:
|
|||
/// Substitute Replacement for auto in TypeWithAuto
|
||||
TypeSourceInfo* SubstAutoTypeSourceInfo(TypeSourceInfo *TypeWithAuto,
|
||||
QualType Replacement);
|
||||
|
||||
// Substitute auto in TypeWithAuto for a Dependent auto type
|
||||
QualType SubstAutoTypeDependent(QualType TypeWithAuto);
|
||||
|
||||
// Substitute auto in TypeWithAuto for a Dependent auto type
|
||||
TypeSourceInfo *
|
||||
SubstAutoTypeSourceInfoDependent(TypeSourceInfo *TypeWithAuto);
|
||||
|
||||
/// Completely replace the \c auto in \p TypeWithAuto by
|
||||
/// \p Replacement. This does not retain any \c auto type sugar.
|
||||
QualType ReplaceAutoType(QualType TypeWithAuto, QualType Replacement);
|
||||
|
|
|
@ -4815,23 +4815,6 @@ ASTContext::getTemplateSpecializationType(TemplateName Template,
|
|||
return QualType(Spec, 0);
|
||||
}
|
||||
|
||||
static bool
|
||||
getCanonicalTemplateArguments(const ASTContext &C,
|
||||
ArrayRef<TemplateArgument> OrigArgs,
|
||||
SmallVectorImpl<TemplateArgument> &CanonArgs) {
|
||||
bool AnyNonCanonArgs = false;
|
||||
unsigned NumArgs = OrigArgs.size();
|
||||
CanonArgs.resize(NumArgs);
|
||||
for (unsigned I = 0; I != NumArgs; ++I) {
|
||||
const TemplateArgument &OrigArg = OrigArgs[I];
|
||||
TemplateArgument &CanonArg = CanonArgs[I];
|
||||
CanonArg = C.getCanonicalTemplateArgument(OrigArg);
|
||||
if (!CanonArg.structurallyEquals(OrigArg))
|
||||
AnyNonCanonArgs = true;
|
||||
}
|
||||
return AnyNonCanonArgs;
|
||||
}
|
||||
|
||||
QualType ASTContext::getCanonicalTemplateSpecializationType(
|
||||
TemplateName Template, ArrayRef<TemplateArgument> Args) const {
|
||||
assert(!Template.getAsDependentTemplateName() &&
|
||||
|
@ -4844,7 +4827,10 @@ QualType ASTContext::getCanonicalTemplateSpecializationType(
|
|||
// Build the canonical template specialization type.
|
||||
TemplateName CanonTemplate = getCanonicalTemplateName(Template);
|
||||
SmallVector<TemplateArgument, 4> CanonArgs;
|
||||
::getCanonicalTemplateArguments(*this, Args, CanonArgs);
|
||||
unsigned NumArgs = Args.size();
|
||||
CanonArgs.reserve(NumArgs);
|
||||
for (const TemplateArgument &Arg : Args)
|
||||
CanonArgs.push_back(getCanonicalTemplateArgument(Arg));
|
||||
|
||||
// Determine whether this canonical template specialization type already
|
||||
// exists.
|
||||
|
@ -4859,7 +4845,7 @@ QualType ASTContext::getCanonicalTemplateSpecializationType(
|
|||
if (!Spec) {
|
||||
// Allocate a new canonical template specialization type.
|
||||
void *Mem = Allocate((sizeof(TemplateSpecializationType) +
|
||||
sizeof(TemplateArgument) * CanonArgs.size()),
|
||||
sizeof(TemplateArgument) * NumArgs),
|
||||
TypeAlignment);
|
||||
Spec = new (Mem) TemplateSpecializationType(CanonTemplate,
|
||||
CanonArgs,
|
||||
|
@ -5001,9 +4987,14 @@ ASTContext::getDependentTemplateSpecializationType(
|
|||
ElaboratedTypeKeyword CanonKeyword = Keyword;
|
||||
if (Keyword == ETK_None) CanonKeyword = ETK_Typename;
|
||||
|
||||
SmallVector<TemplateArgument, 16> CanonArgs;
|
||||
bool AnyNonCanonArgs =
|
||||
::getCanonicalTemplateArguments(*this, Args, CanonArgs);
|
||||
bool AnyNonCanonArgs = false;
|
||||
unsigned NumArgs = Args.size();
|
||||
SmallVector<TemplateArgument, 16> CanonArgs(NumArgs);
|
||||
for (unsigned I = 0; I != NumArgs; ++I) {
|
||||
CanonArgs[I] = getCanonicalTemplateArgument(Args[I]);
|
||||
if (!CanonArgs[I].structurallyEquals(Args[I]))
|
||||
AnyNonCanonArgs = true;
|
||||
}
|
||||
|
||||
QualType Canon;
|
||||
if (AnyNonCanonArgs || CanonNNS != NNS || CanonKeyword != Keyword) {
|
||||
|
@ -5016,7 +5007,7 @@ ASTContext::getDependentTemplateSpecializationType(
|
|||
}
|
||||
|
||||
void *Mem = Allocate((sizeof(DependentTemplateSpecializationType) +
|
||||
sizeof(TemplateArgument) * Args.size()),
|
||||
sizeof(TemplateArgument) * NumArgs),
|
||||
TypeAlignment);
|
||||
T = new (Mem) DependentTemplateSpecializationType(Keyword, NNS,
|
||||
Name, Args, Canon);
|
||||
|
@ -5598,10 +5589,15 @@ QualType ASTContext::getUnaryTransformType(QualType BaseType,
|
|||
return QualType(ut, 0);
|
||||
}
|
||||
|
||||
QualType ASTContext::getAutoTypeInternal(
|
||||
QualType DeducedType, AutoTypeKeyword Keyword, bool IsDependent,
|
||||
bool IsPack, ConceptDecl *TypeConstraintConcept,
|
||||
ArrayRef<TemplateArgument> TypeConstraintArgs, bool IsCanon) const {
|
||||
/// getAutoType - Return the uniqued reference to the 'auto' type which has been
|
||||
/// deduced to the given type, or to the canonical undeduced 'auto' type, or the
|
||||
/// canonical deduced-but-dependent 'auto' type.
|
||||
QualType
|
||||
ASTContext::getAutoType(QualType DeducedType, AutoTypeKeyword Keyword,
|
||||
bool IsDependent, bool IsPack,
|
||||
ConceptDecl *TypeConstraintConcept,
|
||||
ArrayRef<TemplateArgument> TypeConstraintArgs) const {
|
||||
assert((!IsPack || IsDependent) && "only use IsPack for a dependent pack");
|
||||
if (DeducedType.isNull() && Keyword == AutoTypeKeyword::Auto &&
|
||||
!TypeConstraintConcept && !IsDependent)
|
||||
return getAutoDeductType();
|
||||
|
@ -5614,52 +5610,21 @@ QualType ASTContext::getAutoTypeInternal(
|
|||
if (AutoType *AT = AutoTypes.FindNodeOrInsertPos(ID, InsertPos))
|
||||
return QualType(AT, 0);
|
||||
|
||||
QualType Canon;
|
||||
if (!IsCanon) {
|
||||
if (DeducedType.isNull()) {
|
||||
SmallVector<TemplateArgument, 4> CanonArgs;
|
||||
bool AnyNonCanonArgs =
|
||||
::getCanonicalTemplateArguments(*this, TypeConstraintArgs, CanonArgs);
|
||||
if (AnyNonCanonArgs) {
|
||||
Canon = getAutoTypeInternal(QualType(), Keyword, IsDependent, IsPack,
|
||||
TypeConstraintConcept, CanonArgs, true);
|
||||
// Find the insert position again.
|
||||
AutoTypes.FindNodeOrInsertPos(ID, InsertPos);
|
||||
}
|
||||
} else {
|
||||
Canon = DeducedType.getCanonicalType();
|
||||
}
|
||||
}
|
||||
|
||||
void *Mem = Allocate(sizeof(AutoType) +
|
||||
sizeof(TemplateArgument) * TypeConstraintArgs.size(),
|
||||
sizeof(TemplateArgument) * TypeConstraintArgs.size(),
|
||||
TypeAlignment);
|
||||
auto *AT = new (Mem) AutoType(
|
||||
DeducedType, Keyword,
|
||||
(IsDependent ? TypeDependence::DependentInstantiation
|
||||
: TypeDependence::None) |
|
||||
(IsPack ? TypeDependence::UnexpandedPack : TypeDependence::None),
|
||||
Canon, TypeConstraintConcept, TypeConstraintArgs);
|
||||
TypeConstraintConcept, TypeConstraintArgs);
|
||||
Types.push_back(AT);
|
||||
AutoTypes.InsertNode(AT, InsertPos);
|
||||
if (InsertPos)
|
||||
AutoTypes.InsertNode(AT, InsertPos);
|
||||
return QualType(AT, 0);
|
||||
}
|
||||
|
||||
/// getAutoType - Return the uniqued reference to the 'auto' type which has been
|
||||
/// deduced to the given type, or to the canonical undeduced 'auto' type, or the
|
||||
/// canonical deduced-but-dependent 'auto' type.
|
||||
QualType
|
||||
ASTContext::getAutoType(QualType DeducedType, AutoTypeKeyword Keyword,
|
||||
bool IsDependent, bool IsPack,
|
||||
ConceptDecl *TypeConstraintConcept,
|
||||
ArrayRef<TemplateArgument> TypeConstraintArgs) const {
|
||||
assert((!IsPack || IsDependent) && "only use IsPack for a dependent pack");
|
||||
assert((!IsDependent || DeducedType.isNull()) &&
|
||||
"A dependent auto should be undeduced");
|
||||
return getAutoTypeInternal(DeducedType, Keyword, IsDependent, IsPack,
|
||||
TypeConstraintConcept, TypeConstraintArgs);
|
||||
}
|
||||
|
||||
/// Return the uniqued reference to the deduced template specialization type
|
||||
/// which has been deduced to the given type, or to the canonical undeduced
|
||||
/// such type, or the canonical deduced-but-dependent such type.
|
||||
|
@ -5677,7 +5642,8 @@ QualType ASTContext::getDeducedTemplateSpecializationType(
|
|||
auto *DTST = new (*this, TypeAlignment)
|
||||
DeducedTemplateSpecializationType(Template, DeducedType, IsDependent);
|
||||
Types.push_back(DTST);
|
||||
DeducedTemplateSpecializationTypes.InsertNode(DTST, InsertPos);
|
||||
if (InsertPos)
|
||||
DeducedTemplateSpecializationTypes.InsertNode(DTST, InsertPos);
|
||||
return QualType(DTST, 0);
|
||||
}
|
||||
|
||||
|
@ -5714,7 +5680,7 @@ QualType ASTContext::getAutoDeductType() const {
|
|||
if (AutoDeductTy.isNull())
|
||||
AutoDeductTy = QualType(new (*this, TypeAlignment)
|
||||
AutoType(QualType(), AutoTypeKeyword::Auto,
|
||||
TypeDependence::None, QualType(),
|
||||
TypeDependence::None,
|
||||
/*concept*/ nullptr, /*args*/ {}),
|
||||
0);
|
||||
return AutoDeductTy;
|
||||
|
|
|
@ -3172,14 +3172,13 @@ static bool isAncestorDeclContextOf(const DeclContext *DC, const Decl *D) {
|
|||
|
||||
bool ASTNodeImporter::hasAutoReturnTypeDeclaredInside(FunctionDecl *D) {
|
||||
QualType FromTy = D->getType();
|
||||
const auto *FromFPT = FromTy->getAs<FunctionProtoType>();
|
||||
const FunctionProtoType *FromFPT = FromTy->getAs<FunctionProtoType>();
|
||||
assert(FromFPT && "Must be called on FunctionProtoType");
|
||||
if (const AutoType *AutoT =
|
||||
FromFPT->getReturnType()->getContainedAutoType()) {
|
||||
if (AutoType *AutoT = FromFPT->getReturnType()->getContainedAutoType()) {
|
||||
QualType DeducedT = AutoT->getDeducedType();
|
||||
if (const auto *RecordT =
|
||||
!DeducedT.isNull() ? DeducedT->getAs<RecordType>() : nullptr) {
|
||||
const RecordDecl *RD = RecordT->getDecl();
|
||||
if (const RecordType *RecordT =
|
||||
DeducedT.isNull() ? nullptr : dyn_cast<RecordType>(DeducedT)) {
|
||||
RecordDecl *RD = RecordT->getDecl();
|
||||
assert(RD);
|
||||
if (isAncestorDeclContextOf(D, RD)) {
|
||||
assert(RD->getLexicalDeclContext() == RD->getDeclContext());
|
||||
|
@ -3187,8 +3186,9 @@ bool ASTNodeImporter::hasAutoReturnTypeDeclaredInside(FunctionDecl *D) {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (const auto *TypedefT = FromFPT->getReturnType()->getAs<TypedefType>()) {
|
||||
const TypedefNameDecl *TD = TypedefT->getDecl();
|
||||
if (const TypedefType *TypedefT =
|
||||
dyn_cast<TypedefType>(FromFPT->getReturnType())) {
|
||||
TypedefNameDecl *TD = TypedefT->getDecl();
|
||||
assert(TD);
|
||||
if (isAncestorDeclContextOf(D, TD)) {
|
||||
assert(TD->getLexicalDeclContext() == TD->getDeclContext());
|
||||
|
|
|
@ -4400,10 +4400,10 @@ void clang::FixedPointValueToString(SmallVectorImpl<char> &Str,
|
|||
}
|
||||
|
||||
AutoType::AutoType(QualType DeducedAsType, AutoTypeKeyword Keyword,
|
||||
TypeDependence ExtraDependence, QualType Canon,
|
||||
TypeDependence ExtraDependence,
|
||||
ConceptDecl *TypeConstraintConcept,
|
||||
ArrayRef<TemplateArgument> TypeConstraintArgs)
|
||||
: DeducedType(Auto, DeducedAsType, ExtraDependence, Canon) {
|
||||
: DeducedType(Auto, DeducedAsType, ExtraDependence) {
|
||||
AutoTypeBits.Keyword = (unsigned)Keyword;
|
||||
AutoTypeBits.NumArgs = TypeConstraintArgs.size();
|
||||
this->TypeConstraintConcept = TypeConstraintConcept;
|
||||
|
|
|
@ -865,7 +865,7 @@ bool Sema::ActOnCXXNestedNameSpecifierDecltype(CXXScopeSpec &SS,
|
|||
|
||||
assert(DS.getTypeSpecType() == DeclSpec::TST_decltype);
|
||||
|
||||
QualType T = BuildDecltypeType(DS.getRepAsExpr());
|
||||
QualType T = BuildDecltypeType(DS.getRepAsExpr(), DS.getTypeSpecTypeLoc());
|
||||
if (T.isNull())
|
||||
return true;
|
||||
|
||||
|
|
|
@ -3613,14 +3613,14 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD,
|
|||
// defined, copy the deduced value from the old declaration.
|
||||
AutoType *OldAT = Old->getReturnType()->getContainedAutoType();
|
||||
if (OldAT && OldAT->isDeduced()) {
|
||||
QualType DT = OldAT->getDeducedType();
|
||||
if (DT.isNull()) {
|
||||
New->setType(SubstAutoTypeDependent(New->getType()));
|
||||
NewQType = Context.getCanonicalType(SubstAutoTypeDependent(NewQType));
|
||||
} else {
|
||||
New->setType(SubstAutoType(New->getType(), DT));
|
||||
NewQType = Context.getCanonicalType(SubstAutoType(NewQType, DT));
|
||||
}
|
||||
New->setType(
|
||||
SubstAutoType(New->getType(),
|
||||
OldAT->isDependentType() ? Context.DependentTy
|
||||
: OldAT->getDeducedType()));
|
||||
NewQType = Context.getCanonicalType(
|
||||
SubstAutoType(NewQType,
|
||||
OldAT->isDependentType() ? Context.DependentTy
|
||||
: OldAT->getDeducedType()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9258,7 +9258,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
|||
// a friend yet, so 'isDependentContext' on the FD doesn't work.
|
||||
const FunctionProtoType *FPT =
|
||||
NewFD->getType()->castAs<FunctionProtoType>();
|
||||
QualType Result = SubstAutoTypeDependent(FPT->getReturnType());
|
||||
QualType Result =
|
||||
SubstAutoType(FPT->getReturnType(), Context.DependentTy);
|
||||
NewFD->setType(Context.getFunctionType(Result, FPT->getParamTypes(),
|
||||
FPT->getExtProtoInfo()));
|
||||
}
|
||||
|
@ -12349,7 +12350,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {
|
|||
/*TreatUnavailableAsInvalid=*/false);
|
||||
ExprResult Result = InitSeq.Perform(*this, Entity, Kind, Args, &DclT);
|
||||
if (Result.isInvalid()) {
|
||||
// If the provided initializer fails to initialize the var decl,
|
||||
// If the provied initializer fails to initialize the var decl,
|
||||
// we attach a recovery expr for better recovery.
|
||||
auto RecoveryExpr =
|
||||
CreateRecoveryExpr(Init->getBeginLoc(), Init->getEndLoc(), Args);
|
||||
|
|
|
@ -4219,7 +4219,7 @@ Sema::BuildMemInitializer(Decl *ConstructorD,
|
|||
if (BaseType.isNull())
|
||||
return true;
|
||||
} else if (DS.getTypeSpecType() == TST_decltype) {
|
||||
BaseType = BuildDecltypeType(DS.getRepAsExpr());
|
||||
BaseType = BuildDecltypeType(DS.getRepAsExpr(), DS.getTypeSpecTypeLoc());
|
||||
} else if (DS.getTypeSpecType() == TST_decltype_auto) {
|
||||
Diag(DS.getTypeSpecTypeLoc(), diag::err_decltype_auto_invalid);
|
||||
return true;
|
||||
|
|
|
@ -468,7 +468,7 @@ ParsedType Sema::getDestructorTypeForDecltype(const DeclSpec &DS,
|
|||
|
||||
assert(DS.getTypeSpecType() == DeclSpec::TST_decltype &&
|
||||
"unexpected type in getDestructorType");
|
||||
QualType T = BuildDecltypeType(DS.getRepAsExpr());
|
||||
QualType T = BuildDecltypeType(DS.getRepAsExpr(), DS.getTypeSpecTypeLoc());
|
||||
|
||||
// If we know the type of the object, check that the correct destructor
|
||||
// type was named now; we can give better diagnostics this way.
|
||||
|
@ -7761,7 +7761,8 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
|
|||
return true;
|
||||
}
|
||||
|
||||
QualType T = BuildDecltypeType(DS.getRepAsExpr(), /*AsUnevaluated=*/false);
|
||||
QualType T = BuildDecltypeType(DS.getRepAsExpr(), DS.getTypeSpecTypeLoc(),
|
||||
false);
|
||||
|
||||
TypeLocBuilder TLB;
|
||||
DecltypeTypeLoc DecltypeTL = TLB.push<DecltypeTypeLoc>(T);
|
||||
|
|
|
@ -9972,7 +9972,7 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer(
|
|||
|
||||
auto TemplateName = DeducedTST->getTemplateName();
|
||||
if (TemplateName.isDependent())
|
||||
return SubstAutoTypeDependent(TSInfo->getType());
|
||||
return SubstAutoType(TSInfo->getType(), Context.DependentTy);
|
||||
|
||||
// We can only perform deduction for class templates.
|
||||
auto *Template =
|
||||
|
@ -9991,7 +9991,7 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer(
|
|||
Diag(TSInfo->getTypeLoc().getBeginLoc(),
|
||||
diag::warn_cxx14_compat_class_template_argument_deduction)
|
||||
<< TSInfo->getTypeLoc().getSourceRange() << 0;
|
||||
return SubstAutoTypeDependent(TSInfo->getType());
|
||||
return SubstAutoType(TSInfo->getType(), Context.DependentTy);
|
||||
}
|
||||
|
||||
// FIXME: Perform "exact type" matching first, per CWG discussion?
|
||||
|
|
|
@ -373,7 +373,7 @@ CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class,
|
|||
const FunctionProtoType *FPT = MethodType->castAs<FunctionProtoType>();
|
||||
QualType Result = FPT->getReturnType();
|
||||
if (Result->isUndeducedType()) {
|
||||
Result = SubstAutoTypeDependent(Result);
|
||||
Result = SubstAutoType(Result, Context.DependentTy);
|
||||
MethodType = Context.getFunctionType(Result, FPT->getParamTypes(),
|
||||
FPT->getExtProtoInfo());
|
||||
}
|
||||
|
|
|
@ -2759,7 +2759,7 @@ StmtResult Sema::BuildCXXForRangeStmt(SourceLocation ForLoc,
|
|||
if (auto *DD = dyn_cast<DecompositionDecl>(LoopVar))
|
||||
for (auto *Binding : DD->bindings())
|
||||
Binding->setType(Context.DependentTy);
|
||||
LoopVar->setType(SubstAutoTypeDependent(LoopVar->getType()));
|
||||
LoopVar->setType(SubstAutoType(LoopVar->getType(), Context.DependentTy));
|
||||
}
|
||||
} else if (!BeginDeclStmt.get()) {
|
||||
SourceLocation RangeLoc = RangeVar->getLocation();
|
||||
|
|
|
@ -1259,15 +1259,15 @@ bool Sema::AttachTypeConstraint(AutoTypeLoc TL, NonTypeTemplateParmDecl *NTTP,
|
|||
BuildDeclRefExpr(NTTP, NTTP->getType(), VK_PRValue, NTTP->getLocation());
|
||||
if (!Ref)
|
||||
return true;
|
||||
ExprResult ImmediatelyDeclaredConstraint = formImmediatelyDeclaredConstraint(
|
||||
*this, TL.getNestedNameSpecifierLoc(), TL.getConceptNameInfo(),
|
||||
TL.getNamedConcept(), TL.getLAngleLoc(), TL.getRAngleLoc(),
|
||||
BuildDecltypeType(Ref), NTTP->getLocation(),
|
||||
[&](TemplateArgumentListInfo &ConstraintArgs) {
|
||||
for (unsigned I = 0, C = TL.getNumArgs(); I != C; ++I)
|
||||
ConstraintArgs.addArgument(TL.getArgLoc(I));
|
||||
},
|
||||
EllipsisLoc);
|
||||
ExprResult ImmediatelyDeclaredConstraint =
|
||||
formImmediatelyDeclaredConstraint(
|
||||
*this, TL.getNestedNameSpecifierLoc(), TL.getConceptNameInfo(),
|
||||
TL.getNamedConcept(), TL.getLAngleLoc(), TL.getRAngleLoc(),
|
||||
BuildDecltypeType(Ref, NTTP->getLocation()), NTTP->getLocation(),
|
||||
[&] (TemplateArgumentListInfo &ConstraintArgs) {
|
||||
for (unsigned I = 0, C = TL.getNumArgs(); I != C; ++I)
|
||||
ConstraintArgs.addArgument(TL.getArgLoc(I));
|
||||
}, EllipsisLoc);
|
||||
if (ImmediatelyDeclaredConstraint.isInvalid() ||
|
||||
!ImmediatelyDeclaredConstraint.isUsable())
|
||||
return true;
|
||||
|
@ -1289,7 +1289,7 @@ QualType Sema::CheckNonTypeTemplateParameterType(TypeSourceInfo *&TSI,
|
|||
// - an identifier associated by name lookup with a non-type
|
||||
// template-parameter declared with a type that contains a
|
||||
// placeholder type (7.1.7.4),
|
||||
TSI = SubstAutoTypeSourceInfoDependent(TSI);
|
||||
TSI = SubstAutoTypeSourceInfo(TSI, Context.DependentTy);
|
||||
}
|
||||
|
||||
return CheckNonTypeTemplateParameterType(TSI->getType(), Loc);
|
||||
|
@ -10873,7 +10873,7 @@ bool Sema::RebuildTemplateParamsInCurrentInstantiation(
|
|||
// - an identifier associated by name lookup with a non-type
|
||||
// template-parameter declared with a type that contains a
|
||||
// placeholder type (7.1.7.4),
|
||||
NewTSI = SubstAutoTypeSourceInfoDependent(NewTSI);
|
||||
NewTSI = SubstAutoTypeSourceInfo(NewTSI, Context.DependentTy);
|
||||
}
|
||||
|
||||
if (NewTSI != NTTP->getTypeSourceInfo()) {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1622,7 +1622,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
|
|||
Expr *E = DS.getRepAsExpr();
|
||||
assert(E && "Didn't get an expression for typeof?");
|
||||
// TypeQuals handled by caller.
|
||||
Result = S.BuildTypeofExprType(E);
|
||||
Result = S.BuildTypeofExprType(E, DS.getTypeSpecTypeLoc());
|
||||
if (Result.isNull()) {
|
||||
Result = Context.IntTy;
|
||||
declarator.setInvalidType(true);
|
||||
|
@ -1633,7 +1633,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
|
|||
Expr *E = DS.getRepAsExpr();
|
||||
assert(E && "Didn't get an expression for decltype?");
|
||||
// TypeQuals handled by caller.
|
||||
Result = S.BuildDecltypeType(E);
|
||||
Result = S.BuildDecltypeType(E, DS.getTypeSpecTypeLoc());
|
||||
if (Result.isNull()) {
|
||||
Result = Context.IntTy;
|
||||
declarator.setInvalidType(true);
|
||||
|
@ -8925,7 +8925,7 @@ QualType Sema::getElaboratedType(ElaboratedTypeKeyword Keyword,
|
|||
return Context.getElaboratedType(Keyword, NNS, T, OwnedTagDecl);
|
||||
}
|
||||
|
||||
QualType Sema::BuildTypeofExprType(Expr *E) {
|
||||
QualType Sema::BuildTypeofExprType(Expr *E, SourceLocation Loc) {
|
||||
assert(!E->hasPlaceholderType() && "unexpected placeholder");
|
||||
|
||||
if (!getLangOpts().CPlusPlus && E->refersToBitField())
|
||||
|
@ -8942,9 +8942,9 @@ QualType Sema::BuildTypeofExprType(Expr *E) {
|
|||
/// getDecltypeForExpr - Given an expr, will return the decltype for
|
||||
/// that expression, according to the rules in C++11
|
||||
/// [dcl.type.simple]p4 and C++11 [expr.lambda.prim]p18.
|
||||
QualType Sema::getDecltypeForExpr(Expr *E) {
|
||||
static QualType getDecltypeForExpr(Sema &S, Expr *E) {
|
||||
if (E->isTypeDependent())
|
||||
return Context.DependentTy;
|
||||
return S.Context.DependentTy;
|
||||
|
||||
Expr *IDExpr = E;
|
||||
if (auto *ImplCastExpr = dyn_cast<ImplicitCastExpr>(E))
|
||||
|
@ -8961,7 +8961,7 @@ QualType Sema::getDecltypeForExpr(Expr *E) {
|
|||
// parameter object. This rule makes no difference before C++20 so we apply
|
||||
// it unconditionally.
|
||||
if (const auto *SNTTPE = dyn_cast<SubstNonTypeTemplateParmExpr>(IDExpr))
|
||||
return SNTTPE->getParameterType(Context);
|
||||
return SNTTPE->getParameterType(S.Context);
|
||||
|
||||
// - if e is an unparenthesized id-expression or an unparenthesized class
|
||||
// member access (5.2.5), decltype(e) is the type of the entity named
|
||||
|
@ -8969,21 +8969,22 @@ QualType Sema::getDecltypeForExpr(Expr *E) {
|
|||
// functions, the program is ill-formed;
|
||||
//
|
||||
// We apply the same rules for Objective-C ivar and property references.
|
||||
if (const auto *DRE = dyn_cast<DeclRefExpr>(IDExpr)) {
|
||||
if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(IDExpr)) {
|
||||
const ValueDecl *VD = DRE->getDecl();
|
||||
QualType T = VD->getType();
|
||||
return isa<TemplateParamObjectDecl>(VD) ? T.getUnqualifiedType() : T;
|
||||
}
|
||||
if (const auto *ME = dyn_cast<MemberExpr>(IDExpr)) {
|
||||
if (const auto *VD = ME->getMemberDecl())
|
||||
if (auto *TPO = dyn_cast<TemplateParamObjectDecl>(VD))
|
||||
return TPO->getType().getUnqualifiedType();
|
||||
return VD->getType();
|
||||
} else if (const MemberExpr *ME = dyn_cast<MemberExpr>(IDExpr)) {
|
||||
if (const ValueDecl *VD = ME->getMemberDecl())
|
||||
if (isa<FieldDecl>(VD) || isa<VarDecl>(VD))
|
||||
return VD->getType();
|
||||
} else if (const auto *IR = dyn_cast<ObjCIvarRefExpr>(IDExpr)) {
|
||||
} else if (const ObjCIvarRefExpr *IR = dyn_cast<ObjCIvarRefExpr>(IDExpr)) {
|
||||
return IR->getDecl()->getType();
|
||||
} else if (const auto *PR = dyn_cast<ObjCPropertyRefExpr>(IDExpr)) {
|
||||
} else if (const ObjCPropertyRefExpr *PR =
|
||||
dyn_cast<ObjCPropertyRefExpr>(IDExpr)) {
|
||||
if (PR->isExplicitProperty())
|
||||
return PR->getExplicitProperty()->getType();
|
||||
} else if (const auto *PE = dyn_cast<PredefinedExpr>(IDExpr)) {
|
||||
} else if (auto *PE = dyn_cast<PredefinedExpr>(IDExpr)) {
|
||||
return PE->getType();
|
||||
}
|
||||
|
||||
|
@ -8994,20 +8995,24 @@ QualType Sema::getDecltypeForExpr(Expr *E) {
|
|||
// access to a corresponding data member of the closure type that
|
||||
// would have been declared if x were an odr-use of the denoted
|
||||
// entity.
|
||||
if (getCurLambda() && isa<ParenExpr>(IDExpr)) {
|
||||
if (auto *DRE = dyn_cast<DeclRefExpr>(IDExpr->IgnoreParens())) {
|
||||
if (auto *Var = dyn_cast<VarDecl>(DRE->getDecl())) {
|
||||
QualType T = getCapturedDeclRefType(Var, DRE->getLocation());
|
||||
if (!T.isNull())
|
||||
return Context.getLValueReferenceType(T);
|
||||
using namespace sema;
|
||||
if (S.getCurLambda()) {
|
||||
if (isa<ParenExpr>(IDExpr)) {
|
||||
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(IDExpr->IgnoreParens())) {
|
||||
if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) {
|
||||
QualType T = S.getCapturedDeclRefType(Var, DRE->getLocation());
|
||||
if (!T.isNull())
|
||||
return S.Context.getLValueReferenceType(T);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Context.getReferenceQualifiedType(E);
|
||||
return S.Context.getReferenceQualifiedType(E);
|
||||
}
|
||||
|
||||
QualType Sema::BuildDecltypeType(Expr *E, bool AsUnevaluated) {
|
||||
QualType Sema::BuildDecltypeType(Expr *E, SourceLocation Loc,
|
||||
bool AsUnevaluated) {
|
||||
assert(!E->hasPlaceholderType() && "unexpected placeholder");
|
||||
|
||||
if (AsUnevaluated && CodeSynthesisContexts.empty() &&
|
||||
|
@ -9018,7 +9023,8 @@ QualType Sema::BuildDecltypeType(Expr *E, bool AsUnevaluated) {
|
|||
// used to build SFINAE gadgets.
|
||||
Diag(E->getExprLoc(), diag::warn_side_effects_unevaluated_context);
|
||||
}
|
||||
return Context.getDecltypeType(E, getDecltypeForExpr(E));
|
||||
|
||||
return Context.getDecltypeType(E, getDecltypeForExpr(*this, E));
|
||||
}
|
||||
|
||||
QualType Sema::BuildUnaryTransformType(QualType BaseType,
|
||||
|
|
|
@ -6586,7 +6586,7 @@ QualType TreeTransform<Derived>::TransformAutoType(TypeLocBuilder &TLB,
|
|||
T->isDependentType() || T->isConstrained()) {
|
||||
// FIXME: Maybe don't rebuild if all template arguments are the same.
|
||||
llvm::SmallVector<TemplateArgument, 4> NewArgList;
|
||||
NewArgList.reserve(NewTemplateArgs.size());
|
||||
NewArgList.reserve(NewArgList.size());
|
||||
for (const auto &ArgLoc : NewTemplateArgs.arguments())
|
||||
NewArgList.push_back(ArgLoc.getArgument());
|
||||
Result = getDerived().RebuildAutoType(NewDeduced, T->getKeyword(), NewCD,
|
||||
|
@ -14501,10 +14501,10 @@ QualType TreeTransform<Derived>::RebuildUnresolvedUsingType(SourceLocation Loc,
|
|||
return SemaRef.Context.getTypeDeclType(Ty);
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
template<typename Derived>
|
||||
QualType TreeTransform<Derived>::RebuildTypeOfExprType(Expr *E,
|
||||
SourceLocation) {
|
||||
return SemaRef.BuildTypeofExprType(E);
|
||||
SourceLocation Loc) {
|
||||
return SemaRef.BuildTypeofExprType(E, Loc);
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
|
@ -14512,9 +14512,10 @@ QualType TreeTransform<Derived>::RebuildTypeOfType(QualType Underlying) {
|
|||
return SemaRef.Context.getTypeOfType(Underlying);
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
QualType TreeTransform<Derived>::RebuildDecltypeType(Expr *E, SourceLocation) {
|
||||
return SemaRef.BuildDecltypeType(E);
|
||||
template<typename Derived>
|
||||
QualType TreeTransform<Derived>::RebuildDecltypeType(Expr *E,
|
||||
SourceLocation Loc) {
|
||||
return SemaRef.BuildDecltypeType(E, Loc);
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
|
|
|
@ -36,7 +36,7 @@ namespace std {
|
|||
|
||||
namespace p0702r1 {
|
||||
template<typename T> struct X { // expected-note {{candidate}}
|
||||
X(std::initializer_list<T>); // expected-note {{candidate template ignored: could not match 'std::initializer_list<T>' against 'p0702r1::Z'}}
|
||||
X(std::initializer_list<T>); // expected-note {{candidate template ignored: could not match 'initializer_list<type-parameter-0-0>' against 'p0702r1::Z'}}
|
||||
};
|
||||
|
||||
X xi = {0};
|
||||
|
|
|
@ -321,14 +321,14 @@ namespace p0962r1 {
|
|||
|
||||
namespace NE {
|
||||
struct E {
|
||||
void begin(); // expected-note {{member is not a candidate because range type 'NE::E' has no 'end' member}}
|
||||
void begin(); // expected-note {{member is not a candidate because range type 'p0962r1::NE::E' has no 'end' member}}
|
||||
};
|
||||
int *end(E);
|
||||
}
|
||||
|
||||
namespace NF {
|
||||
struct F {
|
||||
void end(); // expected-note {{member is not a candidate because range type 'NF::F' has no 'begin' member}}
|
||||
void end(); // expected-note {{member is not a candidate because range type 'p0962r1::NF::F' has no 'begin' member}}
|
||||
};
|
||||
int *begin(F);
|
||||
}
|
||||
|
@ -336,9 +336,9 @@ namespace p0962r1 {
|
|||
void use(NA::A a, NB::B b, NC::C c, ND::D d, NE::E e, NF::F f) {
|
||||
for (auto x : a) {}
|
||||
for (auto x : b) {}
|
||||
for (auto x : c) {} // expected-error {{invalid range expression of type 'NC::C'; no viable 'end' function available}}
|
||||
for (auto x : d) {} // expected-error {{invalid range expression of type 'ND::D'; no viable 'begin' function available}}
|
||||
for (auto x : e) {} // expected-error {{invalid range expression of type 'NE::E'; no viable 'begin' function available}}
|
||||
for (auto x : f) {} // expected-error {{invalid range expression of type 'NF::F'; no viable 'end' function available}}
|
||||
for (auto x : c) {} // expected-error {{invalid range expression of type 'p0962r1::NC::C'; no viable 'end' function available}}
|
||||
for (auto x : d) {} // expected-error {{invalid range expression of type 'p0962r1::ND::D'; no viable 'begin' function available}}
|
||||
for (auto x : e) {} // expected-error {{invalid range expression of type 'p0962r1::NE::E'; no viable 'begin' function available}}
|
||||
for (auto x : f) {} // expected-error {{invalid range expression of type 'p0962r1::NF::F'; no viable 'end' function available}}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -284,7 +284,7 @@ namespace PR13386 {
|
|||
void g(U &&...u, T &&...t) {} // expected-note {{candidate}}
|
||||
template<typename...U>
|
||||
void h(tuple<T, U> &&...) {}
|
||||
// expected-note@-1 {{candidate template ignored: could not match 'tuple<T, U>' against 'int'}}
|
||||
// expected-note@-1 {{candidate template ignored: could not match 'tuple<type-parameter-0-0, type-parameter-0-0>' against 'int'}}
|
||||
// expected-note@-2 {{candidate template ignored: substitution failure: deduced incomplete pack <(no value)> for template parameter 'U'}}
|
||||
|
||||
template<typename...U>
|
||||
|
|
|
@ -53,8 +53,9 @@ void test_simple_ref_deduction(int *ip, float *fp, double *dp) {
|
|||
}
|
||||
|
||||
|
||||
// FIXME: Use the template parameter names in this diagnostic.
|
||||
template<typename ...Args1, typename ...Args2>
|
||||
typename get_nth_type<0, Args1...>::type first_arg_pair(pair<Args1, Args2>...); // expected-note{{candidate template ignored: could not match 'pair<Args1, Args2>' against 'int'}}
|
||||
typename get_nth_type<0, Args1...>::type first_arg_pair(pair<Args1, Args2>...); // expected-note{{candidate template ignored: could not match 'pair<type-parameter-0-0, type-parameter-0-1>' against 'int'}}
|
||||
|
||||
template<typename ...Args1, typename ...Args2>
|
||||
typename get_nth_type<1, Args1...>::type second_arg_pair(pair<Args1, Args2>...);
|
||||
|
|
|
@ -18,12 +18,6 @@ namespace PR12132 {
|
|||
void foo() {
|
||||
fun(&A::x);
|
||||
}
|
||||
struct B { char* x; };
|
||||
void bar() {
|
||||
fun(&B::x);
|
||||
// expected-error@-1 {{no matching function for call to 'fun'}}
|
||||
// expected-note@-9 {{candidate template ignored: could not match 'const int' against 'char'}}
|
||||
}
|
||||
}
|
||||
|
||||
#if __cplusplus > 201402L
|
||||
|
@ -58,4 +52,6 @@ namespace noexcept_conversion {
|
|||
int i1 = i(g1);
|
||||
int i2 = i(g2);
|
||||
}
|
||||
#else
|
||||
// expected-no-diagnostics
|
||||
#endif
|
||||
|
|
|
@ -199,7 +199,7 @@ inline namespace InlineNS {}
|
|||
// CHECK: UnexposedExpr=templRefParam:71:40 [type=const Specialization<Specialization<bool> &>] [typekind=Record] const [templateargs/1= [type=Specialization<bool> &] [typekind=LValueReference]] [isPOD=1]
|
||||
// CHECK: DeclRefExpr=templRefParam:71:40 [type=Specialization<Specialization<bool> &>] [typekind=Unexposed] [templateargs/1= [type=Specialization<bool> &] [typekind=LValueReference]] [canonicaltype=Specialization<Specialization<bool> &>] [canonicaltypekind=Record] [canonicaltemplateargs/1= [type=Specialization<bool> &] [typekind=LValueReference]] [isPOD=1]
|
||||
// CHECK: TypeAliasDecl=baz:76:7 (Definition) [type=baz] [typekind=Typedef] [templateargs/1= [type=A<void>] [typekind=Unexposed]] [canonicaltype=A<void>] [canonicaltypekind=Record] [canonicaltemplateargs/1= [type=void] [typekind=Void]] [isPOD=0]
|
||||
// CHECK: VarDecl=autoTemplPointer:78:6 (Definition) [type=Specialization<Specialization<bool> &> *] [typekind=Auto] [canonicaltype=Specialization<Specialization<bool> &> *] [canonicaltypekind=Pointer] [isPOD=1] [pointeetype=Specialization<Specialization<bool> &>] [pointeekind=Auto]
|
||||
// CHECK: VarDecl=autoTemplPointer:78:6 (Definition) [type=Specialization<Specialization<bool> &> *] [typekind=Auto] [canonicaltype=Specialization<Specialization<bool> &> *] [canonicaltypekind=Pointer] [isPOD=1] [pointeetype=Specialization<Specialization<bool> &>] [pointeekind=Record]
|
||||
// CHECK: CallExpr=Bar:17:3 [type=outer::inner::Bar] [typekind=Elaborated] [canonicaltype=outer::inner::Bar] [canonicaltypekind=Record] [args= [outer::Foo<bool> *] [Pointer]] [isPOD=0] [nbFields=3]
|
||||
// CHECK: StructDecl=:84:3 (Definition) [type=X::(anonymous struct at {{.*}}print-type.cpp:84:3)] [typekind=Record] [isPOD=1] [nbFields=1] [isAnon=1]
|
||||
// CHECK: ClassDecl=:85:3 (Definition) [type=X::(anonymous class at {{.*}}print-type.cpp:85:3)] [typekind=Record] [isPOD=1] [nbFields=1] [isAnon=1]
|
||||
|
|
|
@ -569,52 +569,6 @@ namespace PR52139 {
|
|||
virtual void f() = 0;
|
||||
};
|
||||
}
|
||||
|
||||
namespace function_prototypes {
|
||||
template<class T> using fptr1 = void (*) (T);
|
||||
template<class T> using fptr2 = fptr1<fptr1<T>>;
|
||||
|
||||
template<class T> void foo0(fptr1<T>) {
|
||||
static_assert(__is_same(T, const char*));
|
||||
}
|
||||
void bar0(const char *const volatile __restrict);
|
||||
void t0() { foo0(&bar0); }
|
||||
|
||||
template<class T> void foo1(fptr1<const T *>) {
|
||||
static_assert(__is_same(T, char));
|
||||
}
|
||||
void bar1(const char * __restrict);
|
||||
void t1() { foo1(&bar1); }
|
||||
|
||||
template<class T> void foo2(fptr2<const T *>) {
|
||||
static_assert(__is_same(T, char));
|
||||
}
|
||||
void bar2(fptr1<const char * __restrict>);
|
||||
void t2() { foo2(&bar2); }
|
||||
|
||||
template<class T> void foo3(fptr1<const T *>) {}
|
||||
void bar3(char * __restrict);
|
||||
void t3() { foo3(&bar3); }
|
||||
// expected-error@-1 {{no matching function for call to 'foo3'}}
|
||||
// expected-note@-4 {{candidate template ignored: cannot deduce a type for 'T' that would make 'const T' equal 'char'}}
|
||||
|
||||
template<class T> void foo4(fptr2<const T *>) {}
|
||||
void bar4(fptr1<char * __restrict>);
|
||||
void t4() { foo4(&bar4); }
|
||||
// expected-error@-1 {{no matching function for call to 'foo4'}}
|
||||
// expected-note@-4 {{candidate template ignored: cannot deduce a type for 'T' that would make 'const T' equal 'char'}}
|
||||
|
||||
template<typename T> void foo5(T(T)) {}
|
||||
const int bar5(int);
|
||||
void t5() { foo5(bar5); }
|
||||
// expected-error@-1 {{no matching function for call to 'foo5'}}
|
||||
// expected-note@-4 {{candidate template ignored: deduced conflicting types for parameter 'T' ('const int' vs. 'int')}}
|
||||
|
||||
struct Foo6 {};
|
||||
template<typename T> void foo6(void(*)(struct Foo6, T)) {}
|
||||
void bar6(Foo6, int);
|
||||
void t6() { foo6(bar6); }
|
||||
}
|
||||
#else
|
||||
|
||||
// expected-no-diagnostics
|
||||
|
|
|
@ -9,7 +9,7 @@ void num_elems() {
|
|||
int a1[1], a2[2];
|
||||
|
||||
auto [] = a0; // expected-warning {{does not allow a decomposition group to be empty}}
|
||||
auto [v1] = a0; // expected-error {{type 'struct A0' decomposes into 0 elements, but 1 name was provided}}
|
||||
auto [v1] = a0; // expected-error {{type 'A0' decomposes into 0 elements, but 1 name was provided}}
|
||||
auto [] = a1; // expected-error {{type 'int[1]' decomposes into 1 element, but no names were provided}} expected-warning {{empty}}
|
||||
auto [v2] = a1;
|
||||
auto [v3, v4] = a1; // expected-error {{type 'int[1]' decomposes into 1 element, but 2 names were provided}}
|
||||
|
@ -70,7 +70,7 @@ void enclosing() {
|
|||
void bitfield() {
|
||||
struct { int a : 3, : 4, b : 5; } a;
|
||||
auto &[x, y] = a;
|
||||
auto &[p, q, r] = a; // expected-error-re {{type 'struct (unnamed struct at {{.*}})' decomposes into 2 elements, but 3 names were provided}}
|
||||
auto &[p, q, r] = a; // expected-error-re {{type '(unnamed struct at {{.*}})' decomposes into 2 elements, but 3 names were provided}}
|
||||
}
|
||||
|
||||
void for_range() {
|
||||
|
|
|
@ -300,7 +300,7 @@ namespace Constexpr {
|
|||
}
|
||||
struct NonLiteral { ~NonLiteral(); } nl; // cxx14-note {{user-provided destructor}}
|
||||
// cxx20_2b-note@-1 {{'NonLiteral' is not literal because its destructor is not constexpr}}
|
||||
constexpr auto f2(int n) { return nl; } // expected-error {{return type 'struct NonLiteral' is not a literal type}}
|
||||
constexpr auto f2(int n) { return nl; } // expected-error {{return type 'Constexpr::NonLiteral' is not a literal type}}
|
||||
}
|
||||
|
||||
// It's not really clear whether these are valid, but this matches g++.
|
||||
|
|
|
@ -415,7 +415,7 @@ namespace PR33222 {
|
|||
|
||||
namespace qualified_friend_no_match {
|
||||
void f(int); // expected-note {{type mismatch at 1st parameter}}
|
||||
template<typename T> void f(T*); // expected-note {{could not match 'T *' against 'double'}}
|
||||
template<typename T> void f(T*); // expected-note {{could not match 'type-parameter-0-0 *' against 'double'}}
|
||||
struct X {
|
||||
friend void qualified_friend_no_match::f(double); // expected-error {{friend declaration of 'f' does not match any declaration in namespace 'qualified_friend_no_match'}}
|
||||
friend void qualified_friend_no_match::g(); // expected-error {{friend declaration of 'g' does not match any declaration in namespace 'qualified_friend_no_match'}}
|
||||
|
@ -423,7 +423,7 @@ namespace qualified_friend_no_match {
|
|||
|
||||
struct Y {
|
||||
void f(int); // expected-note {{type mismatch at 1st parameter}}
|
||||
template<typename T> void f(T*); // expected-note {{could not match 'T *' against 'double'}}
|
||||
template<typename T> void f(T*); // expected-note {{could not match 'type-parameter-0-0 *' against 'double'}}
|
||||
};
|
||||
struct Z {
|
||||
friend void Y::f(double); // expected-error {{friend declaration of 'f' does not match any declaration in 'qualified_friend_no_match::Y'}}
|
||||
|
|
|
@ -133,7 +133,7 @@ struct S { // expected-note {{candidate}}
|
|||
template <typename T> S(T t) -> S<void *>;
|
||||
|
||||
void baz() {
|
||||
bar(S(123)); // expected-error {{no matching conversion for functional-style cast from 'int' to 'S<void *>'}}
|
||||
bar(S(123)); // expected-error {{no matching conversion for functional-style cast from 'int' to 'test11::S<>'}}
|
||||
}
|
||||
} // namespace test11
|
||||
|
||||
|
|
|
@ -581,7 +581,7 @@ void cxx_only(int sel) {
|
|||
auto auto_int8 = local_int8;
|
||||
auto auto_int16 = local_int16;
|
||||
#if __cplusplus >= 201703L
|
||||
auto [auto_int8_a] = local_int8; // expected-error {{cannot decompose non-class, non-array type 'svint8_t' (aka '__SVInt8_t')}}
|
||||
auto [auto_int8_a] = local_int8; // expected-error {{cannot decompose non-class, non-array type '__SVInt8_t'}}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
@ -600,7 +600,7 @@ void cxx_only(int sel) {
|
|||
auto fn1 = [&local_int8](svint8_t x) { local_int8 = x; };
|
||||
auto fn2 = [&local_int8](svint8_t *ptr) { *ptr = local_int8; };
|
||||
#if __cplusplus >= 201703L
|
||||
auto fn3 = [a(return_int8())] {}; // expected-error {{field has sizeless type 'svint8_t' (aka '__SVInt8_t')}}
|
||||
auto fn3 = [a(return_int8())] {}; // expected-error {{field has sizeless type '__SVInt8_t'}}
|
||||
#endif
|
||||
auto fn4 = [local_int8](svint8_t *ptr) { *ptr = local_int8; }; // expected-error {{by-copy capture of variable 'local_int8' with sizeless type 'svint8_t'}}
|
||||
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++20
|
||||
|
||||
enum class N {};
|
||||
|
||||
using Animal = int;
|
||||
|
||||
using AnimalPtr = Animal *;
|
||||
|
||||
using Man = Animal;
|
||||
using Dog = Animal;
|
||||
|
||||
namespace variable {
|
||||
|
||||
auto x1 = Animal();
|
||||
N t1 = x1; // expected-error {{lvalue of type 'Animal' (aka 'int')}}
|
||||
|
||||
auto x2 = AnimalPtr();
|
||||
N t2 = x2; // expected-error {{lvalue of type 'AnimalPtr' (aka 'int *')}}
|
||||
|
||||
auto *x3 = AnimalPtr();
|
||||
N t3 = x3; // expected-error {{lvalue of type 'Animal *' (aka 'int *')}}
|
||||
|
||||
// Each variable deduces separately.
|
||||
auto x4 = Man(), x5 = Dog();
|
||||
N t4 = x4; // expected-error {{lvalue of type 'Man' (aka 'int')}}
|
||||
N t5 = x5; // expected-error {{lvalue of type 'Dog' (aka 'int')}}
|
||||
|
||||
} // namespace variable
|
||||
|
||||
namespace function_basic {
|
||||
|
||||
auto f1() { return Animal(); }
|
||||
auto x1 = f1();
|
||||
N t1 = x1; // expected-error {{lvalue of type 'Animal' (aka 'int')}}
|
||||
|
||||
decltype(auto) f2() { return Animal(); }
|
||||
auto x2 = f2();
|
||||
N t2 = x2; // expected-error {{lvalue of type 'Animal' (aka 'int')}}
|
||||
|
||||
auto x3 = [a = Animal()] { return a; }();
|
||||
N t3 = x3; // expected-error {{lvalue of type 'Animal' (aka 'int')}}
|
||||
|
||||
} // namespace function_basic
|
|
@ -124,8 +124,7 @@ namespace preferred_name {
|
|||
struct [[clang::preferred_name(iterator),
|
||||
clang::preferred_name(const_iterator)]] Iter {};
|
||||
};
|
||||
template<typename T> T desugar(T);
|
||||
auto it = desugar(MemberTemplate<int>::Iter<const int>());
|
||||
auto it = MemberTemplate<int>::Iter<const int>();
|
||||
int n = it; // expected-error {{no viable conversion from 'preferred_name::MemberTemplate<int>::const_iterator' to 'int'}}
|
||||
|
||||
template<int A, int B, typename ...T> struct Foo;
|
||||
|
|
|
@ -50,7 +50,7 @@ C<int> c;
|
|||
|
||||
namespace qualified_friend {
|
||||
void f(int); // expected-note 2{{type mismatch at 1st parameter}}
|
||||
template<typename T> void f(T*); // expected-note 2{{could not match 'T *' against 'double'}}
|
||||
template<typename T> void f(T*); // expected-note 2{{could not match 'type-parameter-0-0 *' against 'double'}}
|
||||
template<typename T> void nondep();
|
||||
|
||||
template<typename> struct X1 {
|
||||
|
@ -66,7 +66,7 @@ namespace qualified_friend {
|
|||
|
||||
struct Y {
|
||||
void f(int); // expected-note 2{{type mismatch at 1st parameter}}
|
||||
template<typename T> void f(T*); // expected-note 2{{could not match 'T *' against 'double'}}
|
||||
template<typename T> void f(T*); // expected-note 2{{could not match 'type-parameter-0-0 *' against 'double'}}
|
||||
template<typename T> void nondep();
|
||||
};
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
// Make sure we accept this
|
||||
template<class X>struct A{typedef X Y;};
|
||||
template<class X>bool operator==(A<X>,typename A<X>::Y); // expected-note{{candidate template ignored: could not match 'A<X>' against 'B<int> *'}}
|
||||
template<class X>bool operator==(A<X>,typename A<X>::Y); // expected-note{{candidate template ignored: could not match 'A<type-parameter-0-0>' against 'B<int> *'}}
|
||||
|
||||
int a(A<int> x) { return operator==(x,1); }
|
||||
|
||||
|
|
Loading…
Reference in New Issue