forked from OSchip/llvm-project
Revert "[c++20] P1907R1: Support for generalized non-type template arguments of scalar type."
This reverts commit 9e08e51a20
.
This is part of 5 commits being reverted due to https://crbug.com/1161059. See bug for repro.
This commit is contained in:
parent
ab7a60eb41
commit
2080232333
|
@ -72,7 +72,6 @@ class CountPropertyType<string typeName = ""> : PropertyType<typeName> {
|
|||
|
||||
def APInt : PropertyType<"llvm::APInt"> { let PassByReference = 1; }
|
||||
def APSInt : PropertyType<"llvm::APSInt"> { let PassByReference = 1; }
|
||||
def APValue : PropertyType { let PassByReference = 1; }
|
||||
def ArraySizeModifier : EnumPropertyType<"ArrayType::ArraySizeModifier">;
|
||||
def AttrKind : EnumPropertyType<"attr::Kind">;
|
||||
def AutoTypeKeyword : EnumPropertyType;
|
||||
|
@ -451,17 +450,6 @@ let Class = PropertyTypeCase<TemplateArgument, "Integral"> in {
|
|||
return TemplateArgument(ctx, value, type);
|
||||
}]>;
|
||||
}
|
||||
let Class = PropertyTypeCase<TemplateArgument, "UncommonValue"> in {
|
||||
def : Property<"value", APValue> {
|
||||
let Read = [{ node.getAsUncommonValue() }];
|
||||
}
|
||||
def : Property<"type", QualType> {
|
||||
let Read = [{ node.getUncommonValueType() }];
|
||||
}
|
||||
def : Creator<[{
|
||||
return TemplateArgument(ctx, type, value);
|
||||
}]>;
|
||||
}
|
||||
let Class = PropertyTypeCase<TemplateArgument, "Template"> in {
|
||||
def : Property<"name", TemplateName> {
|
||||
let Read = [{ node.getAsTemplateOrTemplatePattern() }];
|
||||
|
|
|
@ -768,7 +768,6 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgument(
|
|||
case TemplateArgument::Declaration:
|
||||
case TemplateArgument::Integral:
|
||||
case TemplateArgument::NullPtr:
|
||||
case TemplateArgument::UncommonValue:
|
||||
return true;
|
||||
|
||||
case TemplateArgument::Type:
|
||||
|
@ -802,7 +801,6 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLoc(
|
|||
case TemplateArgument::Declaration:
|
||||
case TemplateArgument::Integral:
|
||||
case TemplateArgument::NullPtr:
|
||||
case TemplateArgument::UncommonValue:
|
||||
return true;
|
||||
|
||||
case TemplateArgument::Type: {
|
||||
|
|
|
@ -37,7 +37,6 @@ public:
|
|||
DISPATCH(Declaration);
|
||||
DISPATCH(NullPtr);
|
||||
DISPATCH(Integral);
|
||||
DISPATCH(UncommonValue);
|
||||
DISPATCH(Template);
|
||||
DISPATCH(TemplateExpansion);
|
||||
DISPATCH(Expression);
|
||||
|
@ -60,7 +59,6 @@ public:
|
|||
VISIT_METHOD(Declaration);
|
||||
VISIT_METHOD(NullPtr);
|
||||
VISIT_METHOD(Integral);
|
||||
VISIT_METHOD(UncommonValue);
|
||||
VISIT_METHOD(Template);
|
||||
VISIT_METHOD(TemplateExpansion);
|
||||
VISIT_METHOD(Expression);
|
||||
|
|
|
@ -51,7 +51,6 @@ template <> struct PointerLikeTypeTraits<clang::Expr *> {
|
|||
|
||||
namespace clang {
|
||||
|
||||
class APValue;
|
||||
class ASTContext;
|
||||
class DiagnosticBuilder;
|
||||
class Expr;
|
||||
|
@ -83,12 +82,6 @@ public:
|
|||
/// that was provided for an integral non-type template parameter.
|
||||
Integral,
|
||||
|
||||
/// The template argument is a non-type template argument that can't be
|
||||
/// represented by the special-case Declaration, NullPtr, or Integral
|
||||
/// forms. These values are only ever produced by constant evaluation,
|
||||
/// so cannot be dependent.
|
||||
UncommonValue,
|
||||
|
||||
/// The template argument is a template name that was provided for a
|
||||
/// template template parameter.
|
||||
Template,
|
||||
|
@ -132,11 +125,6 @@ private:
|
|||
};
|
||||
void *Type;
|
||||
};
|
||||
struct V {
|
||||
unsigned Kind;
|
||||
const APValue *Value;
|
||||
void *Type;
|
||||
};
|
||||
struct A {
|
||||
unsigned Kind;
|
||||
unsigned NumArgs;
|
||||
|
@ -154,7 +142,6 @@ private:
|
|||
union {
|
||||
struct DA DeclArg;
|
||||
struct I Integer;
|
||||
struct V Value;
|
||||
struct A Args;
|
||||
struct TA TemplateArg;
|
||||
struct TV TypeOrValue;
|
||||
|
@ -170,8 +157,9 @@ public:
|
|||
TypeOrValue.V = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
|
||||
}
|
||||
|
||||
/// Construct a template argument that refers to a (non-dependent)
|
||||
/// declaration.
|
||||
/// Construct a template argument that refers to a
|
||||
/// declaration, which is either an external declaration or a
|
||||
/// template declaration.
|
||||
TemplateArgument(ValueDecl *D, QualType QT) {
|
||||
assert(D && "Expected decl");
|
||||
DeclArg.Kind = Declaration;
|
||||
|
@ -181,11 +169,7 @@ public:
|
|||
|
||||
/// Construct an integral constant template argument. The memory to
|
||||
/// store the value is allocated with Ctx.
|
||||
TemplateArgument(const ASTContext &Ctx, const llvm::APSInt &Value,
|
||||
QualType Type);
|
||||
|
||||
/// Construct a template argument from an arbitrary constant value.
|
||||
TemplateArgument(const ASTContext &Ctx, QualType Type, const APValue &Value);
|
||||
TemplateArgument(ASTContext &Ctx, const llvm::APSInt &Value, QualType Type);
|
||||
|
||||
/// Construct an integral constant template argument with the same
|
||||
/// value as Other but a different type.
|
||||
|
@ -356,16 +340,6 @@ public:
|
|||
Integer.Type = T.getAsOpaquePtr();
|
||||
}
|
||||
|
||||
/// Get the value of an UncommonValue.
|
||||
const APValue &getAsUncommonValue() const {
|
||||
return *Value.Value;
|
||||
}
|
||||
|
||||
/// Get the type of an UncommonValue.
|
||||
QualType getUncommonValueType() const {
|
||||
return QualType::getFromOpaquePtr(Value.Type);
|
||||
}
|
||||
|
||||
/// If this is a non-type template argument, get its type. Otherwise,
|
||||
/// returns a null QualType.
|
||||
QualType getNonTypeTemplateArgumentType() const;
|
||||
|
@ -510,7 +484,6 @@ public:
|
|||
assert(Argument.getKind() == TemplateArgument::NullPtr ||
|
||||
Argument.getKind() == TemplateArgument::Integral ||
|
||||
Argument.getKind() == TemplateArgument::Declaration ||
|
||||
Argument.getKind() == TemplateArgument::UncommonValue ||
|
||||
Argument.getKind() == TemplateArgument::Expression);
|
||||
}
|
||||
|
||||
|
@ -569,11 +542,6 @@ public:
|
|||
return LocInfo.getAsExpr();
|
||||
}
|
||||
|
||||
Expr *getSourceUncommonValueExpression() const {
|
||||
assert(Argument.getKind() == TemplateArgument::UncommonValue);
|
||||
return LocInfo.getAsExpr();
|
||||
}
|
||||
|
||||
NestedNameSpecifierLoc getTemplateQualifierLoc() const {
|
||||
if (Argument.getKind() != TemplateArgument::Template &&
|
||||
Argument.getKind() != TemplateArgument::TemplateExpansion)
|
||||
|
|
|
@ -4656,6 +4656,8 @@ def err_non_type_template_arg_subobject : Error<
|
|||
"non-type template argument refers to subobject '%0'">;
|
||||
def err_non_type_template_arg_addr_label_diff : Error<
|
||||
"template argument / label address difference / what did you expect?">;
|
||||
def err_non_type_template_arg_unsupported : Error<
|
||||
"sorry, non-type template argument of type %0 is not yet supported">;
|
||||
def err_template_arg_not_convertible : Error<
|
||||
"non-type template argument of type %0 cannot be converted to a value "
|
||||
"of type %1">;
|
||||
|
@ -4707,6 +4709,9 @@ def err_template_arg_not_object_or_func : Error<
|
|||
"non-type template argument does not refer to an object or function">;
|
||||
def err_template_arg_not_pointer_to_member_form : Error<
|
||||
"non-type template argument is not a pointer to member constant">;
|
||||
def err_template_arg_member_ptr_base_derived_not_supported : Error<
|
||||
"sorry, non-type template argument of pointer-to-member type %1 that refers "
|
||||
"to member %q0 of a different class is not supported yet">;
|
||||
def ext_template_arg_extra_parens : ExtWarn<
|
||||
"address non-type template argument cannot be surrounded by parentheses">;
|
||||
def warn_cxx98_compat_template_arg_extra_parens : Warning<
|
||||
|
|
|
@ -7623,8 +7623,8 @@ public:
|
|||
QualType ParamType,
|
||||
SourceLocation Loc);
|
||||
ExprResult
|
||||
BuildExpressionFromNonTypeTemplateArgument(const TemplateArgument &Arg,
|
||||
SourceLocation Loc);
|
||||
BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg,
|
||||
SourceLocation Loc);
|
||||
|
||||
/// Enumeration describing how template parameter lists are compared
|
||||
/// for equality.
|
||||
|
|
|
@ -166,7 +166,6 @@ public:
|
|||
|
||||
/// Emit an APvalue.
|
||||
void AddAPValue(const APValue &Value);
|
||||
void writeAPValue(const APValue &Value) { AddAPValue(Value); }
|
||||
|
||||
/// Emit a reference to an identifier.
|
||||
void AddIdentifierRef(const IdentifierInfo *II) {
|
||||
|
|
|
@ -5941,11 +5941,6 @@ ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) const {
|
|||
case TemplateArgument::Integral:
|
||||
return TemplateArgument(Arg, getCanonicalType(Arg.getIntegralType()));
|
||||
|
||||
case TemplateArgument::UncommonValue:
|
||||
return TemplateArgument(*this,
|
||||
getCanonicalType(Arg.getUncommonValueType()),
|
||||
Arg.getAsUncommonValue());
|
||||
|
||||
case TemplateArgument::Type:
|
||||
return TemplateArgument(getCanonicalType(Arg.getAsType()));
|
||||
|
||||
|
|
|
@ -808,17 +808,6 @@ ASTNodeImporter::import(const TemplateArgument &From) {
|
|||
return TemplateArgument(*ToTypeOrErr, /*isNullPtr*/true);
|
||||
}
|
||||
|
||||
case TemplateArgument::UncommonValue: {
|
||||
ExpectedType ToTypeOrErr = import(From.getUncommonValueType());
|
||||
if (!ToTypeOrErr)
|
||||
return ToTypeOrErr.takeError();
|
||||
Expected<APValue> ToValueOrErr = import(From.getAsUncommonValue());
|
||||
if (!ToValueOrErr)
|
||||
return ToValueOrErr.takeError();
|
||||
return TemplateArgument(Importer.getToContext(), *ToTypeOrErr,
|
||||
*ToValueOrErr);
|
||||
}
|
||||
|
||||
case TemplateArgument::Template: {
|
||||
Expected<TemplateName> ToTemplateOrErr = import(From.getAsTemplate());
|
||||
if (!ToTemplateOrErr)
|
||||
|
|
|
@ -565,10 +565,6 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
|
|||
return IsStructurallyEquivalent(Context, Arg1.getAsExpr(),
|
||||
Arg2.getAsExpr());
|
||||
|
||||
case TemplateArgument::UncommonValue:
|
||||
// FIXME: Do we need to customize the comparison?
|
||||
return Arg1.structurallyEquals(Arg2);
|
||||
|
||||
case TemplateArgument::Pack:
|
||||
if (Arg1.pack_size() != Arg2.pack_size())
|
||||
return false;
|
||||
|
|
|
@ -342,10 +342,6 @@ LinkageComputer::getLVForTemplateArgumentList(ArrayRef<TemplateArgument> Args,
|
|||
LV.merge(getTypeLinkageAndVisibility(Arg.getNullPtrType()));
|
||||
continue;
|
||||
|
||||
case TemplateArgument::UncommonValue:
|
||||
LV.merge(getLVForValue(Arg.getAsUncommonValue(), computation));
|
||||
continue;
|
||||
|
||||
case TemplateArgument::Template:
|
||||
case TemplateArgument::TemplateExpansion:
|
||||
if (TemplateDecl *Template =
|
||||
|
|
|
@ -4079,28 +4079,10 @@ recurse:
|
|||
mangleExpression(cast<CXXStdInitializerListExpr>(E)->getSubExpr(), Arity);
|
||||
break;
|
||||
|
||||
case Expr::SubstNonTypeTemplateParmExprClass: {
|
||||
// Mangle a substituted parameter the same way we mangle the template
|
||||
// argument.
|
||||
// As proposed in https://github.com/itanium-cxx-abi/cxx-abi/issues/111.
|
||||
auto *SNTTPE = cast<SubstNonTypeTemplateParmExpr>(E);
|
||||
if (auto *CE = dyn_cast<ConstantExpr>(SNTTPE->getReplacement())) {
|
||||
// Pull out the constant value and mangle it as a template argument.
|
||||
QualType ParamType = SNTTPE->getParameterType(Context.getASTContext());
|
||||
if (CE->hasAPValueResult())
|
||||
mangleValueInTemplateArg(ParamType, CE->getResultAsAPValue(), false,
|
||||
/*NeedExactType=*/true);
|
||||
else
|
||||
mangleValueInTemplateArg(ParamType, CE->getAPValueResult(), false,
|
||||
/*NeedExactType=*/true);
|
||||
} else {
|
||||
// The remaining cases all happen to be substituted with expressions that
|
||||
// mangle the same as a corresponding template argument anyway.
|
||||
mangleExpression(cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement(),
|
||||
Arity);
|
||||
}
|
||||
case Expr::SubstNonTypeTemplateParmExprClass:
|
||||
mangleExpression(cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement(),
|
||||
Arity);
|
||||
break;
|
||||
}
|
||||
|
||||
case Expr::UserDefinedLiteralClass:
|
||||
// We follow g++'s approach of mangling a UDL as a call to the literal
|
||||
|
@ -5057,10 +5039,6 @@ void CXXNameMangler::mangleTemplateArg(TemplateArgument A, bool NeedExactType) {
|
|||
mangleNullPointer(A.getNullPtrType());
|
||||
break;
|
||||
}
|
||||
case TemplateArgument::UncommonValue:
|
||||
mangleValueInTemplateArg(A.getUncommonValueType(), A.getAsUncommonValue(),
|
||||
/*TopLevel=*/true, NeedExactType);
|
||||
break;
|
||||
case TemplateArgument::Pack: {
|
||||
// <template-arg> ::= J <template-arg>* E
|
||||
Out << 'J';
|
||||
|
@ -5395,20 +5373,7 @@ void CXXNameMangler::mangleValueInTemplateArg(QualType T, const APValue &V,
|
|||
Out << "plcvPcad";
|
||||
Kind = Offset;
|
||||
} else {
|
||||
// Clang 11 and before mangled an array subject to array-to-pointer decay
|
||||
// as if it were the declaration itself.
|
||||
bool IsArrayToPointerDecayMangledAsDecl = false;
|
||||
if (TopLevel && Ctx.getLangOpts().getClangABICompat() <=
|
||||
LangOptions::ClangABI::Ver11) {
|
||||
QualType BType = B.getType();
|
||||
IsArrayToPointerDecayMangledAsDecl =
|
||||
BType->isArrayType() && V.getLValuePath().size() == 1 &&
|
||||
V.getLValuePath()[0].getAsArrayIndex() == 0 &&
|
||||
Ctx.hasSimilarType(T, Ctx.getDecayedType(BType));
|
||||
}
|
||||
|
||||
if ((!V.getLValuePath().empty() || V.isLValueOnePastTheEnd()) &&
|
||||
!IsArrayToPointerDecayMangledAsDecl) {
|
||||
if (!V.getLValuePath().empty() || V.isLValueOnePastTheEnd()) {
|
||||
NotPrimaryExpr();
|
||||
// A final conversion to the template parameter's type is usually
|
||||
// folded into the 'so' mangling, but we can't do that for 'void*'
|
||||
|
|
|
@ -1575,17 +1575,6 @@ void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD,
|
|||
cast<NonTypeTemplateParmDecl>(Parm), T);
|
||||
break;
|
||||
}
|
||||
case TemplateArgument::UncommonValue:
|
||||
Out << "$";
|
||||
if (cast<NonTypeTemplateParmDecl>(Parm)
|
||||
->getType()
|
||||
->getContainedDeducedType()) {
|
||||
Out << "M";
|
||||
mangleType(TA.getNonTypeTemplateArgumentType(), SourceRange(), QMM_Drop);
|
||||
}
|
||||
mangleTemplateArgValue(TA.getUncommonValueType(), TA.getAsUncommonValue(),
|
||||
/*WithScalarType=*/false);
|
||||
break;
|
||||
case TemplateArgument::Expression:
|
||||
mangleExpression(TA.getAsExpr(), cast<NonTypeTemplateParmDecl>(Parm));
|
||||
break;
|
||||
|
|
|
@ -169,8 +169,6 @@ void ODRHash::AddTemplateArgument(TemplateArgument TA) {
|
|||
break;
|
||||
case TemplateArgument::NullPtr:
|
||||
case TemplateArgument::Integral:
|
||||
case TemplateArgument::UncommonValue:
|
||||
// FIXME: Include a representation of these arguments.
|
||||
break;
|
||||
case TemplateArgument::Template:
|
||||
case TemplateArgument::TemplateExpansion:
|
||||
|
|
|
@ -2208,12 +2208,6 @@ void StmtProfiler::VisitTemplateArgument(const TemplateArgument &Arg) {
|
|||
Arg.getAsIntegral().Profile(ID);
|
||||
break;
|
||||
|
||||
case TemplateArgument::UncommonValue:
|
||||
VisitType(Arg.getUncommonValueType());
|
||||
// FIXME: Do we need to recursively decompose this ourselves?
|
||||
Arg.getAsUncommonValue().Profile(ID);
|
||||
break;
|
||||
|
||||
case TemplateArgument::Expression:
|
||||
Visit(Arg.getAsExpr());
|
||||
break;
|
||||
|
|
|
@ -84,8 +84,8 @@ static void printIntegral(const TemplateArgument &TemplArg,
|
|||
// TemplateArgument Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
TemplateArgument::TemplateArgument(const ASTContext &Ctx,
|
||||
const llvm::APSInt &Value, QualType Type) {
|
||||
TemplateArgument::TemplateArgument(ASTContext &Ctx, const llvm::APSInt &Value,
|
||||
QualType Type) {
|
||||
Integer.Kind = Integral;
|
||||
// Copy the APSInt value into our decomposed form.
|
||||
Integer.BitWidth = Value.getBitWidth();
|
||||
|
@ -103,44 +103,6 @@ TemplateArgument::TemplateArgument(const ASTContext &Ctx,
|
|||
Integer.Type = Type.getAsOpaquePtr();
|
||||
}
|
||||
|
||||
static const ValueDecl *getAsSimpleValueDeclRef(const ASTContext &Ctx,
|
||||
QualType T, const APValue &V) {
|
||||
// Pointers to members are relatively easy.
|
||||
if (V.isMemberPointer() && V.getMemberPointerPath().empty())
|
||||
return V.getMemberPointerDecl();
|
||||
|
||||
// We model class non-type template parameters as their template parameter
|
||||
// object declaration.
|
||||
if (V.isStruct() || V.isUnion())
|
||||
return Ctx.getTemplateParamObjectDecl(T, V);
|
||||
|
||||
// Pointers and references with an empty path use the special 'Declaration'
|
||||
// representation.
|
||||
if (V.isLValue() && V.hasLValuePath() &&
|
||||
V.getLValuePath().empty() && !V.isLValueOnePastTheEnd())
|
||||
return V.getLValueBase().dyn_cast<const ValueDecl *>();
|
||||
|
||||
// Everything else uses the 'uncommon' representation.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
TemplateArgument::TemplateArgument(const ASTContext &Ctx, QualType Type,
|
||||
const APValue &V) {
|
||||
if (Type->isIntegralOrEnumerationType() && V.isInt())
|
||||
*this = TemplateArgument(Ctx, V.getInt(), Type);
|
||||
else if ((V.isLValue() && V.isNullPointer()) ||
|
||||
(V.isMemberPointer() && !V.getMemberPointerDecl()))
|
||||
*this = TemplateArgument(Type, /*isNullPtr=*/true);
|
||||
else if (const ValueDecl *VD = getAsSimpleValueDeclRef(Ctx, Type, V))
|
||||
// FIXME: The Declaration form should expose a const ValueDecl*.
|
||||
*this = TemplateArgument(const_cast<ValueDecl*>(VD), Type);
|
||||
else {
|
||||
Value.Kind = UncommonValue;
|
||||
Value.Value = new (Ctx) APValue(V);
|
||||
Value.Type = Type.getAsOpaquePtr();
|
||||
}
|
||||
}
|
||||
|
||||
TemplateArgument
|
||||
TemplateArgument::CreatePackCopy(ASTContext &Context,
|
||||
ArrayRef<TemplateArgument> Args) {
|
||||
|
@ -172,7 +134,6 @@ TemplateArgumentDependence TemplateArgument::getDependence() const {
|
|||
case NullPtr:
|
||||
case Integral:
|
||||
case Declaration:
|
||||
case UncommonValue:
|
||||
return TemplateArgumentDependence::None;
|
||||
|
||||
case Expression:
|
||||
|
@ -204,7 +165,6 @@ bool TemplateArgument::isPackExpansion() const {
|
|||
case Null:
|
||||
case Declaration:
|
||||
case Integral:
|
||||
case UncommonValue:
|
||||
case Pack:
|
||||
case Template:
|
||||
case NullPtr:
|
||||
|
@ -255,9 +215,6 @@ QualType TemplateArgument::getNonTypeTemplateArgumentType() const {
|
|||
|
||||
case TemplateArgument::NullPtr:
|
||||
return getNullPtrType();
|
||||
|
||||
case TemplateArgument::UncommonValue:
|
||||
return getUncommonValueType();
|
||||
}
|
||||
|
||||
llvm_unreachable("Invalid TemplateArgument Kind!");
|
||||
|
@ -302,13 +259,8 @@ void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID,
|
|||
}
|
||||
|
||||
case Integral:
|
||||
getIntegralType().Profile(ID);
|
||||
getAsIntegral().Profile(ID);
|
||||
break;
|
||||
|
||||
case UncommonValue:
|
||||
getUncommonValueType().Profile(ID);
|
||||
getAsUncommonValue().Profile(ID);
|
||||
getIntegralType().Profile(ID);
|
||||
break;
|
||||
|
||||
case Expression:
|
||||
|
@ -344,16 +296,6 @@ bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const {
|
|||
return getIntegralType() == Other.getIntegralType() &&
|
||||
getAsIntegral() == Other.getAsIntegral();
|
||||
|
||||
case UncommonValue: {
|
||||
if (getUncommonValueType() != Other.getUncommonValueType())
|
||||
return false;
|
||||
|
||||
llvm::FoldingSetNodeID A, B;
|
||||
getAsUncommonValue().Profile(A);
|
||||
Other.getAsUncommonValue().Profile(B);
|
||||
return A == B;
|
||||
}
|
||||
|
||||
case Pack:
|
||||
if (Args.NumArgs != Other.Args.NumArgs) return false;
|
||||
for (unsigned I = 0, E = Args.NumArgs; I != E; ++I)
|
||||
|
@ -380,7 +322,6 @@ TemplateArgument TemplateArgument::getPackExpansionPattern() const {
|
|||
|
||||
case Declaration:
|
||||
case Integral:
|
||||
case UncommonValue:
|
||||
case Pack:
|
||||
case Null:
|
||||
case Template:
|
||||
|
@ -420,10 +361,6 @@ void TemplateArgument::print(const PrintingPolicy &Policy,
|
|||
break;
|
||||
}
|
||||
|
||||
case UncommonValue:
|
||||
getAsUncommonValue().printPretty(Out, Policy, getUncommonValueType());
|
||||
break;
|
||||
|
||||
case NullPtr:
|
||||
Out << "nullptr";
|
||||
break;
|
||||
|
@ -506,9 +443,6 @@ SourceRange TemplateArgumentLoc::getSourceRange() const {
|
|||
case TemplateArgument::Integral:
|
||||
return getSourceIntegralExpression()->getSourceRange();
|
||||
|
||||
case TemplateArgument::UncommonValue:
|
||||
return getSourceUncommonValueExpression()->getSourceRange();
|
||||
|
||||
case TemplateArgument::Pack:
|
||||
case TemplateArgument::Null:
|
||||
return SourceRange();
|
||||
|
@ -537,18 +471,6 @@ static const T &DiagTemplateArg(const T &DB, const TemplateArgument &Arg) {
|
|||
case TemplateArgument::Integral:
|
||||
return DB << Arg.getAsIntegral().toString(10);
|
||||
|
||||
case TemplateArgument::UncommonValue: {
|
||||
// FIXME: We're guessing at LangOptions!
|
||||
SmallString<32> Str;
|
||||
llvm::raw_svector_ostream OS(Str);
|
||||
LangOptions LangOpts;
|
||||
LangOpts.CPlusPlus = true;
|
||||
PrintingPolicy Policy(LangOpts);
|
||||
Arg.getAsUncommonValue().printPretty(OS, Policy,
|
||||
Arg.getUncommonValueType());
|
||||
return DB << OS.str();
|
||||
}
|
||||
|
||||
case TemplateArgument::Template:
|
||||
return DB << Arg.getAsTemplate();
|
||||
|
||||
|
|
|
@ -562,7 +562,6 @@ void TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context,
|
|||
case TemplateArgument::Integral:
|
||||
case TemplateArgument::Declaration:
|
||||
case TemplateArgument::NullPtr:
|
||||
case TemplateArgument::UncommonValue:
|
||||
ArgInfos[i] = TemplateArgumentLocInfo();
|
||||
break;
|
||||
|
||||
|
|
|
@ -1953,14 +1953,6 @@ CGDebugInfo::CollectTemplateParams(const TemplateParameterList *TPList,
|
|||
TemplateParams.push_back(DBuilder.createTemplateValueParameter(
|
||||
TheCU, Name, TTy, defaultParameter, V));
|
||||
} break;
|
||||
case TemplateArgument::UncommonValue: {
|
||||
QualType T = TA.getUncommonValueType();
|
||||
llvm::DIType *TTy = getOrCreateType(T, Unit);
|
||||
llvm::Constant *V = ConstantEmitter(CGM).emitAbstract(
|
||||
SourceLocation(), TA.getAsUncommonValue(), T);
|
||||
TemplateParams.push_back(DBuilder.createTemplateValueParameter(
|
||||
TheCU, Name, TTy, defaultParameter, V));
|
||||
} break;
|
||||
case TemplateArgument::Template:
|
||||
TemplateParams.push_back(DBuilder.createTemplateTemplateParameter(
|
||||
TheCU, Name, nullptr,
|
||||
|
|
|
@ -1366,11 +1366,11 @@ llvm::Constant *ConstantEmitter::tryEmitConstantExpr(const ConstantExpr *CE) {
|
|||
if (!CE->hasAPValueResult())
|
||||
return nullptr;
|
||||
const Expr *Inner = CE->getSubExpr()->IgnoreImplicit();
|
||||
QualType RetType = Inner->getType();
|
||||
if (Inner->isLValue())
|
||||
RetType = CGF->getContext().getLValueReferenceType(RetType);
|
||||
else if (Inner->isXValue())
|
||||
RetType = CGF->getContext().getRValueReferenceType(RetType);
|
||||
QualType RetType;
|
||||
if (auto *Call = dyn_cast<CallExpr>(Inner))
|
||||
RetType = Call->getCallReturnType(CGF->getContext());
|
||||
else if (auto *Ctor = dyn_cast<CXXConstructExpr>(Inner))
|
||||
RetType = Ctor->getType();
|
||||
llvm::Constant *Res =
|
||||
emitAbstract(CE->getBeginLoc(), CE->getAPValueResult(), RetType);
|
||||
return Res;
|
||||
|
|
|
@ -983,10 +983,6 @@ void USRGenerator::VisitTemplateArgument(const TemplateArgument &Arg) {
|
|||
VisitType(Arg.getIntegralType());
|
||||
Out << Arg.getAsIntegral();
|
||||
break;
|
||||
|
||||
case TemplateArgument::UncommonValue:
|
||||
// FIXME: Visit value.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2657,7 +2657,6 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result,
|
|||
case TemplateArgument::Integral:
|
||||
case TemplateArgument::Expression:
|
||||
case TemplateArgument::NullPtr:
|
||||
case TemplateArgument::UncommonValue:
|
||||
// [Note: non-type template arguments do not contribute to the set of
|
||||
// associated namespaces. ]
|
||||
break;
|
||||
|
|
|
@ -5774,9 +5774,7 @@ static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From,
|
|||
|
||||
if (Notes.empty()) {
|
||||
// It's a constant expression.
|
||||
Expr *E = Result.get();
|
||||
if (!isa<ConstantExpr>(E))
|
||||
E = ConstantExpr::Create(S.Context, Result.get(), Value);
|
||||
Expr *E = ConstantExpr::Create(S.Context, Result.get(), Value);
|
||||
if (ReturnPreNarrowingValue)
|
||||
Value = std::move(PreNarrowingValue);
|
||||
return E;
|
||||
|
|
|
@ -4086,7 +4086,6 @@ static bool isTemplateArgumentTemplateParameter(
|
|||
case TemplateArgument::NullPtr:
|
||||
case TemplateArgument::Integral:
|
||||
case TemplateArgument::Declaration:
|
||||
case TemplateArgument::UncommonValue:
|
||||
case TemplateArgument::Pack:
|
||||
case TemplateArgument::TemplateExpansion:
|
||||
return false;
|
||||
|
@ -5420,7 +5419,6 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
|
|||
|
||||
case TemplateArgument::Declaration:
|
||||
case TemplateArgument::Integral:
|
||||
case TemplateArgument::UncommonValue:
|
||||
case TemplateArgument::NullPtr:
|
||||
// We've already checked this template argument, so just copy
|
||||
// it to the list of converted arguments.
|
||||
|
@ -5567,10 +5565,11 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
|
|||
return true;
|
||||
|
||||
case TemplateArgument::Declaration:
|
||||
llvm_unreachable("Declaration argument with template template parameter");
|
||||
case TemplateArgument::Integral:
|
||||
case TemplateArgument::UncommonValue:
|
||||
llvm_unreachable("Integral argument with template template parameter");
|
||||
case TemplateArgument::NullPtr:
|
||||
llvm_unreachable("non-type argument with template template parameter");
|
||||
llvm_unreachable("Null pointer argument with template template parameter");
|
||||
|
||||
case TemplateArgument::Pack:
|
||||
llvm_unreachable("Caller must expand template argument packs");
|
||||
|
@ -6937,9 +6936,37 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
|
|||
return ArgResult;
|
||||
}
|
||||
|
||||
// Prior to C++20, enforce restrictions on possible template argument
|
||||
// values.
|
||||
if (!getLangOpts().CPlusPlus20 && Value.isLValue()) {
|
||||
// Convert the APValue to a TemplateArgument.
|
||||
switch (Value.getKind()) {
|
||||
case APValue::None:
|
||||
assert(ParamType->isNullPtrType());
|
||||
Converted = TemplateArgument(CanonParamType, /*isNullPtr*/true);
|
||||
break;
|
||||
case APValue::Indeterminate:
|
||||
llvm_unreachable("result of constant evaluation should be initialized");
|
||||
break;
|
||||
case APValue::Int:
|
||||
assert(ParamType->isIntegralOrEnumerationType());
|
||||
Converted = TemplateArgument(Context, Value.getInt(), CanonParamType);
|
||||
break;
|
||||
case APValue::MemberPointer: {
|
||||
assert(ParamType->isMemberPointerType());
|
||||
|
||||
// FIXME: We need TemplateArgument representation and mangling for these.
|
||||
if (!Value.getMemberPointerPath().empty()) {
|
||||
Diag(Arg->getBeginLoc(),
|
||||
diag::err_template_arg_member_ptr_base_derived_not_supported)
|
||||
<< Value.getMemberPointerDecl() << ParamType
|
||||
<< Arg->getSourceRange();
|
||||
return ExprError();
|
||||
}
|
||||
|
||||
auto *VD = const_cast<ValueDecl*>(Value.getMemberPointerDecl());
|
||||
Converted = VD ? TemplateArgument(VD, CanonParamType)
|
||||
: TemplateArgument(CanonParamType, /*isNullPtr*/true);
|
||||
break;
|
||||
}
|
||||
case APValue::LValue: {
|
||||
// For a non-type template-parameter of pointer or reference type,
|
||||
// the value of the constant expression shall not refer to
|
||||
assert(ParamType->isPointerType() || ParamType->isReferenceType() ||
|
||||
|
@ -6955,7 +6982,8 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
|
|||
<< Arg->getSourceRange();
|
||||
return ExprError();
|
||||
}
|
||||
// -- a subobject [until C++20]
|
||||
// -- a subobject
|
||||
// FIXME: Until C++20
|
||||
if (Value.hasLValuePath() && Value.getLValuePath().size() == 1 &&
|
||||
VD && VD->getType()->isArrayType() &&
|
||||
Value.getLValuePath()[0].getAsArrayIndex() == 0 &&
|
||||
|
@ -6973,12 +7001,29 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
|
|||
"null reference should not be a constant expression");
|
||||
assert((!VD || !ParamType->isNullPtrType()) &&
|
||||
"non-null value of type nullptr_t?");
|
||||
Converted = VD ? TemplateArgument(VD, CanonParamType)
|
||||
: TemplateArgument(CanonParamType, /*isNullPtr*/true);
|
||||
break;
|
||||
}
|
||||
case APValue::Struct:
|
||||
case APValue::Union:
|
||||
// Get or create the corresponding template parameter object.
|
||||
Converted = TemplateArgument(
|
||||
Context.getTemplateParamObjectDecl(CanonParamType, Value),
|
||||
CanonParamType);
|
||||
break;
|
||||
case APValue::AddrLabelDiff:
|
||||
return Diag(StartLoc, diag::err_non_type_template_arg_addr_label_diff);
|
||||
case APValue::FixedPoint:
|
||||
case APValue::Float:
|
||||
case APValue::ComplexInt:
|
||||
case APValue::ComplexFloat:
|
||||
case APValue::Vector:
|
||||
case APValue::Array:
|
||||
return Diag(StartLoc, diag::err_non_type_template_arg_unsupported)
|
||||
<< ParamType;
|
||||
}
|
||||
|
||||
if (Value.isAddrLabelDiff())
|
||||
return Diag(StartLoc, diag::err_non_type_template_arg_addr_label_diff);
|
||||
|
||||
Converted = TemplateArgument(Context, CanonParamType, Value);
|
||||
return ArgResult.get();
|
||||
}
|
||||
|
||||
|
@ -7516,9 +7561,12 @@ Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg,
|
|||
/// This routine takes care of the mapping from an integral template
|
||||
/// argument (which may have any integral type) to the appropriate
|
||||
/// literal value.
|
||||
static Expr *BuildExpressionFromIntegralTemplateArgumentValue(
|
||||
Sema &S, QualType OrigT, const llvm::APSInt &Int, SourceLocation Loc) {
|
||||
assert(OrigT->isIntegralOrEnumerationType());
|
||||
ExprResult
|
||||
Sema::BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg,
|
||||
SourceLocation Loc) {
|
||||
assert(Arg.getKind() == TemplateArgument::Integral &&
|
||||
"Operation is only valid for integral template arguments");
|
||||
QualType OrigT = Arg.getIntegralType();
|
||||
|
||||
// If this is an enum type that we're instantiating, we need to use an integer
|
||||
// type the same size as the enumerator. We don't want to build an
|
||||
|
@ -7534,7 +7582,7 @@ static Expr *BuildExpressionFromIntegralTemplateArgumentValue(
|
|||
CharacterLiteral::CharacterKind Kind;
|
||||
if (T->isWideCharType())
|
||||
Kind = CharacterLiteral::Wide;
|
||||
else if (T->isChar8Type() && S.getLangOpts().Char8)
|
||||
else if (T->isChar8Type() && getLangOpts().Char8)
|
||||
Kind = CharacterLiteral::UTF8;
|
||||
else if (T->isChar16Type())
|
||||
Kind = CharacterLiteral::UTF16;
|
||||
|
@ -7543,131 +7591,29 @@ static Expr *BuildExpressionFromIntegralTemplateArgumentValue(
|
|||
else
|
||||
Kind = CharacterLiteral::Ascii;
|
||||
|
||||
E = new (S.Context) CharacterLiteral(Int.getZExtValue(), Kind, T, Loc);
|
||||
E = new (Context) CharacterLiteral(Arg.getAsIntegral().getZExtValue(),
|
||||
Kind, T, Loc);
|
||||
} else if (T->isBooleanType()) {
|
||||
E = new (S.Context) CXXBoolLiteralExpr(Int.getBoolValue(), T, Loc);
|
||||
E = new (Context) CXXBoolLiteralExpr(Arg.getAsIntegral().getBoolValue(),
|
||||
T, Loc);
|
||||
} else if (T->isNullPtrType()) {
|
||||
E = new (Context) CXXNullPtrLiteralExpr(Context.NullPtrTy, Loc);
|
||||
} else {
|
||||
E = IntegerLiteral::Create(S.Context, Int, T, Loc);
|
||||
E = IntegerLiteral::Create(Context, Arg.getAsIntegral(), T, Loc);
|
||||
}
|
||||
|
||||
if (OrigT->isEnumeralType()) {
|
||||
// FIXME: This is a hack. We need a better way to handle substituted
|
||||
// non-type template parameters.
|
||||
E = CStyleCastExpr::Create(S.Context, OrigT, VK_RValue, CK_IntegralCast, E,
|
||||
nullptr, S.CurFPFeatureOverrides(),
|
||||
S.Context.getTrivialTypeSourceInfo(OrigT, Loc),
|
||||
E = CStyleCastExpr::Create(Context, OrigT, VK_RValue, CK_IntegralCast, E,
|
||||
nullptr, CurFPFeatureOverrides(),
|
||||
Context.getTrivialTypeSourceInfo(OrigT, Loc),
|
||||
Loc, Loc);
|
||||
}
|
||||
|
||||
return E;
|
||||
}
|
||||
|
||||
static Expr *BuildExpressionFromNonTypeTemplateArgumentValue(
|
||||
Sema &S, QualType T, const APValue &Val, SourceLocation Loc) {
|
||||
auto MakeInitList = [&] (ArrayRef<Expr*> Elts) -> Expr* {
|
||||
auto *ILE = new (S.Context) InitListExpr(S.Context, Loc, Elts, Loc);
|
||||
ILE->setType(T);
|
||||
return ILE;
|
||||
};
|
||||
|
||||
switch (Val.getKind()) {
|
||||
case APValue::AddrLabelDiff:
|
||||
// This cannot occur in a template argument at all.
|
||||
case APValue::Array:
|
||||
case APValue::Struct:
|
||||
case APValue::Union:
|
||||
// These can only occur within a template parameter object, which is
|
||||
// represented as a TemplateArgument::Declaration.
|
||||
llvm_unreachable("unexpected template argument value");
|
||||
|
||||
case APValue::Int:
|
||||
return BuildExpressionFromIntegralTemplateArgumentValue(S, T, Val.getInt(),
|
||||
Loc);
|
||||
|
||||
case APValue::Float:
|
||||
return FloatingLiteral::Create(S.Context, Val.getFloat(), /*IsExact=*/true,
|
||||
T, Loc);
|
||||
|
||||
case APValue::FixedPoint:
|
||||
return FixedPointLiteral::CreateFromRawInt(
|
||||
S.Context, Val.getFixedPoint().getValue(), T, Loc,
|
||||
Val.getFixedPoint().getScale());
|
||||
|
||||
case APValue::ComplexInt: {
|
||||
QualType ElemT = T->castAs<ComplexType>()->getElementType();
|
||||
return MakeInitList({BuildExpressionFromIntegralTemplateArgumentValue(
|
||||
S, ElemT, Val.getComplexIntReal(), Loc),
|
||||
BuildExpressionFromIntegralTemplateArgumentValue(
|
||||
S, ElemT, Val.getComplexIntImag(), Loc)});
|
||||
}
|
||||
|
||||
case APValue::ComplexFloat: {
|
||||
QualType ElemT = T->castAs<ComplexType>()->getElementType();
|
||||
return MakeInitList(
|
||||
{FloatingLiteral::Create(S.Context, Val.getComplexFloatReal(), true,
|
||||
ElemT, Loc),
|
||||
FloatingLiteral::Create(S.Context, Val.getComplexFloatImag(), true,
|
||||
ElemT, Loc)});
|
||||
}
|
||||
|
||||
case APValue::Vector: {
|
||||
QualType ElemT = T->castAs<VectorType>()->getElementType();
|
||||
llvm::SmallVector<Expr *, 8> Elts;
|
||||
for (unsigned I = 0, N = Val.getVectorLength(); I != N; ++I)
|
||||
Elts.push_back(BuildExpressionFromNonTypeTemplateArgumentValue(
|
||||
S, ElemT, Val.getVectorElt(I), Loc));
|
||||
return MakeInitList(Elts);
|
||||
}
|
||||
|
||||
case APValue::None:
|
||||
case APValue::Indeterminate:
|
||||
// FIXME: Are these values possible?
|
||||
case APValue::LValue:
|
||||
case APValue::MemberPointer:
|
||||
// There isn't necessarily a valid equivalent source-level syntax for
|
||||
// these; in particular, a naive lowering might violate access control.
|
||||
// So for now we lower to a ConstantExpr holding the value, wrapped around
|
||||
// an OpaqueValueExpr.
|
||||
// FIXME: We should have a better representation for this.
|
||||
ExprValueKind VK = VK_RValue;
|
||||
if (T->isReferenceType()) {
|
||||
T = T->getPointeeType();
|
||||
VK = VK_LValue;
|
||||
}
|
||||
auto *OVE = new (S.Context) OpaqueValueExpr(Loc, T, VK);
|
||||
return ConstantExpr::Create(S.Context, OVE, Val);
|
||||
}
|
||||
}
|
||||
|
||||
ExprResult
|
||||
Sema::BuildExpressionFromNonTypeTemplateArgument(const TemplateArgument &Arg,
|
||||
SourceLocation Loc) {
|
||||
switch (Arg.getKind()) {
|
||||
case TemplateArgument::Null:
|
||||
case TemplateArgument::Type:
|
||||
case TemplateArgument::Template:
|
||||
case TemplateArgument::TemplateExpansion:
|
||||
case TemplateArgument::Pack:
|
||||
llvm_unreachable("not a non-type template argument");
|
||||
|
||||
case TemplateArgument::Expression:
|
||||
return Arg.getAsExpr();
|
||||
|
||||
case TemplateArgument::NullPtr:
|
||||
case TemplateArgument::Declaration:
|
||||
return BuildExpressionFromDeclTemplateArgument(
|
||||
Arg, Arg.getNonTypeTemplateArgumentType(), Loc);
|
||||
|
||||
case TemplateArgument::Integral:
|
||||
return BuildExpressionFromIntegralTemplateArgumentValue(
|
||||
*this, Arg.getIntegralType(), Arg.getAsIntegral(), Loc);
|
||||
|
||||
case TemplateArgument::UncommonValue:
|
||||
return BuildExpressionFromNonTypeTemplateArgumentValue(
|
||||
*this, Arg.getUncommonValueType(), Arg.getAsUncommonValue(), Loc);
|
||||
}
|
||||
}
|
||||
|
||||
/// Match two template parameters within template parameter lists.
|
||||
static bool MatchTemplateParameterKind(Sema &S, NamedDecl *New, NamedDecl *Old,
|
||||
bool Complain,
|
||||
|
|
|
@ -276,16 +276,6 @@ checkDeducedTemplateArguments(ASTContext &Context,
|
|||
// All other combinations are incompatible.
|
||||
return DeducedTemplateArgument();
|
||||
|
||||
case TemplateArgument::UncommonValue:
|
||||
// If we deduced a value and a dependent expression, keep the value.
|
||||
if (Y.getKind() == TemplateArgument::Expression ||
|
||||
(Y.getKind() == TemplateArgument::UncommonValue &&
|
||||
X.structurallyEquals(Y)))
|
||||
return X;
|
||||
|
||||
// All other combinations are incompatible.
|
||||
return DeducedTemplateArgument();
|
||||
|
||||
case TemplateArgument::Template:
|
||||
if (Y.getKind() == TemplateArgument::Template &&
|
||||
Context.hasSameTemplateName(X.getAsTemplate(), Y.getAsTemplate()))
|
||||
|
@ -2371,18 +2361,20 @@ DeduceTemplateArguments(Sema &S,
|
|||
return Sema::TDK_NonDeducedMismatch;
|
||||
|
||||
case TemplateArgument::Integral:
|
||||
if (Arg.getKind() == TemplateArgument::Integral &&
|
||||
hasSameExtendedValue(Param.getAsIntegral(), Arg.getAsIntegral()))
|
||||
return Sema::TDK_Success;
|
||||
if (Arg.getKind() == TemplateArgument::Integral) {
|
||||
if (hasSameExtendedValue(Param.getAsIntegral(), Arg.getAsIntegral()))
|
||||
return Sema::TDK_Success;
|
||||
|
||||
Info.FirstArg = Param;
|
||||
Info.SecondArg = Arg;
|
||||
return Sema::TDK_NonDeducedMismatch;
|
||||
Info.FirstArg = Param;
|
||||
Info.SecondArg = Arg;
|
||||
return Sema::TDK_NonDeducedMismatch;
|
||||
}
|
||||
|
||||
case TemplateArgument::UncommonValue:
|
||||
if (Arg.getKind() == TemplateArgument::UncommonValue &&
|
||||
Arg.structurallyEquals(Param))
|
||||
return Sema::TDK_Success;
|
||||
if (Arg.getKind() == TemplateArgument::Expression) {
|
||||
Info.FirstArg = Param;
|
||||
Info.SecondArg = Arg;
|
||||
return Sema::TDK_NonDeducedMismatch;
|
||||
}
|
||||
|
||||
Info.FirstArg = Param;
|
||||
Info.SecondArg = Arg;
|
||||
|
@ -2391,34 +2383,28 @@ DeduceTemplateArguments(Sema &S,
|
|||
case TemplateArgument::Expression:
|
||||
if (const NonTypeTemplateParmDecl *NTTP =
|
||||
getDeducedParameterFromExpr(Info, Param.getAsExpr())) {
|
||||
switch (Arg.getKind()) {
|
||||
case TemplateArgument::Integral:
|
||||
case TemplateArgument::Expression:
|
||||
case TemplateArgument::UncommonValue:
|
||||
return DeduceNonTypeTemplateArgument(
|
||||
S, TemplateParams, NTTP, DeducedTemplateArgument(Arg),
|
||||
Arg.getNonTypeTemplateArgumentType(), Info, Deduced);
|
||||
if (Arg.getKind() == TemplateArgument::Integral)
|
||||
return DeduceNonTypeTemplateArgument(S, TemplateParams, NTTP,
|
||||
Arg.getAsIntegral(),
|
||||
Arg.getIntegralType(),
|
||||
/*ArrayBound=*/false,
|
||||
Info, Deduced);
|
||||
if (Arg.getKind() == TemplateArgument::NullPtr)
|
||||
return DeduceNullPtrTemplateArgument(S, TemplateParams, NTTP,
|
||||
Arg.getNullPtrType(),
|
||||
Info, Deduced);
|
||||
if (Arg.getKind() == TemplateArgument::Expression)
|
||||
return DeduceNonTypeTemplateArgument(S, TemplateParams, NTTP,
|
||||
Arg.getAsExpr(), Info, Deduced);
|
||||
if (Arg.getKind() == TemplateArgument::Declaration)
|
||||
return DeduceNonTypeTemplateArgument(S, TemplateParams, NTTP,
|
||||
Arg.getAsDecl(),
|
||||
Arg.getParamTypeForDecl(),
|
||||
Info, Deduced);
|
||||
|
||||
case TemplateArgument::NullPtr:
|
||||
return DeduceNullPtrTemplateArgument(
|
||||
S, TemplateParams, NTTP, Arg.getNullPtrType(), Info, Deduced);
|
||||
|
||||
|
||||
case TemplateArgument::Declaration:
|
||||
return DeduceNonTypeTemplateArgument(
|
||||
S, TemplateParams, NTTP, Arg.getAsDecl(), Arg.getParamTypeForDecl(),
|
||||
Info, Deduced);
|
||||
|
||||
case TemplateArgument::Null:
|
||||
case TemplateArgument::Type:
|
||||
case TemplateArgument::Template:
|
||||
case TemplateArgument::TemplateExpansion:
|
||||
case TemplateArgument::Pack:
|
||||
Info.FirstArg = Param;
|
||||
Info.SecondArg = Arg;
|
||||
return Sema::TDK_NonDeducedMismatch;
|
||||
}
|
||||
llvm_unreachable("Unknown template argument kind");
|
||||
Info.FirstArg = Param;
|
||||
Info.SecondArg = Arg;
|
||||
return Sema::TDK_NonDeducedMismatch;
|
||||
}
|
||||
|
||||
// Can't deduce anything, but that's okay.
|
||||
|
@ -2606,9 +2592,6 @@ static bool isSameTemplateArg(ASTContext &Context,
|
|||
case TemplateArgument::Integral:
|
||||
return hasSameExtendedValue(X.getAsIntegral(), Y.getAsIntegral());
|
||||
|
||||
case TemplateArgument::UncommonValue:
|
||||
return X.structurallyEquals(Y);
|
||||
|
||||
case TemplateArgument::Expression: {
|
||||
llvm::FoldingSetNodeID XID, YID;
|
||||
X.getAsExpr()->Profile(XID, Context, true);
|
||||
|
@ -2674,9 +2657,9 @@ Sema::getTrivialTemplateArgumentLoc(const TemplateArgument &Arg,
|
|||
E);
|
||||
}
|
||||
|
||||
case TemplateArgument::Integral:
|
||||
case TemplateArgument::UncommonValue: {
|
||||
Expr *E = BuildExpressionFromNonTypeTemplateArgument(Arg, Loc).get();
|
||||
case TemplateArgument::Integral: {
|
||||
Expr *E =
|
||||
BuildExpressionFromIntegralTemplateArgument(Arg, Loc).getAs<Expr>();
|
||||
return TemplateArgumentLoc(TemplateArgument(E), E);
|
||||
}
|
||||
|
||||
|
@ -6120,8 +6103,11 @@ MarkUsedTemplateParameters(ASTContext &Ctx,
|
|||
case TemplateArgument::Null:
|
||||
case TemplateArgument::Integral:
|
||||
case TemplateArgument::Declaration:
|
||||
break;
|
||||
|
||||
case TemplateArgument::NullPtr:
|
||||
case TemplateArgument::UncommonValue:
|
||||
MarkUsedTemplateParameters(Ctx, TemplateArg.getNullPtrType(), OnlyDeduced,
|
||||
Depth, Used);
|
||||
break;
|
||||
|
||||
case TemplateArgument::Type:
|
||||
|
|
|
@ -1556,18 +1556,16 @@ ExprResult TemplateInstantiator::transformNonTypeTemplateParmRef(
|
|||
VD = nullptr;
|
||||
}
|
||||
|
||||
QualType paramType = arg.getNonTypeTemplateArgumentType();
|
||||
QualType paramType = VD ? arg.getParamTypeForDecl() : arg.getNullPtrType();
|
||||
assert(!paramType.isNull() && "type substitution failed for param type");
|
||||
assert(!paramType->isDependentType() && "param type still dependent");
|
||||
result = SemaRef.BuildExpressionFromDeclTemplateArgument(arg, paramType, loc);
|
||||
refParam = paramType->isReferenceType();
|
||||
} else {
|
||||
QualType paramType = arg.getNonTypeTemplateArgumentType();
|
||||
result = SemaRef.BuildExpressionFromNonTypeTemplateArgument(arg, loc);
|
||||
refParam = paramType->isReferenceType();
|
||||
result = SemaRef.BuildExpressionFromIntegralTemplateArgument(arg, loc);
|
||||
assert(result.isInvalid() ||
|
||||
SemaRef.Context.hasSameType(result.get()->getType(),
|
||||
paramType.getNonReferenceType()));
|
||||
arg.getIntegralType()));
|
||||
}
|
||||
|
||||
if (result.isInvalid())
|
||||
|
|
|
@ -1103,7 +1103,6 @@ Sema::getTemplateArgumentPackExpansionPattern(
|
|||
case TemplateArgument::NullPtr:
|
||||
case TemplateArgument::Template:
|
||||
case TemplateArgument::Integral:
|
||||
case TemplateArgument::UncommonValue:
|
||||
case TemplateArgument::Pack:
|
||||
case TemplateArgument::Null:
|
||||
return TemplateArgumentLoc();
|
||||
|
@ -1154,7 +1153,6 @@ Optional<unsigned> Sema::getFullyPackExpandedSize(TemplateArgument Arg) {
|
|||
case TemplateArgument::NullPtr:
|
||||
case TemplateArgument::TemplateExpansion:
|
||||
case TemplateArgument::Integral:
|
||||
case TemplateArgument::UncommonValue:
|
||||
case TemplateArgument::Pack:
|
||||
case TemplateArgument::Null:
|
||||
return None;
|
||||
|
|
|
@ -3557,7 +3557,6 @@ public:
|
|||
case TemplateArgument::Null:
|
||||
case TemplateArgument::Integral:
|
||||
case TemplateArgument::Declaration:
|
||||
case TemplateArgument::UncommonValue:
|
||||
case TemplateArgument::Pack:
|
||||
case TemplateArgument::TemplateExpansion:
|
||||
case TemplateArgument::NullPtr:
|
||||
|
@ -4230,8 +4229,7 @@ bool TreeTransform<Derived>::TransformTemplateArgument(
|
|||
|
||||
case TemplateArgument::Integral:
|
||||
case TemplateArgument::NullPtr:
|
||||
case TemplateArgument::Declaration:
|
||||
case TemplateArgument::UncommonValue: {
|
||||
case TemplateArgument::Declaration: {
|
||||
// Transform a resolved template argument straight to a resolved template
|
||||
// argument. We get here when substituting into an already-substituted
|
||||
// template type argument during concept satisfaction checking.
|
||||
|
@ -4258,15 +4256,9 @@ bool TreeTransform<Derived>::TransformTemplateArgument(
|
|||
else if (Arg.getKind() == TemplateArgument::NullPtr)
|
||||
Output = TemplateArgumentLoc(TemplateArgument(NewT, /*IsNullPtr=*/true),
|
||||
TemplateArgumentLocInfo());
|
||||
else if (Arg.getKind() == TemplateArgument::Declaration)
|
||||
else
|
||||
Output = TemplateArgumentLoc(TemplateArgument(NewD, NewT),
|
||||
TemplateArgumentLocInfo());
|
||||
else if (Arg.getKind() == TemplateArgument::UncommonValue)
|
||||
Output = TemplateArgumentLoc(
|
||||
TemplateArgument(getSema().Context, NewT, Arg.getAsUncommonValue()),
|
||||
TemplateArgumentLocInfo());
|
||||
else
|
||||
llvm_unreachable("unexpected template argument kind");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -7100,7 +7100,6 @@ ASTRecordReader::readTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind) {
|
|||
case TemplateArgument::Integral:
|
||||
case TemplateArgument::Declaration:
|
||||
case TemplateArgument::NullPtr:
|
||||
case TemplateArgument::UncommonValue:
|
||||
case TemplateArgument::Pack:
|
||||
// FIXME: Is this right?
|
||||
return TemplateArgumentLocInfo();
|
||||
|
|
|
@ -5350,7 +5350,6 @@ void ASTRecordWriter::AddTemplateArgumentLocInfo(
|
|||
case TemplateArgument::Integral:
|
||||
case TemplateArgument::Declaration:
|
||||
case TemplateArgument::NullPtr:
|
||||
case TemplateArgument::UncommonValue:
|
||||
case TemplateArgument::Pack:
|
||||
// FIXME: Is this right?
|
||||
break;
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
// RUN: %clang_cc1 -std=c++11 -fms-compatibility-version=19 -emit-llvm %s -o - -fms-extensions -fdelayed-template-parsing -triple=x86_64-pc-win32 | FileCheck -check-prefix X64 %s
|
||||
// RUN: %clang_cc1 -std=c++17 -fms-compatibility-version=19 -emit-llvm %s -o - -fms-extensions -fdelayed-template-parsing -triple=i386-pc-win32 | FileCheck %s
|
||||
// RUN: %clang_cc1 -std=c++17 -fms-compatibility-version=19 -emit-llvm %s -o - -fms-extensions -fdelayed-template-parsing -triple=x86_64-pc-win32 | FileCheck -check-prefix X64 %s
|
||||
// RUN: %clang_cc1 -std=c++20 -fms-compatibility-version=19 -emit-llvm %s -o - -fms-extensions -fdelayed-template-parsing -triple=x86_64-pc-win32 | FileCheck -check-prefix CXX20-X64 %s
|
||||
|
||||
template<typename T>
|
||||
class Class {
|
||||
|
@ -328,12 +327,3 @@ void fun_uint128(UInt128<(unsigned __int128)-1>) {}
|
|||
// X64: define {{.*}} @"?fun_uint128@@YAXU?$UInt128@$0DPPPPPPPPPPPPPPPAAAAAAAAAAAAAAAB@@@@Z"(
|
||||
void fun_uint128(UInt128<(unsigned __int128)9223372036854775807 * (unsigned __int128)9223372036854775807>) {}
|
||||
#endif
|
||||
|
||||
#if __cplusplus >= 202002L
|
||||
template<float> struct Float {};
|
||||
// CXX20-X64: define {{.*}} @"?f@@YAXU?$Float@$ADPIAAAAA@@@@Z"(
|
||||
void f(Float<1.0f>) {}
|
||||
template<auto> struct Auto {};
|
||||
// CXX20-X64: define {{.*}} @"?f@@YAXU?$Auto@$MMADPIAAAAA@@@@Z"(
|
||||
void f(Auto<1.0f>) {}
|
||||
#endif
|
||||
|
|
|
@ -226,16 +226,6 @@ namespace test16 {
|
|||
namespace cxx20 {
|
||||
template<auto> struct A {};
|
||||
template<typename T, T V> struct B {};
|
||||
// CXX20: define {{.*}} @_ZN5cxx201fENS_1AILf3f800000EEE(
|
||||
void f(A<1.0f>) {}
|
||||
// CXX20: define {{.*}} @_ZN5cxx201fENS_1AILd3ff0000000000000EEE(
|
||||
void f(A<1.0>) {}
|
||||
// CXX20: define {{.*}} @_ZN5cxx201fENS_1AILe3fff8000000000000000EEE(
|
||||
void f(A<1.0l>) {}
|
||||
// CXX20: define {{.*}} @_ZN5cxx201fENS_1AIXtlCiLi0ELi1EEEEE(
|
||||
void f(A<1i>) {}
|
||||
// CXX20: define {{.*}} @_ZN5cxx201fENS_1AIXtlCdLd0000000000000000ELd3ff0000000000000EEEEE(
|
||||
void f(A<1.0i>) {}
|
||||
|
||||
int x;
|
||||
// CXX20: define {{.*}} @_ZN5cxx201fENS_1AIXadL_ZNS_1xEEEEE(
|
||||
|
@ -255,24 +245,7 @@ namespace cxx20 {
|
|||
// CXX20: define {{.*}} @_ZN5cxx201fENS_1BIPKvXadL_ZNS_1xEEEEE(
|
||||
void f(B<const void*, (const void*)&x>) {}
|
||||
|
||||
struct Q { int x; } q;
|
||||
|
||||
// CXX20: define {{.*}} @_ZN5cxx201fENS_1AIXadsoiL_ZNS_1qEEEEEE(
|
||||
void f(A<&q.x>) {}
|
||||
// CXX20: define {{.*}} @_ZN5cxx201fENS_1BIPiXadsoiL_ZNS_1qEEEEEE(
|
||||
void f(B<int*, &q.x>) {}
|
||||
// CXX20: define {{.*}} @_ZN5cxx201fENS_1AIXadsoKiL_ZNS_1qEEEEEE(
|
||||
void f(A<(const int*)&q.x>) {}
|
||||
// CXX20: define {{.*}} @_ZN5cxx201fENS_1BIPKiXadsoS1_L_ZNS_1qEEEEEE
|
||||
void f(B<const int*, (const int*)&q.x>) {}
|
||||
// CXX20: define {{.*}} @_ZN5cxx201fENS_1AIXcvPvadsoiL_ZNS_1qEEEEEE(
|
||||
void f(A<(void*)&q.x>) {}
|
||||
// CXX20: define {{.*}} @_ZN5cxx201fENS_1BIPvXadsoiL_ZNS_1qEEEEEE(
|
||||
void f(B<void*, (void*)&q.x>) {}
|
||||
// CXX20: define {{.*}} @_ZN5cxx201fENS_1AIXcvPKvadsoiL_ZNS_1qEEEEEE(
|
||||
void f(A<(const void*)&q.x>) {}
|
||||
// CXX20: define {{.*}} @_ZN5cxx201fENS_1BIPKvXadsoiL_ZNS_1qEEEEEE(
|
||||
void f(B<const void*, (const void*)&q.x>) {}
|
||||
struct Q { int x; };
|
||||
|
||||
// CXX20: define {{.*}} @_ZN5cxx201fENS_1AIXadL_ZNS_1Q1xEEEEE(
|
||||
void f(A<&Q::x>) {}
|
||||
|
@ -282,17 +255,6 @@ namespace cxx20 {
|
|||
void f(A<(const int Q::*)&Q::x>) {}
|
||||
// CXX20: define {{.*}} @_ZN5cxx201fENS_1BIMNS_1QEKiXadL_ZNS1_1xEEEEE(
|
||||
void f(B<const int Q::*, (const int Q::*)&Q::x>) {}
|
||||
|
||||
struct R : Q {};
|
||||
|
||||
// CXX20: define {{.*}} @_ZN5cxx201fENS_1AIXmcMNS_1REiadL_ZNS_1Q1xEEEEEE(
|
||||
void f(A<(int R::*)&Q::x>) {}
|
||||
// CXX20: define {{.*}} @_ZN5cxx201fENS_1BIMNS_1REiXmcS2_adL_ZNS_1Q1xEEEEEE(
|
||||
void f(B<int R::*, (int R::*)&Q::x>) {}
|
||||
// CXX20: define {{.*}} @_ZN5cxx201fENS_1AIXmcMNS_1REKiadL_ZNS_1Q1xEEEEEE(
|
||||
void f(A<(const int R::*)&Q::x>) {}
|
||||
// CXX20: define {{.*}} @_ZN5cxx201fENS_1BIMNS_1REKiXmcS3_adL_ZNS_1Q1xEEEEEE(
|
||||
void f(B<const int R::*, (const int R::*)&Q::x>) {}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,81 +0,0 @@
|
|||
// RUN: %clang_cc1 -std=c++20 %s -emit-llvm -o - -triple x86_64-linux -DCONSTEXPR= | FileCheck %s
|
||||
// RUN: %clang_cc1 -std=c++20 %s -emit-llvm -o - -triple x86_64-linux -DCONSTEXPR=constexpr | FileCheck %s --check-prefix=CONST
|
||||
|
||||
template<typename T> CONSTEXPR T id(T v) { return v; }
|
||||
template<auto V> auto value = id(V);
|
||||
|
||||
// CHECK: call {{.*}} @_Z2idIiET_S0_(i32 1)
|
||||
// CONST: @_Z5valueILi1EE = weak_odr {{.*}} i32 1,
|
||||
template int value<1>;
|
||||
|
||||
// CHECK: call {{.*}} @_Z2idIyET_S0_(i64 -1)
|
||||
// CONST: @_Z5valueILy18446744073709551615EE = weak_odr {{.*}} i64 -1,
|
||||
template unsigned long long value<-1ULL>;
|
||||
|
||||
// CHECK: call {{.*}} @_Z2idIfET_S0_(float 1.000000e+00)
|
||||
// CONST: @_Z5valueILf3f800000EE = weak_odr {{.*}} float 1.000000e+00,
|
||||
template float value<1.0f>;
|
||||
// CHECK: call {{.*}} @_Z2idIdET_S0_(double 1.000000e+00)
|
||||
// CONST: @_Z5valueILd3ff0000000000000EE = weak_odr {{.*}} double 1.000000e+00,
|
||||
template double value<1.0>;
|
||||
|
||||
int n;
|
||||
// CHECK: call {{.*}} @_Z2idIPiET_S1_(i32* @n)
|
||||
// CONST: @_Z5valueIXadL_Z1nEEE = weak_odr {{.*}} i32* @n,
|
||||
template int *value<&n>;
|
||||
|
||||
struct A { int a[3]; } a;
|
||||
// CHECK: call {{.*}} @_Z2idIPiET_S1_(i32* getelementptr inbounds (%struct.A, %struct.A* @a, i32 0, i32 0, i32 0))
|
||||
// CONST: @_Z5valueIXadsoiL_Z1aEEEE = weak_odr {{.*}} i32* getelementptr inbounds (%struct.A, %struct.A* @a, i32 0, i32 0, i32 0),
|
||||
template int *value<&a.a[0]>;
|
||||
// CHECK: call {{.*}} @_Z2idIPiET_S1_(i32* bitcast (i8* getelementptr (i8, i8* bitcast (%struct.A* @a to i8*), i64 4) to i32*))
|
||||
// CONST: @_Z5valueIXadsoiL_Z1aE4EEE = weak_odr {{.*}} i32* bitcast (i8* getelementptr (i8, i8* bitcast (%struct.A* @a to i8*), i64 4) to i32*),
|
||||
template int *value<&a.a[1]>;
|
||||
// CHECK: call {{.*}} @_Z2idIPiET_S1_(i32* bitcast (i8* getelementptr (i8, i8* bitcast (%struct.A* @a to i8*), i64 8) to i32*))
|
||||
// CONST: @_Z5valueIXadsoiL_Z1aE8EEE = weak_odr {{.*}} i32* bitcast (i8* getelementptr (i8, i8* bitcast (%struct.A* @a to i8*), i64 8) to i32*),
|
||||
template int *value<&a.a[2]>;
|
||||
// CHECK: call {{.*}} @_Z2idIPiET_S1_(i32* bitcast (i8* getelementptr (i8, i8* bitcast (%struct.A* @a to i8*), i64 12) to i32*))
|
||||
// CONST: @_Z5valueIXadsoiL_Z1aE12pEEE = weak_odr {{.*}} i32* bitcast (i8* getelementptr (i8, i8* bitcast (%struct.A* @a to i8*), i64 12) to i32*),
|
||||
template int *value<&a.a[3]>;
|
||||
|
||||
struct B { int x, y; };
|
||||
// CHECK: call {{.*}} @_Z2idIM1BiET_S2_(i64 0)
|
||||
// CONST: @_Z5valueIXadL_ZN1B1xEEEE = weak_odr {{.*}} i64 0,
|
||||
template int B::*value<&B::x>;
|
||||
// CHECK: call {{.*}} @_Z2idIM1BiET_S2_(i64 4)
|
||||
// CONST: @_Z5valueIXadL_ZN1B1yEEEE = weak_odr {{.*}} i64 4,
|
||||
template int B::*value<&B::y>;
|
||||
|
||||
struct C : A, B { int z; };
|
||||
// CHECK: call {{.*}} @_Z2idIM1CiET_S2_(i64 12)
|
||||
// CONST: @_Z5valueIXmcM1CiadL_ZN1B1xEE12EEE = weak_odr {{.*}} i64 12,
|
||||
template int C::*value<(int C::*)&B::x>;
|
||||
// CHECK: call {{.*}} @_Z2idIM1BiET_S2_(i64 8)
|
||||
// CONST: @_Z5valueIXmcM1BiadL_ZN1C1zEEn12EEE = weak_odr {{.*}} i64 8,
|
||||
template int B::*value<(int B::*)&C::z>;
|
||||
|
||||
// CHECK: store i32 1, i32*
|
||||
// CHECK: store i32 2, i32*
|
||||
// CHECK: bitcast { i32, i32 }* %{{.*}} to i64*
|
||||
// CHECK: load i64,
|
||||
// CHECK: call {{.*}} @_Z2idICiET_S1_(i64 %
|
||||
// CONST: @_Z5valueIXtlCiLi1ELi2EEEE = weak_odr {{.*}} { i32, i32 } { i32 1, i32 2 },
|
||||
template _Complex int value<1 + 2j>;
|
||||
|
||||
// CHECK: store float 1.000000e+00, float*
|
||||
// CHECK: store float 2.000000e+00, float*
|
||||
// CHECK: bitcast { float, float }* %{{.*}} to <2 x float>*
|
||||
// CHECK: load <2 x float>,
|
||||
// CHECK: call {{.*}} @_Z2idICfET_S1_(<2 x float> %
|
||||
// CONST: @_Z5valueIXtlCfLf3f800000ELf40000000EEEE = weak_odr {{.*}} { float, float } { float 1.000000e+00, float 2.000000e+00 },
|
||||
template _Complex float value<1.0f + 2.0fj>;
|
||||
|
||||
using V3i __attribute__((ext_vector_type(3))) = int;
|
||||
// CHECK: call {{.*}} @_Z2idIDv3_iET_S1_(<3 x i32> <i32 1, i32 2, i32 3>)
|
||||
// CONST: @_Z5valueIXtlDv3_iLi1ELi2ELi3EEEE = weak_odr {{.*}} <3 x i32> <i32 1, i32 2, i32 3>
|
||||
template V3i value<V3i{1, 2, 3}>;
|
||||
|
||||
using V3f [[gnu::vector_size(12)]] = float;
|
||||
// CHECK: call {{.*}} @_Z2idIDv3_fET_S1_(<3 x float> <float 1.000000e+00, float 2.000000e+00, float 3.000000e+00>)
|
||||
// CONST: @_Z5valueIXtlDv3_fLf3f800000ELf40000000ELf40400000EEEE = weak_odr {{.*}} <3 x float> <float 1.000000e+00, float 2.000000e+00, float 3.000000e+00>
|
||||
template V3f value<V3f{1, 2, 3}>;
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
template<typename T, T val> struct A {};
|
||||
|
||||
template<typename T, typename U> constexpr bool is_same = false;
|
||||
template<typename T, typename U> constexpr bool is_same = false; // expected-note +{{here}}
|
||||
template<typename T> constexpr bool is_same<T, T> = true;
|
||||
|
||||
namespace String {
|
||||
|
@ -84,32 +84,34 @@ namespace PtrMem {
|
|||
constexpr int B::*b = &B::b;
|
||||
constexpr int C::*cb = b;
|
||||
constexpr int D::*db = b;
|
||||
constexpr int E::*ecb = cb;
|
||||
constexpr int E::*edb = db;
|
||||
constexpr int E::*ecb = cb; // expected-note +{{here}}
|
||||
constexpr int E::*edb = db; // expected-note +{{here}}
|
||||
|
||||
constexpr int E::*e = &E::e;
|
||||
constexpr int D::*de = (int D::*)e;
|
||||
constexpr int C::*ce = (int C::*)e;
|
||||
constexpr int B::*bde = (int B::*)de;
|
||||
constexpr int B::*bce = (int B::*)ce;
|
||||
constexpr int B::*bde = (int B::*)de; // expected-note +{{here}}
|
||||
constexpr int B::*bce = (int B::*)ce; // expected-note +{{here}}
|
||||
|
||||
// FIXME: This should all be accepted, but we don't yet have a representation
|
||||
// nor mangling for this form of template argument.
|
||||
using Ab = A<int B::*, b>;
|
||||
using Ab = A<int B::*, &B::b>;
|
||||
using Abce = A<int B::*, bce>;
|
||||
using Abde = A<int B::*, bde>;
|
||||
static_assert(!is_same<Ab, Abce>, "");
|
||||
static_assert(!is_same<Ab, Abde>, "");
|
||||
static_assert(!is_same<Abce, Abde>, "");
|
||||
static_assert(is_same<Abce, A<int B::*, (int B::*)(int C::*)&E::e>>, "");
|
||||
using Abce = A<int B::*, bce>; // expected-error {{not supported}}
|
||||
using Abde = A<int B::*, bde>; // expected-error {{not supported}}
|
||||
static_assert(!is_same<Ab, Abce>, ""); // expected-error {{undeclared}} expected-error {{must be a type}}
|
||||
static_assert(!is_same<Ab, Abde>, ""); // expected-error {{undeclared}} expected-error {{must be a type}}
|
||||
static_assert(!is_same<Abce, Abde>, ""); // expected-error 2{{undeclared}} expected-error {{must be a type}}
|
||||
static_assert(is_same<Abce, A<int B::*, (int B::*)(int C::*)&E::e>>, ""); // expected-error {{undeclared}} expected-error {{not supported}}
|
||||
|
||||
using Ae = A<int E::*, e>;
|
||||
using Ae = A<int E::*, &E::e>;
|
||||
using Aecb = A<int E::*, ecb>;
|
||||
using Aedb = A<int E::*, edb>;
|
||||
static_assert(!is_same<Ae, Aecb>, "");
|
||||
static_assert(!is_same<Ae, Aedb>, "");
|
||||
static_assert(!is_same<Aecb, Aedb>, "");
|
||||
static_assert(is_same<Aecb, A<int E::*, (int E::*)(int C::*)&B::b>>, "");
|
||||
using Aecb = A<int E::*, ecb>; // expected-error {{not supported}}
|
||||
using Aedb = A<int E::*, edb>; // expected-error {{not supported}}
|
||||
static_assert(!is_same<Ae, Aecb>, ""); // expected-error {{undeclared}} expected-error {{must be a type}}
|
||||
static_assert(!is_same<Ae, Aedb>, ""); // expected-error {{undeclared}} expected-error {{must be a type}}
|
||||
static_assert(!is_same<Aecb, Aedb>, ""); // expected-error 2{{undeclared}} expected-error {{must be a type}}
|
||||
static_assert(is_same<Aecb, A<int E::*, (int E::*)(int C::*)&B::b>>, ""); // expected-error {{undeclared}} expected-error {{not supported}}
|
||||
|
||||
using An = A<int E::*, nullptr>;
|
||||
using A0 = A<int E::*, (int E::*)0>;
|
||||
|
@ -203,9 +205,9 @@ namespace Auto {
|
|||
|
||||
struct Y : X {};
|
||||
void type_affects_identity(B<&X::n>) {}
|
||||
void type_affects_identity(B<(int Y::*)&X::n>) {}
|
||||
void type_affects_identity(B<(int Y::*)&X::n>) {} // FIXME: expected-error {{sorry}}
|
||||
void type_affects_identity(B<(const int X::*)&X::n>) {}
|
||||
void type_affects_identity(B<(const int Y::*)&X::n>) {}
|
||||
void type_affects_identity(B<(const int Y::*)&X::n>) {} // FIXME: expected-error {{sorry}}
|
||||
|
||||
// A case where we need to do auto-deduction, and check whether the
|
||||
// resulting dependent types match during partial ordering. These
|
||||
|
|
|
@ -8,8 +8,8 @@ namespace std {
|
|||
|
||||
// floating-point arguments
|
||||
template<float> struct Float {};
|
||||
using F1 = Float<1.0f>;
|
||||
using F1 = Float<2.0f / 2>;
|
||||
using F1 = Float<1.0f>; // FIXME expected-error {{sorry}}
|
||||
using F1 = Float<2.0f / 2>; // FIXME expected-error {{sorry}}
|
||||
|
||||
struct S { int n[3]; } s; // expected-note 1+{{here}}
|
||||
union U { int a, b; } u;
|
||||
|
@ -17,24 +17,24 @@ int n; // expected-note 1+{{here}}
|
|||
|
||||
// pointers to subobjects
|
||||
template<int *> struct IntPtr {};
|
||||
using IPn = IntPtr<&n + 1>;
|
||||
using IPn = IntPtr<&n + 1>;
|
||||
using IPn = IntPtr<&n + 1>; // FIXME expected-error {{refers to subobject}}
|
||||
using IPn = IntPtr<&n + 1>; // FIXME expected-error {{refers to subobject}}
|
||||
|
||||
using IP2 = IntPtr<&s.n[2]>;
|
||||
using IP2 = IntPtr<s.n + 2>;
|
||||
using IP2 = IntPtr<&s.n[2]>; // FIXME expected-error {{refers to subobject}}
|
||||
using IP2 = IntPtr<s.n + 2>; // FIXME expected-error {{refers to subobject}}
|
||||
|
||||
using IP3 = IntPtr<&s.n[3]>;
|
||||
using IP3 = IntPtr<s.n + 3>;
|
||||
using IP3 = IntPtr<&s.n[3]>; // FIXME expected-error {{refers to subobject}}
|
||||
using IP3 = IntPtr<s.n + 3>; // FIXME expected-error {{refers to subobject}}
|
||||
|
||||
template<int &> struct IntRef {};
|
||||
using IRn = IntRef<*(&n + 1)>; // expected-error {{not a constant expression}} expected-note {{dereferenced pointer past the end of 'n'}}
|
||||
using IRn = IntRef<*(&n + 1)>; // expected-error {{not a constant expression}} expected-note {{dereferenced pointer past the end of 'n'}}
|
||||
using IPn = IntRef<*(&n + 1)>; // expected-error {{not a constant expression}} expected-note {{dereferenced pointer past the end of 'n'}}
|
||||
using IPn = IntRef<*(&n + 1)>; // expected-error {{not a constant expression}} expected-note {{dereferenced pointer past the end of 'n'}}
|
||||
|
||||
using IR2 = IntRef<s.n[2]>;
|
||||
using IR2 = IntRef<*(s.n + 2)>;
|
||||
using IP2 = IntRef<s.n[2]>; // FIXME expected-error {{refers to subobject}}
|
||||
using IP2 = IntRef<*(s.n + 2)>; // FIXME expected-error {{refers to subobject}}
|
||||
|
||||
using IR3 = IntRef<s.n[3]>; // expected-error {{not a constant expression}} expected-note {{dereferenced pointer past the end of subobject of 's'}}
|
||||
using IR3 = IntRef<*(s.n + 3)>; // expected-error {{not a constant expression}} expected-note {{dereferenced pointer past the end of subobject of 's'}}
|
||||
using IP3 = IntRef<s.n[3]>; // expected-error {{not a constant expression}} expected-note {{dereferenced pointer past the end of subobject of 's'}}
|
||||
using IP3 = IntRef<*(s.n + 3)>; // expected-error {{not a constant expression}} expected-note {{dereferenced pointer past the end of subobject of 's'}}
|
||||
|
||||
// classes
|
||||
template<S> struct Struct {};
|
||||
|
@ -48,12 +48,12 @@ using U1 = Union<U{.b = 1}>; // expected-error {{different types}}
|
|||
|
||||
// miscellaneous scalar types
|
||||
template<_Complex int> struct ComplexInt {};
|
||||
using CI = ComplexInt<1 + 3i>;
|
||||
using CI = ComplexInt<3i + 1>;
|
||||
using CI = ComplexInt<1 + 3i>; // FIXME: expected-error {{sorry}}
|
||||
using CI = ComplexInt<1 + 3i>; // FIXME: expected-error {{sorry}}
|
||||
|
||||
template<_Complex float> struct ComplexFloat {};
|
||||
using CF = ComplexFloat<1.0f + 3.0fi>;
|
||||
using CF = ComplexFloat<3.0fi + 1.0f>;
|
||||
using CF = ComplexFloat<1.0f + 3.0fi>; // FIXME: expected-error {{sorry}}
|
||||
using CF = ComplexFloat<1.0f + 3.0fi>; // FIXME: expected-error {{sorry}}
|
||||
|
||||
namespace ClassNTTP {
|
||||
struct A { // expected-note 2{{candidate}}
|
||||
|
@ -307,11 +307,11 @@ namespace dependent {
|
|||
if constexpr (N < 10)
|
||||
return R<n>();
|
||||
else if constexpr (N < 20)
|
||||
return R<vn.v>();
|
||||
return R<vn.v>(); // FIXME: expected-error 2{{refers to subobject}}
|
||||
else if constexpr (N < 30)
|
||||
return S<&n>();
|
||||
else if constexpr (N < 40)
|
||||
return S<&vn.v>();
|
||||
return S<&vn.v>(); // FIXME: expected-error 2{{refers to subobject}}
|
||||
else if constexpr (N < 50)
|
||||
return T<V<int&>{n}>();
|
||||
else if constexpr (N < 60)
|
||||
|
@ -322,15 +322,15 @@ namespace dependent {
|
|||
return T<V<int*>{&vn.v}>();
|
||||
}
|
||||
template<int Base> void check() {
|
||||
auto v = f<Base + 0>();
|
||||
auto w = f<Base + 1>();
|
||||
auto v = f<Base + 0>(); // FIXME: expected-note 2{{instantiation of}}
|
||||
auto w = f<Base + 1>(); // FIXME: expected-note 2{{instantiation of}}
|
||||
static_assert(!__is_same(decltype(v), decltype(w)));
|
||||
static_assert(v != w);
|
||||
}
|
||||
template void check<0>();
|
||||
template void check<10>();
|
||||
template void check<10>(); // FIXME: expected-note 2{{instantiation of}}
|
||||
template void check<20>();
|
||||
template void check<30>();
|
||||
template void check<30>(); // FIXME: expected-note 2{{instantiation of}}
|
||||
template void check<40>();
|
||||
template void check<50>();
|
||||
template void check<60>();
|
||||
|
|
|
@ -1493,11 +1493,6 @@ bool CursorVisitor::VisitTemplateArgumentLoc(const TemplateArgumentLoc &TAL) {
|
|||
return Visit(MakeCXCursor(E, StmtParent, TU, RegionOfInterest));
|
||||
return false;
|
||||
|
||||
case TemplateArgument::UncommonValue:
|
||||
if (Expr *E = TAL.getSourceUncommonValueExpression())
|
||||
return Visit(MakeCXCursor(E, StmtParent, TU, RegionOfInterest));
|
||||
return false;
|
||||
|
||||
case TemplateArgument::NullPtr:
|
||||
if (Expr *E = TAL.getSourceNullPtrExpression())
|
||||
return Visit(MakeCXCursor(E, StmtParent, TU, RegionOfInterest));
|
||||
|
|
|
@ -1375,9 +1375,6 @@ enum CXTemplateArgumentKind clang_Cursor_getTemplateArgumentKind(CXCursor C,
|
|||
return CXTemplateArgumentKind_NullPtr;
|
||||
case TemplateArgument::Integral:
|
||||
return CXTemplateArgumentKind_Integral;
|
||||
case TemplateArgument::UncommonValue:
|
||||
// FIXME: Expose these values.
|
||||
return CXTemplateArgumentKind_Invalid;
|
||||
case TemplateArgument::Template:
|
||||
return CXTemplateArgumentKind_Template;
|
||||
case TemplateArgument::TemplateExpansion:
|
||||
|
|
Loading…
Reference in New Issue