diff options
46 files changed, 230 insertions, 1106 deletions
diff --git a/clang-tools-extra/clangd/DumpAST.cpp b/clang-tools-extra/clangd/DumpAST.cpp index 9a525ef..b0cec65 100644 --- a/clang-tools-extra/clangd/DumpAST.cpp +++ b/clang-tools-extra/clangd/DumpAST.cpp @@ -143,7 +143,6 @@ class DumpVisitor : public RecursiveASTVisitor<DumpVisitor> { TEMPLATE_ARGUMENT_KIND(Declaration); TEMPLATE_ARGUMENT_KIND(Template); TEMPLATE_ARGUMENT_KIND(TemplateExpansion); - TEMPLATE_ARGUMENT_KIND(StructuralValue); #undef TEMPLATE_ARGUMENT_KIND } llvm_unreachable("Unhandled ArgKind enum"); diff --git a/clang-tools-extra/clangd/FindTarget.cpp b/clang-tools-extra/clangd/FindTarget.cpp index e702c6b..3d73e77 100644 --- a/clang-tools-extra/clangd/FindTarget.cpp +++ b/clang-tools-extra/clangd/FindTarget.cpp @@ -1039,7 +1039,6 @@ public: case TemplateArgument::Pack: case TemplateArgument::Type: case TemplateArgument::Expression: - case TemplateArgument::StructuralValue: break; // Handled by VisitType and VisitExpression. }; return RecursiveASTVisitor::TraverseTemplateArgumentLoc(A); diff --git a/clang/include/clang/AST/ODRHash.h b/clang/include/clang/AST/ODRHash.h index a1caa6d..cedf644 100644 --- a/clang/include/clang/AST/ODRHash.h +++ b/clang/include/clang/AST/ODRHash.h @@ -25,7 +25,6 @@ namespace clang { -class APValue; class Decl; class IdentifierInfo; class NestedNameSpecifier; @@ -102,8 +101,6 @@ public: // Save booleans until the end to lower the size of data to process. void AddBoolean(bool value); - void AddStructuralValue(const APValue &); - static bool isSubDeclToBeProcessed(const Decl *D, const DeclContext *Parent); private: diff --git a/clang/include/clang/AST/PropertiesBase.td b/clang/include/clang/AST/PropertiesBase.td index 0270c08..d86c4eb 100644 --- a/clang/include/clang/AST/PropertiesBase.td +++ b/clang/include/clang/AST/PropertiesBase.td @@ -808,20 +808,6 @@ let Class = PropertyTypeCase<TemplateArgument, "Integral"> in { return TemplateArgument(ctx, value, type, isDefaulted); }]>; } -let Class = PropertyTypeCase<TemplateArgument, "StructuralValue"> in { - def : Property<"value", APValue> { - let Read = [{ node.getAsStructuralValue() }]; - } - def : Property<"type", QualType> { - let Read = [{ node.getStructuralValueType() }]; - } - def : Property<"isDefaulted", Bool> { - let Read = [{ node.getIsDefaulted() }]; - } - def : Creator<[{ - return TemplateArgument(ctx, type, value, isDefaulted); - }]>; -} let Class = PropertyTypeCase<TemplateArgument, "Template"> in { def : Property<"name", TemplateName> { let Read = [{ node.getAsTemplateOrTemplatePattern() }]; diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index 2aee6a9..8f2714e 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -850,7 +850,6 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgument( case TemplateArgument::Declaration: case TemplateArgument::Integral: case TemplateArgument::NullPtr: - case TemplateArgument::StructuralValue: return true; case TemplateArgument::Type: @@ -883,7 +882,6 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLoc( case TemplateArgument::Declaration: case TemplateArgument::Integral: case TemplateArgument::NullPtr: - case TemplateArgument::StructuralValue: return true; case TemplateArgument::Type: { diff --git a/clang/include/clang/AST/TemplateArgumentVisitor.h b/clang/include/clang/AST/TemplateArgumentVisitor.h index cf0d322..190aa97 100644 --- a/clang/include/clang/AST/TemplateArgumentVisitor.h +++ b/clang/include/clang/AST/TemplateArgumentVisitor.h @@ -37,7 +37,6 @@ public: DISPATCH(Declaration); DISPATCH(NullPtr); DISPATCH(Integral); - DISPATCH(StructuralValue); DISPATCH(Template); DISPATCH(TemplateExpansion); DISPATCH(Expression); @@ -60,7 +59,6 @@ public: VISIT_METHOD(Declaration); VISIT_METHOD(NullPtr); VISIT_METHOD(Integral); - VISIT_METHOD(StructuralValue); VISIT_METHOD(Template); VISIT_METHOD(TemplateExpansion); VISIT_METHOD(Expression); diff --git a/clang/include/clang/AST/TemplateBase.h b/clang/include/clang/AST/TemplateBase.h index fea2c8c..b7cd71f 100644 --- a/clang/include/clang/AST/TemplateBase.h +++ b/clang/include/clang/AST/TemplateBase.h @@ -50,7 +50,6 @@ template <> struct PointerLikeTypeTraits<clang::Expr *> { namespace clang { -class APValue; class ASTContext; class Expr; struct PrintingPolicy; @@ -81,13 +80,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. - /// TODO: merge Declaration, NullPtr and Integral into this? - StructuralValue, - /// The template argument is a template name that was provided for a /// template template parameter. Template, @@ -138,14 +130,6 @@ private: }; void *Type; }; - struct V { - LLVM_PREFERRED_TYPE(ArgKind) - unsigned Kind : 31; - LLVM_PREFERRED_TYPE(bool) - unsigned IsDefaulted : 1; - APValue *Value; - void *Type; - }; struct A { LLVM_PREFERRED_TYPE(ArgKind) unsigned Kind : 31; @@ -172,19 +156,11 @@ private: union { struct DA DeclArg; struct I Integer; - struct V Value; struct A Args; struct TA TemplateArg; struct TV TypeOrValue; }; - void initFromType(QualType T, bool IsNullPtr, bool IsDefaulted); - void initFromDeclaration(ValueDecl *D, QualType QT, bool IsDefaulted); - void initFromIntegral(const ASTContext &Ctx, const llvm::APSInt &Value, - QualType Type, bool IsDefaulted); - void initFromStructural(const ASTContext &Ctx, QualType Type, - const APValue &V, bool IsDefaulted); - public: /// Construct an empty, invalid template argument. constexpr TemplateArgument() : TypeOrValue({Null, 0, /* IsDefaulted */ 0}) {} @@ -192,22 +168,25 @@ public: /// Construct a template type argument. TemplateArgument(QualType T, bool isNullPtr = false, bool IsDefaulted = false) { - initFromType(T, isNullPtr, IsDefaulted); + TypeOrValue.Kind = isNullPtr ? NullPtr : Type; + TypeOrValue.IsDefaulted = IsDefaulted; + 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, bool IsDefaulted = false) { - initFromDeclaration(D, QT, IsDefaulted); + assert(D && "Expected decl"); + DeclArg.Kind = Declaration; + DeclArg.IsDefaulted = IsDefaulted; + DeclArg.QT = QT.getAsOpaquePtr(); + DeclArg.D = D; } /// 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, bool IsDefaulted = false); - - /// 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, bool IsDefaulted = false); /// Construct an integral constant template argument with the same @@ -318,7 +297,7 @@ public: /// Retrieve the type for a type template argument. QualType getAsType() const { assert(getKind() == Type && "Unexpected kind"); - return QualType::getFromOpaquePtr(reinterpret_cast<void *>(TypeOrValue.V)); + return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue.V)); } /// Retrieve the declaration for a declaration non-type @@ -336,7 +315,7 @@ public: /// Retrieve the type for null non-type template argument. QualType getNullPtrType() const { assert(getKind() == NullPtr && "Unexpected kind"); - return QualType::getFromOpaquePtr(reinterpret_cast<void *>(TypeOrValue.V)); + return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue.V)); } /// Retrieve the template name for a template name argument. @@ -392,14 +371,6 @@ public: /// default template parameter. bool getIsDefaulted() const { return (bool)TypeOrValue.IsDefaulted; } - /// Get the value of a StructuralValue. - const APValue &getAsStructuralValue() const { return *Value.Value; } - - /// Get the type of a StructuralValue. - QualType getStructuralValueType() 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; @@ -545,7 +516,6 @@ public: assert(Argument.getKind() == TemplateArgument::NullPtr || Argument.getKind() == TemplateArgument::Integral || Argument.getKind() == TemplateArgument::Declaration || - Argument.getKind() == TemplateArgument::StructuralValue || Argument.getKind() == TemplateArgument::Expression); } @@ -571,9 +541,13 @@ public: /// - Fetches the full source range of the argument. SourceRange getSourceRange() const LLVM_READONLY; - const TemplateArgument &getArgument() const { return Argument; } + const TemplateArgument &getArgument() const { + return Argument; + } - TemplateArgumentLocInfo getLocInfo() const { return LocInfo; } + TemplateArgumentLocInfo getLocInfo() const { + return LocInfo; + } TypeSourceInfo *getTypeSourceInfo() const { if (Argument.getKind() != TemplateArgument::Type) @@ -601,11 +575,6 @@ public: return LocInfo.getAsExpr(); } - Expr *getSourceStructuralValueExpression() const { - assert(Argument.getKind() == TemplateArgument::StructuralValue); - return LocInfo.getAsExpr(); - } - NestedNameSpecifierLoc getTemplateQualifierLoc() const { if (Argument.getKind() != TemplateArgument::Template && Argument.getKind() != TemplateArgument::TemplateExpansion) @@ -637,7 +606,8 @@ class TemplateArgumentListInfo { public: TemplateArgumentListInfo() = default; - TemplateArgumentListInfo(SourceLocation LAngleLoc, SourceLocation RAngleLoc) + TemplateArgumentListInfo(SourceLocation LAngleLoc, + SourceLocation RAngleLoc) : LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc) {} // This can leak if used in an AST node, use ASTTemplateArgumentListInfo @@ -656,15 +626,21 @@ public: return Arguments.data(); } - llvm::ArrayRef<TemplateArgumentLoc> arguments() const { return Arguments; } + llvm::ArrayRef<TemplateArgumentLoc> arguments() const { + return Arguments; + } const TemplateArgumentLoc &operator[](unsigned I) const { return Arguments[I]; } - TemplateArgumentLoc &operator[](unsigned I) { return Arguments[I]; } + TemplateArgumentLoc &operator[](unsigned I) { + return Arguments[I]; + } - void addArgument(const TemplateArgumentLoc &Loc) { Arguments.push_back(Loc); } + void addArgument(const TemplateArgumentLoc &Loc) { + Arguments.push_back(Loc); + } }; /// Represents an explicit template argument list in C++, e.g., diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index a1c32ab..cce58b5 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -5161,6 +5161,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< + "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">; @@ -5212,6 +5214,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< + "non-type template argument of pointer-to-member type %1 that refers " + "to member %q0 of a different class is not supported yet">; def err_template_arg_invalid : Error< "non-type template argument '%0' is invalid">; def ext_template_arg_extra_parens : ExtWarn< diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 1f1cbd1..d4c33dd 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -8595,8 +8595,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. diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 5eb7aa3..0fc0831 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -6754,11 +6754,6 @@ ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) const { case TemplateArgument::Integral: return TemplateArgument(Arg, getCanonicalType(Arg.getIntegralType())); - case TemplateArgument::StructuralValue: - return TemplateArgument(*this, - getCanonicalType(Arg.getStructuralValueType()), - Arg.getAsStructuralValue()); - case TemplateArgument::Type: return TemplateArgument(getCanonicalType(Arg.getAsType()), /*isNullPtr*/ false, Arg.getIsDefaulted()); diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 12734d6..b364796 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -823,17 +823,6 @@ ASTNodeImporter::import(const TemplateArgument &From) { From.getIsDefaulted()); } - case TemplateArgument::StructuralValue: { - ExpectedType ToTypeOrErr = import(From.getStructuralValueType()); - if (!ToTypeOrErr) - return ToTypeOrErr.takeError(); - Expected<APValue> ToValueOrErr = import(From.getAsStructuralValue()); - if (!ToValueOrErr) - return ToValueOrErr.takeError(); - return TemplateArgument(Importer.getToContext(), *ToTypeOrErr, - *ToValueOrErr); - } - case TemplateArgument::Template: { Expected<TemplateName> ToTemplateOrErr = import(From.getAsTemplate()); if (!ToTemplateOrErr) @@ -3583,8 +3572,6 @@ private: case TemplateArgument::NullPtr: // FIXME: The type is not allowed to be in the function? return CheckType(Arg.getNullPtrType()); - case TemplateArgument::StructuralValue: - return CheckType(Arg.getStructuralValueType()); case TemplateArgument::Pack: for (const auto &PackArg : Arg.getPackAsArray()) if (checkTemplateArgument(PackArg)) diff --git a/clang/lib/AST/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp index be7a850a..5103fc8 100644 --- a/clang/lib/AST/ASTStructuralEquivalence.cpp +++ b/clang/lib/AST/ASTStructuralEquivalence.cpp @@ -685,9 +685,6 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, return IsStructurallyEquivalent(Context, Arg1.getAsExpr(), Arg2.getAsExpr()); - case TemplateArgument::StructuralValue: - return Arg1.structurallyEquals(Arg2); - case TemplateArgument::Pack: return IsStructurallyEquivalent(Context, Arg1.pack_elements(), Arg2.pack_elements()); diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 26fdfa0..2c3a0af 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -343,10 +343,6 @@ LinkageComputer::getLVForTemplateArgumentList(ArrayRef<TemplateArgument> Args, LV.merge(getTypeLinkageAndVisibility(Arg.getNullPtrType())); continue; - case TemplateArgument::StructuralValue: - LV.merge(getLVForValue(Arg.getAsStructuralValue(), computation)); - continue; - case TemplateArgument::Template: case TemplateArgument::TemplateExpansion: if (TemplateDecl *Template = diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 40b1e08..f78265df 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -4833,23 +4833,9 @@ recurse: E = cast<CXXStdInitializerListExpr>(E)->getSubExpr(); goto recurse; - case Expr::SubstNonTypeTemplateParmExprClass: { - // Mangle a substituted parameter the same way we mangle the template - // argument. - 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()); - assert(CE->hasAPValueResult() && "expected the NTTP to have an APValue"); - mangleValueInTemplateArg(ParamType, CE->getAPValueResult(), false, - /*NeedExactType=*/true); - break; - } - // The remaining cases all happen to be substituted with expressions that - // mangle the same as a corresponding template argument anyway. + case Expr::SubstNonTypeTemplateParmExprClass: E = cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement(); goto recurse; - } case Expr::UserDefinedLiteralClass: // We follow g++'s approach of mangling a UDL as a call to the literal @@ -6078,11 +6064,6 @@ void CXXNameMangler::mangleTemplateArg(TemplateArgument A, bool NeedExactType) { mangleNullPointer(A.getNullPtrType()); break; } - case TemplateArgument::StructuralValue: - mangleValueInTemplateArg(A.getStructuralValueType(), - A.getAsStructuralValue(), - /*TopLevel=*/true, NeedExactType); - break; case TemplateArgument::Pack: { // <template-arg> ::= J <template-arg>* E Out << 'J'; @@ -6491,20 +6472,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*' diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp index 36b5bf6..8346ad8 100644 --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/lib/AST/MicrosoftMangle.cpp @@ -337,7 +337,6 @@ class MicrosoftCXXNameMangler { public: enum QualifierMangleMode { QMM_Drop, QMM_Mangle, QMM_Escape, QMM_Result }; - enum class TplArgKind { ClassNTTP, StructuralValue }; MicrosoftCXXNameMangler(MicrosoftMangleContextImpl &C, raw_ostream &Out_) : Context(C), Out(Out_), Structor(nullptr), StructorType(-1), @@ -454,7 +453,7 @@ private: const TemplateArgumentList &TemplateArgs); void mangleTemplateArg(const TemplateDecl *TD, const TemplateArgument &TA, const NamedDecl *Parm); - void mangleTemplateArgValue(QualType T, const APValue &V, TplArgKind, + void mangleTemplateArgValue(QualType T, const APValue &V, bool WithScalarType = false); void mangleObjCProtocol(const ObjCProtocolDecl *PD); @@ -1089,7 +1088,7 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(GlobalDecl GD, if (const auto *TPO = dyn_cast<TemplateParamObjectDecl>(ND)) { Out << "?__N"; mangleTemplateArgValue(TPO->getType().getUnqualifiedType(), - TPO->getValue(), TplArgKind::ClassNTTP); + TPO->getValue()); break; } @@ -1605,22 +1604,6 @@ void MicrosoftCXXNameMangler::mangleTemplateArgs( } } -/// If value V (with type T) represents a decayed pointer to the first element -/// of an array, return that array. -static ValueDecl *getAsArrayToPointerDecayedDecl(QualType T, const APValue &V) { - // Must be a pointer... - if (!T->isPointerType() || !V.isLValue() || !V.hasLValuePath() || - !V.getLValueBase()) - return nullptr; - // ... to element 0 of an array. - QualType BaseT = V.getLValueBase().getType(); - if (!BaseT->isArrayType() || V.getLValuePath().size() != 1 || - V.getLValuePath()[0].getAsArrayIndex() != 0) - return nullptr; - return const_cast<ValueDecl *>( - V.getLValueBase().dyn_cast<const ValueDecl *>()); -} - void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD, const TemplateArgument &TA, const NamedDecl *Parm) { @@ -1686,7 +1669,7 @@ void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD, Out << "$"; auto *TPO = cast<TemplateParamObjectDecl>(ND); mangleTemplateArgValue(TPO->getType().getUnqualifiedType(), - TPO->getValue(), TplArgKind::ClassNTTP); + TPO->getValue()); } else { mangle(ND, "$1?"); } @@ -1729,27 +1712,6 @@ void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD, cast<NonTypeTemplateParmDecl>(Parm), T); break; } - case TemplateArgument::StructuralValue: - if (ValueDecl *D = getAsArrayToPointerDecayedDecl( - TA.getStructuralValueType(), TA.getAsStructuralValue())) { - // Mangle the result of array-to-pointer decay as if it were a reference - // to the original declaration, to match MSVC's behavior. This can result - // in mangling collisions in some cases! - return mangleTemplateArg( - TD, TemplateArgument(D, TA.getStructuralValueType()), Parm); - } - Out << "$"; - if (cast<NonTypeTemplateParmDecl>(Parm) - ->getType() - ->getContainedDeducedType()) { - Out << "M"; - mangleType(TA.getNonTypeTemplateArgumentType(), SourceRange(), QMM_Drop); - } - mangleTemplateArgValue(TA.getStructuralValueType(), - TA.getAsStructuralValue(), - TplArgKind::StructuralValue, - /*WithScalarType=*/false); - break; case TemplateArgument::Expression: mangleExpression(TA.getAsExpr(), cast<NonTypeTemplateParmDecl>(Parm)); break; @@ -1792,7 +1754,6 @@ void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD, void MicrosoftCXXNameMangler::mangleTemplateArgValue(QualType T, const APValue &V, - TplArgKind TAK, bool WithScalarType) { switch (V.getKind()) { case APValue::None: @@ -1845,7 +1806,7 @@ void MicrosoftCXXNameMangler::mangleTemplateArgValue(QualType T, break; } } else { - if (TAK == TplArgKind::ClassNTTP && T->isPointerType()) + if (T->isPointerType()) Out << "5"; SmallVector<char, 2> EntryTypes; @@ -1889,12 +1850,12 @@ void MicrosoftCXXNameMangler::mangleTemplateArgValue(QualType T, auto *VD = Base.dyn_cast<const ValueDecl*>(); if (!VD) break; - Out << (TAK == TplArgKind::ClassNTTP ? 'E' : '1'); + Out << "E"; mangle(VD); for (const std::function<void()> &Mangler : EntryManglers) Mangler(); - if (TAK == TplArgKind::ClassNTTP && T->isPointerType()) + if (T->isPointerType()) Out << '@'; } @@ -1908,18 +1869,11 @@ void MicrosoftCXXNameMangler::mangleTemplateArgValue(QualType T, const CXXRecordDecl *RD = T->castAs<MemberPointerType>()->getMostRecentCXXRecordDecl(); const ValueDecl *D = V.getMemberPointerDecl(); - if (TAK == TplArgKind::ClassNTTP) { - if (T->isMemberDataPointerType()) - mangleMemberDataPointerInClassNTTP(RD, D); - else - mangleMemberFunctionPointerInClassNTTP(RD, - cast_or_null<CXXMethodDecl>(D)); - } else { - if (T->isMemberDataPointerType()) - mangleMemberDataPointer(RD, D, ""); - else - mangleMemberFunctionPointer(RD, cast_or_null<CXXMethodDecl>(D), ""); - } + if (T->isMemberDataPointerType()) + mangleMemberDataPointerInClassNTTP(RD, D); + else + mangleMemberFunctionPointerInClassNTTP(RD, + cast_or_null<CXXMethodDecl>(D)); return; } @@ -1931,11 +1885,11 @@ void MicrosoftCXXNameMangler::mangleTemplateArgValue(QualType T, unsigned BaseIndex = 0; for (const CXXBaseSpecifier &B : RD->bases()) - mangleTemplateArgValue(B.getType(), V.getStructBase(BaseIndex++), TAK); + mangleTemplateArgValue(B.getType(), V.getStructBase(BaseIndex++)); for (const FieldDecl *FD : RD->fields()) if (!FD->isUnnamedBitfield()) mangleTemplateArgValue(FD->getType(), - V.getStructField(FD->getFieldIndex()), TAK, + V.getStructField(FD->getFieldIndex()), /*WithScalarType*/ true); Out << '@'; return; @@ -1946,7 +1900,7 @@ void MicrosoftCXXNameMangler::mangleTemplateArgValue(QualType T, mangleType(T, SourceRange(), QMM_Escape); if (const FieldDecl *FD = V.getUnionField()) { mangleUnqualifiedName(FD); - mangleTemplateArgValue(FD->getType(), V.getUnionValue(), TAK); + mangleTemplateArgValue(FD->getType(), V.getUnionValue()); } Out << '@'; return; @@ -1978,7 +1932,7 @@ void MicrosoftCXXNameMangler::mangleTemplateArgValue(QualType T, const APValue &ElemV = I < V.getArrayInitializedElts() ? V.getArrayInitializedElt(I) : V.getArrayFiller(); - mangleTemplateArgValue(ElemT, ElemV, TAK); + mangleTemplateArgValue(ElemT, ElemV); Out << '@'; } Out << '@'; @@ -1995,7 +1949,7 @@ void MicrosoftCXXNameMangler::mangleTemplateArgValue(QualType T, mangleType(ElemT, SourceRange(), QMM_Escape); for (unsigned I = 0, N = V.getVectorLength(); I != N; ++I) { const APValue &ElemV = V.getVectorElt(I); - mangleTemplateArgValue(ElemT, ElemV, TAK); + mangleTemplateArgValue(ElemT, ElemV); Out << '@'; } Out << "@@"; diff --git a/clang/lib/AST/ODRHash.cpp b/clang/lib/AST/ODRHash.cpp index 5b98646a..c5aa91a 100644 --- a/clang/lib/AST/ODRHash.cpp +++ b/clang/lib/AST/ODRHash.cpp @@ -180,10 +180,6 @@ void ODRHash::AddTemplateArgument(TemplateArgument TA) { TA.getAsIntegral().Profile(ID); break; } - case TemplateArgument::StructuralValue: - AddQualType(TA.getStructuralValueType()); - AddStructuralValue(TA.getAsStructuralValue()); - break; case TemplateArgument::Template: case TemplateArgument::TemplateExpansion: AddTemplateName(TA.getAsTemplateOrTemplatePattern()); @@ -1300,66 +1296,3 @@ void ODRHash::AddQualType(QualType T) { void ODRHash::AddBoolean(bool Value) { Bools.push_back(Value); } - -void ODRHash::AddStructuralValue(const APValue &Value) { - ID.AddInteger(Value.getKind()); - - // 'APValue::Profile' uses pointer values to make hash for LValue and - // MemberPointer, but they differ from one compiler invocation to another. - // So, handle them explicitly here. - - switch (Value.getKind()) { - case APValue::LValue: { - const APValue::LValueBase &Base = Value.getLValueBase(); - if (!Base) { - ID.AddInteger(Value.getLValueOffset().getQuantity()); - break; - } - - assert(Base.is<const ValueDecl *>()); - AddDecl(Base.get<const ValueDecl *>()); - ID.AddInteger(Value.getLValueOffset().getQuantity()); - - bool OnePastTheEnd = Value.isLValueOnePastTheEnd(); - if (Value.hasLValuePath()) { - QualType TypeSoFar = Base.getType(); - for (APValue::LValuePathEntry E : Value.getLValuePath()) { - if (const auto *AT = TypeSoFar->getAsArrayTypeUnsafe()) { - if (const auto *CAT = dyn_cast<ConstantArrayType>(AT)) - OnePastTheEnd |= CAT->getSize() == E.getAsArrayIndex(); - TypeSoFar = AT->getElementType(); - } else { - const Decl *D = E.getAsBaseOrMember().getPointer(); - if (const auto *FD = dyn_cast<FieldDecl>(D)) { - if (FD->getParent()->isUnion()) - ID.AddInteger(FD->getFieldIndex()); - TypeSoFar = FD->getType(); - } else { - TypeSoFar = - D->getASTContext().getRecordType(cast<CXXRecordDecl>(D)); - } - } - } - } - unsigned Val = 0; - if (Value.isNullPointer()) - Val |= 1 << 0; - if (OnePastTheEnd) - Val |= 1 << 1; - if (Value.hasLValuePath()) - Val |= 1 << 2; - ID.AddInteger(Val); - break; - } - case APValue::MemberPointer: { - const ValueDecl *D = Value.getMemberPointerDecl(); - assert(D); - AddDecl(D); - ID.AddInteger( - D->getASTContext().getMemberPointerPathAdjustment(Value).getQuantity()); - break; - } - default: - Value.Profile(ID); - } -} diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index dd0838e..d7b980a 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -2416,12 +2416,6 @@ void StmtProfiler::VisitTemplateArgument(const TemplateArgument &Arg) { Arg.getAsIntegral().Profile(ID); break; - case TemplateArgument::StructuralValue: - VisitType(Arg.getStructuralValueType()); - // FIXME: Do we need to recursively decompose this ourselves? - Arg.getAsStructuralValue().Profile(ID); - break; - case TemplateArgument::Expression: Visit(Arg.getAsExpr()); break; diff --git a/clang/lib/AST/TemplateBase.cpp b/clang/lib/AST/TemplateBase.cpp index 2bdbeb0..2ec0b2cc 100644 --- a/clang/lib/AST/TemplateBase.cpp +++ b/clang/lib/AST/TemplateBase.cpp @@ -161,25 +161,8 @@ static bool needsAmpersandOnTemplateArg(QualType paramType, QualType argType) { // TemplateArgument Implementation //===----------------------------------------------------------------------===// -void TemplateArgument::initFromType(QualType T, bool IsNullPtr, - bool IsDefaulted) { - TypeOrValue.Kind = IsNullPtr ? NullPtr : Type; - TypeOrValue.IsDefaulted = IsDefaulted; - TypeOrValue.V = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr()); -} - -void TemplateArgument::initFromDeclaration(ValueDecl *D, QualType QT, - bool IsDefaulted) { - assert(D && "Expected decl"); - DeclArg.Kind = Declaration; - DeclArg.IsDefaulted = IsDefaulted; - DeclArg.QT = QT.getAsOpaquePtr(); - DeclArg.D = D; -} - -void TemplateArgument::initFromIntegral(const ASTContext &Ctx, - const llvm::APSInt &Value, - QualType Type, bool IsDefaulted) { +TemplateArgument::TemplateArgument(ASTContext &Ctx, const llvm::APSInt &Value, + QualType Type, bool IsDefaulted) { Integer.Kind = Integral; Integer.IsDefaulted = IsDefaulted; // Copy the APSInt value into our decomposed form. @@ -198,56 +181,6 @@ void TemplateArgument::initFromIntegral(const ASTContext &Ctx, Integer.Type = Type.getAsOpaquePtr(); } -void TemplateArgument::initFromStructural(const ASTContext &Ctx, QualType Type, - const APValue &V, bool IsDefaulted) { - Value.Kind = StructuralValue; - Value.IsDefaulted = IsDefaulted; - Value.Value = new (Ctx) APValue(V); - Ctx.addDestruction(Value.Value); - Value.Type = Type.getAsOpaquePtr(); -} - -TemplateArgument::TemplateArgument(const ASTContext &Ctx, - const llvm::APSInt &Value, QualType Type, - bool IsDefaulted) { - initFromIntegral(Ctx, Value, Type, IsDefaulted); -} - -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 'structural' representation. - return nullptr; -} - -TemplateArgument::TemplateArgument(const ASTContext &Ctx, QualType Type, - const APValue &V, bool IsDefaulted) { - if (Type->isIntegralOrEnumerationType() && V.isInt()) - initFromIntegral(Ctx, V.getInt(), Type, IsDefaulted); - else if ((V.isLValue() && V.isNullPointer()) || - (V.isMemberPointer() && !V.getMemberPointerDecl())) - initFromType(Type, /*isNullPtr=*/true, IsDefaulted); - else if (const ValueDecl *VD = getAsSimpleValueDeclRef(Ctx, Type, V)) - // FIXME: The Declaration form should expose a const ValueDecl*. - initFromDeclaration(const_cast<ValueDecl *>(VD), Type, IsDefaulted); - else - initFromStructural(Ctx, Type, V, IsDefaulted); -} - TemplateArgument TemplateArgument::CreatePackCopy(ASTContext &Context, ArrayRef<TemplateArgument> Args) { @@ -288,7 +221,6 @@ TemplateArgumentDependence TemplateArgument::getDependence() const { case NullPtr: case Integral: - case StructuralValue: return TemplateArgumentDependence::None; case Expression: @@ -319,7 +251,6 @@ bool TemplateArgument::isPackExpansion() const { case Null: case Declaration: case Integral: - case StructuralValue: case Pack: case Template: case NullPtr: @@ -370,9 +301,6 @@ QualType TemplateArgument::getNonTypeTemplateArgumentType() const { case TemplateArgument::NullPtr: return getNullPtrType(); - - case TemplateArgument::StructuralValue: - return getStructuralValueType(); } llvm_unreachable("Invalid TemplateArgument Kind!"); @@ -406,13 +334,8 @@ void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID, break; case Integral: - getIntegralType().Profile(ID); getAsIntegral().Profile(ID); - break; - - case StructuralValue: - getStructuralValueType().Profile(ID); - getAsStructuralValue().Profile(ID); + getIntegralType().Profile(ID); break; case Expression: @@ -449,16 +372,6 @@ bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const { return getIntegralType() == Other.getIntegralType() && getAsIntegral() == Other.getAsIntegral(); - case StructuralValue: { - if (getStructuralValueType() != Other.getStructuralValueType()) - return false; - - llvm::FoldingSetNodeID A, B; - getAsStructuralValue().Profile(A); - Other.getAsStructuralValue().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) @@ -485,7 +398,6 @@ TemplateArgument TemplateArgument::getPackExpansionPattern() const { case Declaration: case Integral: - case StructuralValue: case Pack: case Null: case Template: @@ -528,10 +440,6 @@ void TemplateArgument::print(const PrintingPolicy &Policy, raw_ostream &Out, break; } - case StructuralValue: - getAsStructuralValue().printPretty(Out, Policy, getStructuralValueType()); - break; - case NullPtr: // FIXME: Include the type if it's not obvious from the context. Out << "nullptr"; @@ -615,9 +523,6 @@ SourceRange TemplateArgumentLoc::getSourceRange() const { case TemplateArgument::Integral: return getSourceIntegralExpression()->getSourceRange(); - case TemplateArgument::StructuralValue: - return getSourceStructuralValueExpression()->getSourceRange(); - case TemplateArgument::Pack: case TemplateArgument::Null: return SourceRange(); @@ -646,18 +551,6 @@ static const T &DiagTemplateArg(const T &DB, const TemplateArgument &Arg) { case TemplateArgument::Integral: return DB << toString(Arg.getAsIntegral(), 10); - case TemplateArgument::StructuralValue: { - // FIXME: We're guessing at LangOptions! - SmallString<32> Str; - llvm::raw_svector_ostream OS(Str); - LangOptions LangOpts; - LangOpts.CPlusPlus = true; - PrintingPolicy Policy(LangOpts); - Arg.getAsStructuralValue().printPretty(OS, Policy, - Arg.getStructuralValueType()); - return DB << OS.str(); - } - case TemplateArgument::Template: return DB << Arg.getAsTemplate(); diff --git a/clang/lib/AST/TypeLoc.cpp b/clang/lib/AST/TypeLoc.cpp index 66732bb..e12b9b5 100644 --- a/clang/lib/AST/TypeLoc.cpp +++ b/clang/lib/AST/TypeLoc.cpp @@ -586,7 +586,6 @@ void TemplateSpecializationTypeLoc::initializeArgLocs( case TemplateArgument::Integral: case TemplateArgument::Declaration: case TemplateArgument::NullPtr: - case TemplateArgument::StructuralValue: ArgInfos[i] = TemplateArgumentLocInfo(); break; diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 0f3f684..c5b96f9 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -2201,14 +2201,6 @@ CGDebugInfo::CollectTemplateParams(std::optional<TemplateArgs> OArgs, TemplateParams.push_back(DBuilder.createTemplateValueParameter( TheCU, Name, TTy, defaultParameter, V)); } break; - case TemplateArgument::StructuralValue: { - QualType T = TA.getStructuralValueType(); - llvm::DIType *TTy = getOrCreateType(T, Unit); - llvm::Constant *V = ConstantEmitter(CGM).emitAbstract( - SourceLocation(), TA.getAsStructuralValue(), T); - TemplateParams.push_back(DBuilder.createTemplateValueParameter( - TheCU, Name, TTy, defaultParameter, V)); - } break; case TemplateArgument::Template: { std::string QualName; llvm::raw_string_ostream OS(QualName); @@ -5409,8 +5401,6 @@ std::string CGDebugInfo::GetName(const Decl *D, bool Qualified) const { // feasible some day. return TA.getAsIntegral().getBitWidth() <= 64 && IsReconstitutableType(TA.getIntegralType()); - case TemplateArgument::StructuralValue: - return false; case TemplateArgument::Type: return IsReconstitutableType(TA.getAsType()); default: diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index c5f6b6d..d12e85b 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -1516,14 +1516,6 @@ LValue CodeGenFunction::EmitLValue(const Expr *E, return LV; } -static QualType getConstantExprReferredType(const FullExpr *E, - const ASTContext &Ctx) { - const Expr *SE = E->getSubExpr()->IgnoreImplicit(); - if (isa<OpaqueValueExpr>(SE)) - return SE->getType(); - return cast<CallExpr>(SE)->getCallReturnType(Ctx)->getPointeeType(); -} - LValue CodeGenFunction::EmitLValueHelper(const Expr *E, KnownNonNull_t IsKnownNonNull) { ApplyDebugLocation DL(*this, E); @@ -1562,7 +1554,9 @@ LValue CodeGenFunction::EmitLValueHelper(const Expr *E, case Expr::ConstantExprClass: { const ConstantExpr *CE = cast<ConstantExpr>(E); if (llvm::Value *Result = ConstantEmitter(*this).tryEmitConstantExpr(CE)) { - QualType RetType = getConstantExprReferredType(CE, getContext()); + QualType RetType = cast<CallExpr>(CE->getSubExpr()->IgnoreImplicit()) + ->getCallReturnType(getContext()) + ->getPointeeType(); return MakeNaturalAlignAddrLValue(Result, RetType); } return EmitLValue(cast<ConstantExpr>(E)->getSubExpr(), IsKnownNonNull); diff --git a/clang/lib/Index/USRGeneration.cpp b/clang/lib/Index/USRGeneration.cpp index 5acc861..fb936d9 100644 --- a/clang/lib/Index/USRGeneration.cpp +++ b/clang/lib/Index/USRGeneration.cpp @@ -12,7 +12,6 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/DeclVisitor.h" -#include "clang/AST/ODRHash.h" #include "clang/Basic/FileManager.h" #include "clang/Lex/PreprocessingRecord.h" #include "llvm/Support/Path.h" @@ -1052,15 +1051,6 @@ void USRGenerator::VisitTemplateArgument(const TemplateArgument &Arg) { VisitType(Arg.getIntegralType()); Out << Arg.getAsIntegral(); break; - - case TemplateArgument::StructuralValue: { - Out << 'S'; - VisitType(Arg.getStructuralValueType()); - ODRHash Hash{}; - Hash.AddStructuralValue(Arg.getAsStructuralValue()); - Out << Hash.CalculateHash(); - break; - } } } diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index 02b1a04..996f8b5 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -2982,7 +2982,6 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, case TemplateArgument::Integral: case TemplateArgument::Expression: case TemplateArgument::NullPtr: - case TemplateArgument::StructuralValue: // [Note: non-type template arguments do not contribute to the set of // associated namespaces. ] break; diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 03087889..c532f40 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -6217,15 +6217,7 @@ Sema::EvaluateConvertedConstantExpression(Expr *E, QualType T, APValue &Value, if (Notes.empty()) { // It's a constant expression. - Expr *E = Result.get(); - if (const auto *CE = dyn_cast<ConstantExpr>(E)) { - // We expect a ConstantExpr to have a value associated with it - // by this point. - assert(CE->getResultStorageKind() != ConstantResultStorageKind::None && - "ConstantExpr has no value associated with it"); - } else { - E = ConstantExpr::Create(Context, Result.get(), Value); - } + Expr *E = ConstantExpr::Create(Context, Result.get(), Value); if (!PreNarrowingValue.isAbsent()) Value = std::move(PreNarrowingValue); return E; diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 9bfa71d..839d508 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -4427,7 +4427,6 @@ static bool isTemplateArgumentTemplateParameter( case TemplateArgument::NullPtr: case TemplateArgument::Integral: case TemplateArgument::Declaration: - case TemplateArgument::StructuralValue: case TemplateArgument::Pack: case TemplateArgument::TemplateExpansion: return false; @@ -5759,7 +5758,6 @@ bool Sema::CheckTemplateArgument( case TemplateArgument::Declaration: case TemplateArgument::Integral: - case TemplateArgument::StructuralValue: case TemplateArgument::NullPtr: // We've already checked this template argument, so just copy // it to the list of converted arguments. @@ -5914,10 +5912,11 @@ bool Sema::CheckTemplateArgument( return true; case TemplateArgument::Declaration: + llvm_unreachable("Declaration argument with template template parameter"); case TemplateArgument::Integral: - case TemplateArgument::StructuralValue: + 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"); @@ -7412,9 +7411,44 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, if (ArgResult.isInvalid()) return ExprError(); - // 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()); + SugaredConverted = TemplateArgument(ParamType, /*isNullPtr=*/true); + CanonicalConverted = TemplateArgument(CanonParamType, /*isNullPtr=*/true); + break; + case APValue::Indeterminate: + llvm_unreachable("result of constant evaluation should be initialized"); + break; + case APValue::Int: + assert(ParamType->isIntegralOrEnumerationType()); + SugaredConverted = TemplateArgument(Context, Value.getInt(), ParamType); + CanonicalConverted = + 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()); + SugaredConverted = VD ? TemplateArgument(VD, ParamType) + : TemplateArgument(ParamType, /*isNullPtr=*/true); + CanonicalConverted = + VD ? TemplateArgument(cast<ValueDecl>(VD->getCanonicalDecl()), + 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() || @@ -7432,7 +7466,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 && @@ -7450,13 +7485,37 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, "null reference should not be a constant expression"); assert((!VD || !ParamType->isNullPtrType()) && "non-null value of type nullptr_t?"); - } - if (Value.isAddrLabelDiff()) + SugaredConverted = VD ? TemplateArgument(VD, ParamType) + : TemplateArgument(ParamType, /*isNullPtr=*/true); + CanonicalConverted = + VD ? TemplateArgument(cast<ValueDecl>(VD->getCanonicalDecl()), + CanonParamType) + : TemplateArgument(CanonParamType, /*isNullPtr=*/true); + break; + } + case APValue::Struct: + case APValue::Union: { + // Get or create the corresponding template parameter object. + TemplateParamObjectDecl *D = + Context.getTemplateParamObjectDecl(ParamType, Value); + SugaredConverted = TemplateArgument(D, ParamType); + CanonicalConverted = + TemplateArgument(D->getCanonicalDecl(), 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; + } - SugaredConverted = TemplateArgument(Context, ParamType, Value); - CanonicalConverted = TemplateArgument(Context, CanonParamType, Value); return ArgResult.get(); } @@ -8040,9 +8099,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 @@ -8058,7 +8120,7 @@ static Expr *BuildExpressionFromIntegralTemplateArgumentValue( CharacterLiteralKind Kind; if (T->isWideCharType()) Kind = CharacterLiteralKind::Wide; - else if (T->isChar8Type() && S.getLangOpts().Char8) + else if (T->isChar8Type() && getLangOpts().Char8) Kind = CharacterLiteralKind::UTF8; else if (T->isChar16Type()) Kind = CharacterLiteralKind::UTF16; @@ -8067,133 +8129,29 @@ static Expr *BuildExpressionFromIntegralTemplateArgumentValue( else Kind = CharacterLiteralKind::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 = CXXBoolLiteralExpr::Create(S.Context, Int.getBoolValue(), T, Loc); + E = CXXBoolLiteralExpr::Create(Context, 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_PRValue, CK_IntegralCast, E, - nullptr, S.CurFPFeatureOverrides(), - S.Context.getTrivialTypeSourceInfo(OrigT, Loc), + E = CStyleCastExpr::Create(Context, OrigT, VK_PRValue, 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: - llvm_unreachable("Unexpected APValue kind."); - 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_PRValue; - 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); - } - llvm_unreachable("Unhandled APValue::ValueKind enum"); -} - -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::StructuralValue: - return BuildExpressionFromNonTypeTemplateArgumentValue( - *this, Arg.getStructuralValueType(), Arg.getAsStructuralValue(), Loc); - } - llvm_unreachable("Unhandled TemplateArgument::ArgKind enum"); -} - /// Match two template parameters within template parameter lists. static bool MatchTemplateParameterKind( Sema &S, NamedDecl *New, diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index e9e7ab5b..015b0ab 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -268,16 +268,6 @@ checkDeducedTemplateArguments(ASTContext &Context, // All other combinations are incompatible. return DeducedTemplateArgument(); - case TemplateArgument::StructuralValue: - // If we deduced a value and a dependent expression, keep the value. - if (Y.getKind() == TemplateArgument::Expression || - (Y.getKind() == TemplateArgument::StructuralValue && - 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())) @@ -2310,45 +2300,27 @@ DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams, Info.SecondArg = A; return Sema::TDK_NonDeducedMismatch; - case TemplateArgument::StructuralValue: - if (A.getKind() == TemplateArgument::StructuralValue && - A.structurallyEquals(P)) - return Sema::TDK_Success; - - Info.FirstArg = P; - Info.SecondArg = A; - return Sema::TDK_NonDeducedMismatch; - case TemplateArgument::Expression: if (const NonTypeTemplateParmDecl *NTTP = getDeducedParameterFromExpr(Info, P.getAsExpr())) { - switch (A.getKind()) { - case TemplateArgument::Integral: - case TemplateArgument::Expression: - case TemplateArgument::StructuralValue: + if (A.getKind() == TemplateArgument::Integral) return DeduceNonTypeTemplateArgument( - S, TemplateParams, NTTP, DeducedTemplateArgument(A), - A.getNonTypeTemplateArgumentType(), Info, Deduced); - - case TemplateArgument::NullPtr: + S, TemplateParams, NTTP, A.getAsIntegral(), A.getIntegralType(), + /*ArrayBound=*/false, Info, Deduced); + if (A.getKind() == TemplateArgument::NullPtr) return DeduceNullPtrTemplateArgument(S, TemplateParams, NTTP, A.getNullPtrType(), Info, Deduced); - - case TemplateArgument::Declaration: + if (A.getKind() == TemplateArgument::Expression) + return DeduceNonTypeTemplateArgument(S, TemplateParams, NTTP, + A.getAsExpr(), Info, Deduced); + if (A.getKind() == TemplateArgument::Declaration) return DeduceNonTypeTemplateArgument( S, TemplateParams, NTTP, A.getAsDecl(), A.getParamTypeForDecl(), Info, Deduced); - case TemplateArgument::Null: - case TemplateArgument::Type: - case TemplateArgument::Template: - case TemplateArgument::TemplateExpansion: - case TemplateArgument::Pack: - Info.FirstArg = P; - Info.SecondArg = A; - return Sema::TDK_NonDeducedMismatch; - } - llvm_unreachable("Unknown template argument kind"); + Info.FirstArg = P; + Info.SecondArg = A; + return Sema::TDK_NonDeducedMismatch; } // Can't deduce anything, but that's okay. @@ -2533,9 +2505,6 @@ static bool isSameTemplateArg(ASTContext &Context, case TemplateArgument::Integral: return hasSameExtendedValue(X.getAsIntegral(), Y.getAsIntegral()); - case TemplateArgument::StructuralValue: - return X.structurallyEquals(Y); - case TemplateArgument::Expression: { llvm::FoldingSetNodeID XID, YID; X.getAsExpr()->Profile(XID, Context, true); @@ -2616,9 +2585,9 @@ Sema::getTrivialTemplateArgumentLoc(const TemplateArgument &Arg, E); } - case TemplateArgument::Integral: - case TemplateArgument::StructuralValue: { - Expr *E = BuildExpressionFromNonTypeTemplateArgument(Arg, Loc).get(); + case TemplateArgument::Integral: { + Expr *E = + BuildExpressionFromIntegralTemplateArgument(Arg, Loc).getAs<Expr>(); return TemplateArgumentLoc(TemplateArgument(E), E); } @@ -6480,8 +6449,11 @@ MarkUsedTemplateParameters(ASTContext &Ctx, case TemplateArgument::Null: case TemplateArgument::Integral: case TemplateArgument::Declaration: + break; + case TemplateArgument::NullPtr: - case TemplateArgument::StructuralValue: + MarkUsedTemplateParameters(Ctx, TemplateArg.getNullPtrType(), OnlyDeduced, + Depth, Used); break; case TemplateArgument::Type: diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index e12186d..fc80515 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -1975,8 +1975,9 @@ ExprResult TemplateInstantiator::transformNonTypeTemplateParmRef( } } else if (arg.getKind() == TemplateArgument::Declaration || arg.getKind() == TemplateArgument::NullPtr) { + ValueDecl *VD; if (arg.getKind() == TemplateArgument::Declaration) { - ValueDecl *VD = arg.getAsDecl(); + VD = arg.getAsDecl(); // Find the instantiation of the template argument. This is // required for nested templates. @@ -1984,20 +1985,21 @@ ExprResult TemplateInstantiator::transformNonTypeTemplateParmRef( getSema().FindInstantiatedDecl(loc, VD, TemplateArgs)); if (!VD) return ExprError(); + } else { + // Propagate NULL template argument. + 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()) diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp index 4a7872b..0f4e9e7f 100644 --- a/clang/lib/Sema/SemaTemplateVariadic.cpp +++ b/clang/lib/Sema/SemaTemplateVariadic.cpp @@ -1112,7 +1112,6 @@ TemplateArgumentLoc Sema::getTemplateArgumentPackExpansionPattern( case TemplateArgument::NullPtr: case TemplateArgument::Template: case TemplateArgument::Integral: - case TemplateArgument::StructuralValue: case TemplateArgument::Pack: case TemplateArgument::Null: return TemplateArgumentLoc(); @@ -1163,7 +1162,6 @@ std::optional<unsigned> Sema::getFullyPackExpandedSize(TemplateArgument Arg) { case TemplateArgument::NullPtr: case TemplateArgument::TemplateExpansion: case TemplateArgument::Integral: - case TemplateArgument::StructuralValue: case TemplateArgument::Pack: case TemplateArgument::Null: return std::nullopt; diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index e55e752..c217b08 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -3908,7 +3908,6 @@ public: case TemplateArgument::Null: case TemplateArgument::Integral: case TemplateArgument::Declaration: - case TemplateArgument::StructuralValue: case TemplateArgument::Pack: case TemplateArgument::TemplateExpansion: case TemplateArgument::NullPtr: @@ -4578,8 +4577,7 @@ bool TreeTransform<Derived>::TransformTemplateArgument( case TemplateArgument::Integral: case TemplateArgument::NullPtr: - case TemplateArgument::Declaration: - case TemplateArgument::StructuralValue: { + 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. @@ -4606,15 +4604,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::StructuralValue) - Output = TemplateArgumentLoc( - TemplateArgument(getSema().Context, NewT, Arg.getAsStructuralValue()), - TemplateArgumentLocInfo()); - else - llvm_unreachable("unexpected template argument kind"); return false; } diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index fecd94e..ec4de0c 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -7460,7 +7460,6 @@ ASTRecordReader::readTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind) { case TemplateArgument::Integral: case TemplateArgument::Declaration: case TemplateArgument::NullPtr: - case TemplateArgument::StructuralValue: case TemplateArgument::Pack: // FIXME: Is this right? return TemplateArgumentLocInfo(); diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 03bddfe0..a3fa99c 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -5609,7 +5609,6 @@ void ASTRecordWriter::AddTemplateArgumentLocInfo( case TemplateArgument::Integral: case TemplateArgument::Declaration: case TemplateArgument::NullPtr: - case TemplateArgument::StructuralValue: case TemplateArgument::Pack: // FIXME: Is this right? break; diff --git a/clang/test/CXX/drs/dr18xx.cpp b/clang/test/CXX/drs/dr18xx.cpp index 37ea450..f2c056e 100644 --- a/clang/test/CXX/drs/dr18xx.cpp +++ b/clang/test/CXX/drs/dr18xx.cpp @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -verify=expected,cxx98-14,cxx98 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors // RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify=expected,cxx98-14,cxx11-17,since-cxx11 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors // RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,cxx98-14,cxx11-17,since-cxx11,since-cxx14 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,since-cxx17,cxx11-17,since-cxx11,since-cxx14,cxx17 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,since-cxx17,cxx11-17,since-cxx11,since-cxx14 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors // RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,since-cxx17,since-cxx20,since-cxx11,since-cxx14 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors // RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,since-cxx17,since-cxx20,since-cxx11,since-cxx14 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors // RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,since-cxx17,since-cxx20,since-cxx11,since-cxx14 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors @@ -25,7 +25,7 @@ template <int &> struct S {}; // #dr1801-S S<i> V; // #dr1801-S-i // cxx98-14-error@-1 {{non-type template argument does not refer to any declaration}} // cxx98-14-note@#dr1801-S {{template parameter is declared here}} -// cxx17-error@#dr1801-S-i {{non-type template argument refers to subobject '.i'}} +// since-cxx17-error@#dr1801-S-i {{non-type template argument refers to subobject '.i'}} } namespace dr1802 { // dr1802: 3.1 diff --git a/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp b/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp index 7fce615..a17720c 100644 --- a/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp +++ b/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp @@ -200,9 +200,7 @@ namespace bad_args { // cxx17-note@-3 {{reinterpret_cast}} X0<__builtin_constant_p(0) ? (int*)1 : (int*)1> x0d; // precxx17-error@-1 {{non-type template argument '(int *)1' is invalid}} -#if __cplusplus == 201703L - // cxx17-error@-3 {{non-type template argument refers to subobject '(int *)1'}} -#endif + // cxx17-error@-2 {{non-type template argument refers to subobject '(int *)1'}} } #endif // CPP11ONLY diff --git a/clang/test/CodeGenCXX/mangle-ms-templates.cpp b/clang/test/CodeGenCXX/mangle-ms-templates.cpp index ec4250e..cefe1e0 100644 --- a/clang/test/CodeGenCXX/mangle-ms-templates.cpp +++ b/clang/test/CodeGenCXX/mangle-ms-templates.cpp @@ -2,21 +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 - -// Check that array-to-pointer decay is mangled as the underlying declaration. -extern const char arr[4] = "foo"; -template<const char*> struct Decay1 {}; -// CHECK: "?decay1@@3U?$Decay1@$1?arr@@3QBDB@@A" -Decay1<arr> decay1; -#if __cplusplus >= 201702L -// Note that this mangling approach can lead to collisions. -template<const void*> struct Decay2 {}; -// CXX20-X64: "?decay2a@@3U?$Decay2@$1?arr@@3QBDB@@A" -Decay2<(const void*)arr> decay2a; -// CXX20-X64: "?decay2b@@3U?$Decay2@$1?arr@@3QBDB@@A" -Decay2<(const void*)&arr> decay2b; -#endif template<typename T> class Class { @@ -342,36 +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>) {} - -struct S2 { - int arr[2][3]; - int i; - void fn(); -} s2; - -template<int&> struct TplSubobjectRef {}; -// CXX20-X64: define {{.*}} @"?f@@YAXU?$TplSubobjectRef@$CC61?s2@@3US2@@Aarr@@00@01@@@@Z"( -void f(TplSubobjectRef<s2.arr[1][2]>) {} -template<int*> struct TplSubobjectPtr {}; -// CXX20-X64: define {{.*}} @"?f@@YAXU?$TplSubobjectPtr@$CC61?s2@@3US2@@Aarr@@00@01@@@@Z"( -void f(TplSubobjectPtr<&s2.arr[1][2]>) {} - -struct Derived : S2 {}; - -template <int Derived::*> struct TplMemberPtr {}; -// CXX20-X64: define {{.*}} @"?f@@YAXU?$TplMemberPtr@$0BI@@@@Z"( -void f(TplMemberPtr<(int Derived::*)&S2::i>) {} -template <void (Derived::*)()> struct TplMemberFnPtr {}; -// CXX20-X64: define {{.*}} @"?f@@YAXU?$TplMemberFnPtr@$1?fn@S2@@QEAAXXZ@@@Z"( -void f(TplMemberFnPtr<(void (Derived::*)())&S2::fn>) {} - -#endif diff --git a/clang/test/CodeGenCXX/mangle-template.cpp b/clang/test/CodeGenCXX/mangle-template.cpp index a4cb227..8415bac 100644 --- a/clang/test/CodeGenCXX/mangle-template.cpp +++ b/clang/test/CodeGenCXX/mangle-template.cpp @@ -225,16 +225,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( @@ -254,24 +244,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>) {} @@ -281,17 +254,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 diff --git a/clang/test/CodeGenCXX/template-arguments.cpp b/clang/test/CodeGenCXX/template-arguments.cpp deleted file mode 100644 index 14a4549..0000000 --- a/clang/test/CodeGenCXX/template-arguments.cpp +++ /dev/null @@ -1,113 +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 noundef 1) -// CONST: @_Z5valueILi1EE = weak_odr {{.*}} i32 1, -template int value<1>; - -// CHECK: call {{.*}} @_Z2idIyET_S0_(i64 noundef -1) -// CONST: @_Z5valueILy18446744073709551615EE = weak_odr {{.*}} i64 -1, -template unsigned long long value<-1ULL>; - -// CHECK: call {{.*}} @_Z2idIfET_S0_(float noundef 1.000000e+00) -// CONST: @_Z5valueILf3f800000EE = weak_odr {{.*}} float 1.000000e+00, -template float value<1.0f>; -// CHECK: call {{.*}} @_Z2idIdET_S0_(double noundef 1.000000e+00) -// CONST: @_Z5valueILd3ff0000000000000EE = weak_odr {{.*}} double 1.000000e+00, -template double value<1.0>; - -enum E{ E1, E2}; - -// CHECK: call {{.*}} @_Z2idI1EET_S1_(i32 noundef 1) -// CONST: @_Z5valueIL1E1EE = weak_odr {{.*}} i32 1, -template E value<E2>; - -int n; -// CHECK: call {{.*}} @_Z2idIPiET_S1_(ptr noundef @n) -// CONST: @_Z5valueIXadL_Z1nEEE = weak_odr {{.*}} ptr @n, -template int *value<&n>; - -struct A { int a[3]; } a; -// CHECK: call {{.*}} @_Z2idIPiET_S1_(ptr noundef @a) -// CONST: @_Z5valueIXadsoiL_Z1aEEEE = weak_odr {{.*}} ptr @a, -template int *value<&a.a[0]>; -// CHECK: call {{.*}} @_Z2idIPiET_S1_(ptr noundef getelementptr (i8, ptr @a, i64 4)) -// CONST: @_Z5valueIXadsoiL_Z1aE4EEE = weak_odr {{.*}} ptr getelementptr (i8, ptr @a, i64 4), -template int *value<&a.a[1]>; -// CHECK: call {{.*}} @_Z2idIPiET_S1_(ptr noundef getelementptr (i8, ptr @a, i64 8)) -// CONST: @_Z5valueIXadsoiL_Z1aE8EEE = weak_odr {{.*}} ptr getelementptr (i8, ptr @a, i64 8), -template int *value<&a.a[2]>; -// CHECK: call {{.*}} @_Z2idIPiET_S1_(ptr noundef getelementptr (i8, ptr @a, i64 12)) -// CONST: @_Z5valueIXadsoiL_Z1aE12pEEE = weak_odr {{.*}} ptr getelementptr (i8, ptr @a, i64 12), -template int *value<&a.a[3]>; - -union U { - int x, y; - union { - int x, y; - } internal; -} u; - -// CHECK: call {{.*}} @_Z2idIPiET_S1_(ptr noundef @u) -// CONST: @_Z5valueIXadsoiL_Z1uE_EEE = weak_odr {{.*}} ptr @u, -template int *value<&u.x>; -// CHECK: call {{.*}} @_Z2idIPiET_S1_(ptr noundef @u) -// CONST: @_Z5valueIXadsoiL_Z1uE_0EEE = weak_odr {{.*}} ptr @u, -template int *value<&u.y>; -// CHECK: call {{.*}} @_Z2idIPiET_S1_(ptr noundef @u) -// CONST: @_Z5valueIXadsoiL_Z1uE_1_0EEE = weak_odr {{.*}} ptr @u, -template int *value<&u.internal.y>; - -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, -// CHECK: store i32 2, -// CHECK: load i64, -// CHECK: call {{.*}} @_Z2idICiET_S1_(i64 noundef % -// CONST: @_Z5valueIXtlCiLi1ELi2EEEE = weak_odr {{.*}} { i32, i32 } { i32 1, i32 2 }, -template _Complex int value<1 + 2j>; - -// CHECK: store float 1.000000e+00, -// CHECK: store float 2.000000e+00, -// CHECK: load <2 x float>, -// CHECK: call {{.*}} @_Z2idICfET_S1_(<2 x float> noundef % -// 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> noundef <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> noundef <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}>; - - -template <int& i> -void setByRef() { - i = 1; -} - -void callSetByRefWithSubobject() { - // CHECK: store i32 1, ptr getelementptr (i8, ptr @a, i64 4) - setByRef<a.a[1]>(); -} diff --git a/clang/test/Index/USR/structural-value-tpl-arg.cpp b/clang/test/Index/USR/structural-value-tpl-arg.cpp deleted file mode 100644 index 81300124..0000000 --- a/clang/test/Index/USR/structural-value-tpl-arg.cpp +++ /dev/null @@ -1,23 +0,0 @@ -// RUN: c-index-test -test-load-source-usrs local -std=c++20 -- %s | FileCheck %s - -// Check USRs of template specializations with structural NTTP values. - -template <auto> struct Tpl{}; - -struct { - int n; -} s; - -void fn1(Tpl<1.5>); -// CHECK: fn1#$@S@Tpl>#Sd[[#HASH:]]# -void fn2(Tpl<1.7>); -// CHECK-NOT: [[#HASH]] -void fn1(Tpl<1.5>) {} -// CHECK: fn1#$@S@Tpl>#Sd[[#HASH]]# - -void fn(Tpl<&s.n>); -// CHECK: #S*I[[#HASH:]]# -void fn(Tpl<(void*)&s.n>); -// CHECK: #S*v[[#HASH]]# -void fn(Tpl<&s.n>) {} -// CHECK: #S*I[[#HASH]]# diff --git a/clang/test/Modules/odr_hash.cpp b/clang/test/Modules/odr_hash.cpp index fa8b2c8..220ef76 100644 --- a/clang/test/Modules/odr_hash.cpp +++ b/clang/test/Modules/odr_hash.cpp @@ -13,8 +13,8 @@ // RUN: cat %s >> %t/Inputs/second.h // Test that each header can compile -// RUN: %clang_cc1 -fsyntax-only -x c++ -std=c++20 %t/Inputs/first.h -// RUN: %clang_cc1 -fsyntax-only -x c++ -std=c++20 %t/Inputs/second.h +// RUN: %clang_cc1 -fsyntax-only -x c++ -std=c++1z %t/Inputs/first.h +// RUN: %clang_cc1 -fsyntax-only -x c++ -std=c++1z %t/Inputs/second.h // Build module map file // RUN: echo "module FirstModule {" >> %t/Inputs/module.modulemap @@ -25,7 +25,7 @@ // RUN: echo "}" >> %t/Inputs/module.modulemap // Run test -// RUN: %clang_cc1 -triple x86_64-linux-gnu -x c++ -std=c++20 \ +// RUN: %clang_cc1 -triple x86_64-linux-gnu -x c++ -std=c++1z \ // RUN: -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache \ // RUN: -I%t/Inputs -verify %s @@ -2093,193 +2093,6 @@ struct S21 { S21 s21; #endif -#if defined(FIRST) -struct S22 { - template <double> void f(){}; - template <> void f<1.5>(){}; -}; -#elif defined(SECOND) -struct S22 { - template <double> void f(){}; - template <> void f<1.7>(){}; -}; -#else -S22 s22; -// expected-error@second.h:* {{'TemplateArgument::S22' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'f' with 1.700000e+00 for 1st template argument}} -// expected-note@first.h:* {{but in 'FirstModule' found method 'f' with 1.500000e+00 for 1st template argument}} -#endif - -#if defined(FIRST) -struct S23 { - template <double> void f(){}; - template <> void f<2.7>(){}; -}; -#elif defined(SECOND) -struct S23 { - template <double> void f(){}; - template <> void f<2.7>(){}; -}; -#else -S23 s23; -#endif - -#if defined(FIRST) || defined(SECOND) -struct Composite { - int n1[4]; - int n2[4]; -}; -extern Composite composite; -#endif - -#if defined(FIRST) -struct S24 { - template <int&> void f(){}; - template <> void f<composite.n1[1]>(){}; -}; -#elif defined(SECOND) -struct S24 { - template <int&> void f(){}; - template <> void f<composite.n1[2]>(){}; -}; -#else -S24 s24; -// expected-error@second.h:* {{'TemplateArgument::S24' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'f' with composite.n1[2] for 1st template argument}} -// expected-note@first.h:* {{but in 'FirstModule' found method 'f' with composite.n1[1] for 1st template argument}} -#endif - -#if defined(FIRST) || defined(SECOND) -struct S25 { - template <int&> void f(); - template <> void f<composite.n1[2]>(); -}; -#else -S25 s25; -#endif - -#if defined(FIRST) -struct S26 { - template <int*> void f(){}; - template <> void f<&composite.n1[4]>(){}; // Past-the-end pointer. -}; -#elif defined(SECOND) -struct S26 { - template <int*> void f(){}; - template <> void f<&composite.n2[0]>(){}; -}; -#else -S26 s26; -// expected-error@second.h:* {{'TemplateArgument::S26' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'f' with &composite.n2[0] for 1st template argument}} -// expected-note@first.h:* {{but in 'FirstModule' found method 'f' with &composite.n1[4] for 1st template argument}} -#endif - -#if defined(FIRST) || defined(SECOND) -union Union { - int i1; - int i2; -}; -extern Union u; -#endif - -#if defined(FIRST) -struct S27 { - template <int&> void f(){}; - template <> void f<u.i1>(){}; -}; -#elif defined(SECOND) -struct S27 { - template <int&> void f(){}; - template <> void f<u.i2>(){}; -}; -#else -S27 s27; -// expected-error@second.h:* {{'TemplateArgument::S27' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'f' with u.i2 for 1st template argument}} -// expected-note@first.h:* {{but in 'FirstModule' found method 'f' with u.i1 for 1st template argument}} -#endif - -#if defined(FIRST) || defined(SECOND) -struct S28 { - template <int&> void f(){}; - template <> void f<u.i1>(){}; -}; -#else -S28 s28; -#endif - -#if defined(FIRST) || defined(SECOND) -struct A { - int a; -}; -struct B : A {}; -struct C : A {}; -struct D : B, C {}; -#endif - -#if defined(FIRST) -struct S29 { - template <int D::*> void f(){}; - template <> void f<(int D::*)(int B::*)&A::a>(){}; -}; -#elif defined(SECOND) -struct S29 { - template <int D::*> void f(){}; - template <> void f<(int D::*)(int C::*)&A::a>(){}; -}; -#else -S29 s29; -// expected-error@second.h:* {{'TemplateArgument::S29' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'f' with &A::a for 1st template argument}} -// expected-note@first.h:* {{but in 'FirstModule' found method 'f' with &A::a for 1st template argument}} -#endif - -#if defined(FIRST) || defined(SECOND) -struct S30 { - template <int D::*> void f(){}; - template <> void f<(int D::*)(int B::*)&A::a>(){}; -}; -#else -S30 s30; -#endif - -#if defined(FIRST) -struct S31 { - template <auto*> void f(){}; - template <> void f<&composite.n1[2]>(){}; -}; -#elif defined(SECOND) -struct S31 { - template <auto*> void f(){}; - template <> void f<(void*)&composite.n1[2]>(){}; -}; -#else -S31 s31; -// expected-error@second.h:* {{'TemplateArgument::S31' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'f' with &composite.n1[2] for 1st template argument}} -// expected-note@first.h:* {{but in 'FirstModule' found method 'f' with &composite.n1[2] for 1st template argument}} -#endif - -#if defined(FIRST) -struct S32 { - template <int*> void f(){}; - template <> void f<__builtin_constant_p(0) ? (int*)1 : (int*)1>(){}; -}; -#elif defined(SECOND) -struct S32 { - template <int*> void f(){}; - template <> void f<__builtin_constant_p(0) ? (int*)2 : (int*)2>(){}; -}; -#else -S32 s32; -// expected-error@second.h:* {{'TemplateArgument::S32' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'f' with (int *)2 for 1st template argument}} -// expected-note@first.h:* {{but in 'FirstModule' found method 'f' with (int *)1 for 1st template argument}} -#endif - -#if defined(FIRST) || defined(SECOND) -struct S33 { - template <int*> void f(){}; - template <> void f<__builtin_constant_p(0) ? (int*)1 : (int*)1>(){}; -}; -#else -S33 s33; -#endif - #define DECLS \ OneClass<int> a; \ OneInt<1> b; \ diff --git a/clang/test/SemaCXX/warn-bool-conversion.cpp b/clang/test/SemaCXX/warn-bool-conversion.cpp index c81d52d..7b671c5 100644 --- a/clang/test/SemaCXX/warn-bool-conversion.cpp +++ b/clang/test/SemaCXX/warn-bool-conversion.cpp @@ -186,7 +186,6 @@ namespace macros { } } -#if __cplusplus < 201703L namespace Template { // FIXME: These cases should not warn. template<int *p> void f() { if (p) {} } // expected-warning 2{{will always evaluate to 'true'}} expected-cxx11-warning {{implicit conversion of nullptr}} @@ -206,4 +205,3 @@ namespace Template { #endif template void h<d>(); } -#endif // __cplusplus < 201703L diff --git a/clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp b/clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp index ae06055..b54b5a8 100644 --- a/clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp +++ b/clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp @@ -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 {{non-type template argument of pointer-to-member type}} 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 {{non-type template argument of pointer-to-member type}} // A case where we need to do auto-deduction, and check whether the // resulting dependent types match during partial ordering. These diff --git a/clang/test/SemaTemplate/temp_arg_nontype_cxx20.cpp b/clang/test/SemaTemplate/temp_arg_nontype_cxx20.cpp index b5b8cad..e345a1f 100644 --- a/clang/test/SemaTemplate/temp_arg_nontype_cxx20.cpp +++ b/clang/test/SemaTemplate/temp_arg_nontype_cxx20.cpp @@ -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 {{non-type template argument of type}} +using F1 = Float<2.0f / 2>; // FIXME expected-error {{non-type template argument of type}} struct S { int n[3]; } s; // expected-note 1+{{here}} union U { int a, b; } u; @@ -17,28 +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 IPn2 = IntPtr<&n + 2>; // expected-error {{not a constant expression}} expected-note {{cannot refer to element 2 of non-array object}} +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 IP2 = IntPtr<&s.n[2]>; -using IP2 = IntPtr<s.n + 2>; - -using IP3 = IntPtr<&s.n[3]>; -using IP3 = IntPtr<s.n + 3>; - -using IP5 = IntPtr<&s.n[5]>; // expected-error {{not a constant expression}} expected-note {{cannot refer to element 5 of array of 3 elements}} +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 {}; @@ -52,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 {{non-type template argument of type}} +using CI = ComplexInt<1 + 3i>; // FIXME: expected-error {{non-type template argument of type}} 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 {{non-type template argument of type}} +using CF = ComplexFloat<1.0f + 3.0fi>; // FIXME: expected-error {{non-type template argument of type}} namespace ClassNTTP { struct A { // expected-note 2{{candidate}} diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index b03ad60..00c0dff 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -1582,11 +1582,6 @@ bool CursorVisitor::VisitTemplateArgumentLoc(const TemplateArgumentLoc &TAL) { return Visit(MakeCXCursor(E, StmtParent, TU, RegionOfInterest)); return false; - case TemplateArgument::StructuralValue: - if (Expr *E = TAL.getSourceStructuralValueExpression()) - return Visit(MakeCXCursor(E, StmtParent, TU, RegionOfInterest)); - return false; - case TemplateArgument::NullPtr: if (Expr *E = TAL.getSourceNullPtrExpression()) return Visit(MakeCXCursor(E, StmtParent, TU, RegionOfInterest)); diff --git a/clang/tools/libclang/CXCursor.cpp b/clang/tools/libclang/CXCursor.cpp index 978adac..fd03c48 100644 --- a/clang/tools/libclang/CXCursor.cpp +++ b/clang/tools/libclang/CXCursor.cpp @@ -1466,9 +1466,6 @@ enum CXTemplateArgumentKind clang_Cursor_getTemplateArgumentKind(CXCursor C, return CXTemplateArgumentKind_NullPtr; case TemplateArgument::Integral: return CXTemplateArgumentKind_Integral; - case TemplateArgument::StructuralValue: - // FIXME: Expose these values. - return CXTemplateArgumentKind_Invalid; case TemplateArgument::Template: return CXTemplateArgumentKind_Template; case TemplateArgument::TemplateExpansion: diff --git a/clang/www/cxx_status.html b/clang/www/cxx_status.html index a48f35e..197726f 100755 --- a/clang/www/cxx_status.html +++ b/clang/www/cxx_status.html @@ -637,21 +637,13 @@ C++23, informally referred to as C++26.</p> </tr> <!-- Rapperswil papers --> <tr> - <td>Class types as non-type template parameters</td> + <td rowspan="2">Class types as non-type template parameters</td> <td><a href="https://wg21.link/p0732r2">P0732R2</a></td> - <td class="full" align="center">Clang 12</td> - </tr> - <tr> <!-- from Belfast --> - <td>Generalized non-type template parameters of scalar type</td> - <td><a href="https://wg21.link/p1907r1">P1907R1</a></td> - <td class="partial" align="center"> - <details> - <summary>Clang 18 (Partial)</summary> - Reference type template arguments referring to instantiation-dependent objects and subobjects - (i.e. declared inside a template but neither type- nor value-dependent) aren't fully supported. - </details> - </td> + <td rowspan="2" class="partial" align="center">Partial</td> </tr> + <tr> <!-- from Belfast --> + <td><a href="https://wg21.link/p1907r1">P1907R1</a></td> + </tr> <tr> <td>Destroying operator delete</td> <td><a href="https://wg21.link/p0722r3">P0722R3</a></td> diff --git a/lldb/include/lldb/lldb-enumerations.h b/lldb/include/lldb/lldb-enumerations.h index 392d333..ed1dec8 100644 --- a/lldb/include/lldb/lldb-enumerations.h +++ b/lldb/include/lldb/lldb-enumerations.h @@ -875,7 +875,6 @@ enum TemplateArgumentKind { eTemplateArgumentKindExpression, eTemplateArgumentKindPack, eTemplateArgumentKindNullPtr, - eTemplateArgumentKindStructuralValue, }; /// Type of match to be performed when looking for a formatter for a data type. diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp index 6f5ff10..ba37afb 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp @@ -7168,9 +7168,6 @@ TypeSystemClang::GetTemplateArgumentKind(lldb::opaque_compiler_type_t type, case clang::TemplateArgument::Pack: return eTemplateArgumentKindPack; - - case clang::TemplateArgument::StructuralValue: - return eTemplateArgumentKindStructuralValue; } llvm_unreachable("Unhandled clang::TemplateArgument::ArgKind"); } |